- // ==UserScript==
- // @name YouTube - Force rounded corners + tweaks included
- // @version 2025.02.10
- // @description This script forces the rounded version of the layout (which includes some fewer tweaks applied which also improves bugs).
- // @author Joey_JTS (original author: Magma_Craft)
- // @license MIT
- // @match *://www.youtube.com/*
- // @namespace https://greasyfork.org/en/users/933798
- // @icon https://www.youtube.com/favicon.ico
- // @run-at document-start
- // @grant none
- // ==/UserScript==
-
- // Attributes to remove from <html>
- const ATTRS = [
- "darker-dark-theme",
- "darker-dark-theme-deprecate"
- ];
-
- // Regular config keys.
- const CONFIGS = {
- BUTTON_REWORK: true
- }
-
- // Experiment flags.
- const EXPFLAGS = {
- /* Force rounded corners */
- web_button_rework: true,
- web_button_rework_with_live: true,
- web_darker_dark_theme: true,
- web_filled_subscribed_button: true,
- web_guide_ui_refresh: true,
- web_modern_ads: true,
- web_modern_buttons: true,
- web_modern_chips: true,
- web_modern_dialogs: true,
- web_modern_playlists: true,
- web_modern_subscribe: true,
- web_rounded_containers: true,
- web_rounded_thumbnails: true,
- web_searchbar_style: "rounded_corner_borders_light_btn",
- web_segmented_like_dislike_button: true,
- web_sheets_ui_refresh: true,
- web_snackbar_ui_refresh: true,
- /* Force rounded watch layout and few tweaks to be included (such as disabling the useless 'watch grid' UI */
- kevlar_watch_metadata_refresh: true,
- kevlar_watch_metadata_refresh_attached_subscribe: true,
- kevlar_watch_metadata_refresh_clickable_description: true,
- kevlar_watch_metadata_refresh_compact_view_count: true,
- kevlar_watch_metadata_refresh_description_info_dedicated_line: true,
- kevlar_watch_metadata_refresh_description_inline_expander: true,
- kevlar_watch_metadata_refresh_description_primary_color: true,
- kevlar_watch_metadata_refresh_for_live_killswitch: true,
- kevlar_watch_metadata_refresh_full_width_description: true,
- kevlar_watch_metadata_refresh_narrower_item_wrap: true,
- kevlar_watch_metadata_refresh_relative_date: true,
- kevlar_watch_metadata_refresh_top_aligned_actions: true,
- kevlar_watch_modern_metapanel: true,
- kevlar_watch_modern_panels: true,
- kevlar_watch_panel_height_matches_player: true,
- kevlar_watch_grid: false,
- kevlar_watch_grid_hide_chips: false,
- small_avatars_for_comments: false,
- small_avatars_for_comments_ep: false,
- web_watch_compact_comments: false,
- web_watch_compact_comments_ep: false,
- web_watch_theater_chat: false,
- web_watch_theater_fixed_chat: false,
- live_chat_over_engagement_panels: false,
- live_chat_scaled_height: false,
- live_chat_smaller_min_height: false,
- wn_grid_max_item_width: 0,
- wn_grid_min_item_width: 0,
- kevlar_set_internal_player_size: false,
- kevlar_watch_flexy_metadata_height: "136",
- kevlar_watch_max_player_width: "1280",
- web_watch_rounded_player_large: false,
- kevlar_watch_cinematics: false,
- desktop_delay_player_resizing: false,
- /* Additional tweaks (which includes reverting new UI changes and disabling animations except for both web_modern_tabs and web_enable_youtab configs ) */
- kevlar_refresh_on_theme_change: false,
- smartimation_background: false,
- web_animated_actions: false,
- web_animated_like: false,
- web_animated_like_lazy_load: false,
- enable_channel_page_header_profile_section: false,
- kevlar_modern_sd_v2: false,
- web_modern_collections_v2: false,
- web_modern_tabs: false,
- web_modern_typography: true,
- web_enable_youtab: true
- }
-
- // Player flags
- // !!! USE STRINGS FOR VALUES !!!
- // For example: "true" instead of true
- const PLYRFLAGS = {
- web_rounded_containers: "true",
- web_rounded_thumbnails: "true"
- }
-
- class YTP {
- static observer = new MutationObserver(this.onNewScript);
-
- static _config = {};
-
- static isObject(item) {
- return (item && typeof item === "object" && !Array.isArray(item));
- }
-
- static mergeDeep(target, ...sources) {
- if (!sources.length) return target;
- const source = sources.shift();
-
- if (this.isObject(target) && this.isObject(source)) {
- for (const key in source) {
- if (this.isObject(source[key])) {
- if (!target[key]) Object.assign(target, { [key]: {} });
- this.mergeDeep(target[key], source[key]);
- } else {
- Object.assign(target, { [key]: source[key] });
- }
- }
- }
-
- return this.mergeDeep(target, ...sources);
- }
-
-
- static onNewScript(mutations) {
- for (var mut of mutations) {
- for (var node of mut.addedNodes) {
- YTP.bruteforce();
- }
- }
- }
-
- static start() {
- this.observer.observe(document, {childList: true, subtree: true});
- }
-
- static stop() {
- this.observer.disconnect();
- }
-
- static bruteforce() {
- if (!window.yt) return;
- if (!window.yt.config_) return;
-
- this.mergeDeep(window.yt.config_, this._config);
- }
-
- static setCfg(name, value) {
- this._config[name] = value;
- }
-
- static setCfgMulti(configs) {
- this.mergeDeep(this._config, configs);
- }
-
- static setExp(name, value) {
- if (!("EXPERIMENT_FLAGS" in this._config)) this._config.EXPERIMENT_FLAGS = {};
-
- this._config.EXPERIMENT_FLAGS[name] = value;
- }
-
- static setExpMulti(exps) {
- if (!("EXPERIMENT_FLAGS" in this._config)) this._config.EXPERIMENT_FLAGS = {};
-
- this.mergeDeep(this._config.EXPERIMENT_FLAGS, exps);
- }
-
- static decodePlyrFlags(flags) {
- var obj = {},
- dflags = flags.split("&");
-
- for (var i = 0; i < dflags.length; i++) {
- var dflag = dflags[i].split("=");
- obj[dflag[0]] = dflag[1];
- }
-
- return obj;
- }
-
- static encodePlyrFlags(flags) {
- var keys = Object.keys(flags),
- response = "";
-
- for (var i = 0; i < keys.length; i++) {
- if (i > 0) {
- response += "&";
- }
- response += keys[i] + "=" + flags[keys[i]];
- }
-
- return response;
- }
-
- static setPlyrFlags(flags) {
- if (!window.yt) return;
- if (!window.yt.config_) return;
- if (!window.yt.config_.WEB_PLAYER_CONTEXT_CONFIGS) return;
- var conCfgs = window.yt.config_.WEB_PLAYER_CONTEXT_CONFIGS;
- if (!("WEB_PLAYER_CONTEXT_CONFIGS" in this._config)) this._config.WEB_PLAYER_CONTEXT_CONFIGS = {};
-
- for (var cfg in conCfgs) {
- var dflags = this.decodePlyrFlags(conCfgs[cfg].serializedExperimentFlags);
- this.mergeDeep(dflags, flags);
- this._config.WEB_PLAYER_CONTEXT_CONFIGS[cfg] = {
- serializedExperimentFlags: this.encodePlyrFlags(dflags)
- }
- }
- }
- }
-
- window.addEventListener("yt-page-data-updated", function tmp() {
- YTP.stop();
- for (i = 0; i < ATTRS.length; i++) {
- document.getElementsByTagName("html")[0].removeAttribute(ATTRS[i]);
- }
- window.removeEventListener("yt-page-date-updated", tmp);
- });
-
- YTP.start();
-
- YTP.setCfgMulti(CONFIGS);
- YTP.setExpMulti(EXPFLAGS);
- YTP.setPlyrFlags(PLYRFLAGS);
-
- function $(q) {
- return document.querySelector(q);
- }
-
- (function() {
- let css = `
- /* Add rounded corners under the player */
- div#ytp-id-17.ytp-popup.ytp-settings-menu,
- div#ytp-id-18.ytp-popup.ytp-settings-menu {
- border-radius: 12px !important
- }
-
- div.branding-context-container-inner.ytp-rounded-branding-context {
- border-radius: 8px !important
- }
-
- .iv-card {
- border-radius: 8px !important
- }
-
- .ytp-ad-overlay-container.ytp-overlay-ad .ytp-ad-overlay-image img, .ytp-ad-overlay-container.ytp-overlay-ad .ytp-ad-text-overlay, .ytp-ad-overlay-container.ytp-overlay-ad .ytp-ad-enhanced-overlay {
- border-radius: 8px !important
- }
-
- .ytp-tooltip.ytp-text-detail.ytp-preview .ytp-tooltip-bg {
- border-top-left-radius: 12px !important;
- border-bottom-left-radius: 12px !important
- }
-
- .ytp-tooltip.ytp-text-detail.ytp-preview {
- border-radius: 12px !important
- }
-
- .ytp-ce-video.ytp-ce-medium, .ytp-ce-playlist.ytp-ce-medium, .ytp-ce-medium .ytp-ce-expanding-overlay-background {
- border-radius: 8px !important
- }
-
- .ytp-autonav-endscreen-upnext-thumbnail {
- border-radius: 8px !important
- }
-
- .ytp-autonav-endscreen-upnext-button {
- border-radius: 18px !important
- }
-
- .ytp-videowall-still-image {
- border-radius: 8px !important
- }
-
- .ytp-sb-subscribe, .ytp-sb-unsubscribe {
- border-radius: 18px !important
- }
-
- /* Watch page tweaks (including the 'Revert video list' CSS) */
- ytd-watch-flexy[rounded-player-large]:not([fullscreen]):not([theater]) #ytd-player.ytd-watch-flexy {
- border-radius: 0px !important
- }
-
- #actions.ytd-watch-metadata {
- min-width: auto !important
- }
-
- ytd-watch-flexy[default-layout][reduced-top-margin] #primary.ytd-watch-flexy, ytd-watch-flexy[default-layout][reduced-top-margin] #secondary.ytd-watch-flexy {
- padding-top: var(--ytd-margin-6x) !important
- }
-
- ytd-watch-metadata[title-headline-xs] h1.ytd-watch-metadata, ytd-watch-metadata[title-headline-m] h1.ytd-watch-metadata {
- font-family: "YouTube Sans","Roboto",sans-serif !important;
- font-weight: 600 !important;
- font-size: 2rem !important;
- line-height: 2.8rem !important
- }
-
- ytd-comments-header-renderer[compact-header] #title.ytd-comments-header-renderer {
- margin-bottom: 24px !important
- }
-
- ytd-comments-header-renderer[modern-typography][compact-header] .count-text.ytd-comments-header-renderer {
- font-size: 2rem !important;
- line-height: 2.8rem !important;
- font-weight: 700 !important;
- max-height: 2.8rem !important;
- display: flex !important;
- flex-direction: row-reverse !important
- }
-
- [compact-header] .count-text.ytd-comments-header-renderer {
- display: flex !important;
- flex-direction: row-reverse !important
- }
-
- [compact-header] .count-text.ytd-comments-header-renderer span {
- margin-right: 6px !important
- }
-
- ytd-watch-flexy #comment-teaser.ytd-watch-metadata {
- display: none
- }
-
- ytd-watch-flexy ytd-rich-item-renderer[rendered-from-rich-grid] {
- --ytd-rich-item-row-usable-width: 100% !important
- }
-
- ytd-watch-flexy ytd-rich-item-renderer[rendered-from-rich-grid][is-in-first-column] {
- margin-left: 0
- }
-
- ytd-watch-flexy ytd-rich-item-renderer ytd-menu-renderer .ytd-menu-renderer[style-target=button] {
- width: 24px !important;
- height: 24px !important
- }
-
- ytd-watch-flexy #dismissible.ytd-rich-grid-media {
- flex-direction: row
- }
-
- ytd-watch-flexy #attached-survey.ytd-rich-grid-media,
- ytd-watch-flexy #avatar-link.ytd-rich-grid-media,
- ytd-watch-flexy #avatar-container.ytd-rich-grid-media {
- display: none
- }
-
- ytd-watch-flexy ytd-thumbnail.ytd-rich-grid-media,
- ytd-watch-flexy ytd-playlist-thumbnail.ytd-rich-grid-media {
- margin-right: 8px;
- height: 94px;
- width: 168px
- }
-
- ytd-watch-flexy ytd-thumbnail[size=large] a.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large]:before,
- ytd-watch-flexy ytd-thumbnail[size=large][large-margin] a.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large][large-margin]:before {
- border-radius: 8px
- }
-
- ytd-watch-flexy ytd-thumbnail[size=large][large-margin] ytd-thumbnail-overlay-time-status-renderer.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large][large-margin] ytd-thumbnail-overlay-button-renderer.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large][large-margin] ytd-thumbnail-overlay-toggle-button-renderer.ytd-thumbnail,
- ytd-watch-flexy ytd-thumbnail[size=large] ytd-thumbnail-overlay-time-status-renderer.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large] ytd-thumbnail-overlay-button-renderer.ytd-thumbnail, ytd-watch-flexy ytd-thumbnail[size=large] ytd-thumbnail-overlay-toggle-button-renderer.ytd-thumbnail {
- margin: 4px
- }
-
- ytd-watch-flexy ytd-rich-item-renderer,
- ytd-watch-flexy ytd-rich-grid-row #contents.ytd-rich-grid-row {
- margin: 0
- }
-
- ytd-watch-flexy ytd-rich-item-renderer[reduced-bottom-margin] {
- margin-top: 8px;
- margin-bottom: 0
- }
-
- ytd-watch-flexy ytd-rich-grid-renderer[reduced-top-margin] #contents.ytd-rich-grid-renderer {
- padding-top: 0px
- }
-
- ytd-watch-flexy ytd-rich-grid-media {
- margin-bottom: 8px
- }
-
- ytd-watch-flexy #details.ytd-rich-grid-media {
- width: 100%;
- min-width: 0
- }
-
- ytd-watch-flexy ytd-video-meta-block[rich-meta] #metadata-line.ytd-video-meta-block,
- ytd-watch-flexy #channel-name.ytd-video-meta-block {
- font-family: "Roboto", "Arial", sans-serif;
- font-size: 1.2rem;
- line-height: 1.8rem;
- font-weight: 400
- }
-
- ytd-watch-flexy #video-title.ytd-rich-grid-media {
- margin: 0 0 4px 0;
- display: block;
- font-family: "Roboto", "Arial", sans-serif;
- font-size: 1.4rem;
- line-height: 2rem;
- font-weight: 500;
- overflow: hidden;
- display: block;
- max-height: 4rem;
- -webkit-line-clamp: 2;
- display: box;
- display: -webkit-box;
- -webkit-box-orient: vertical;
- text-overflow: ellipsis;
- white-space: normal
- }
-
- ytd-watch-flexy h3.ytd-rich-grid-media {
- margin: 0
- }
-
- ytd-watch-flexy .title-badge.ytd-rich-grid-media, ytd-watch-flexy .video-badge.ytd-rich-grid-media {
- margin-top: 0
- }
-
- ytd-watch-flexy ytd-rich-section-renderer.style-scope.ytd-rich-grid-renderer {
- display: none
- }
-
- ytd-watch-flexy ytd-rich-grid-renderer[hide-chips-bar] ytd-feed-filter-chip-bar-renderer.ytd-rich-grid-renderer, ytd-watch-flexy ytd-rich-grid-renderer[hide-chips-bar-on-watch] ytd-feed-filter-chip-bar-renderer.ytd-rich-grid-renderer, ytd-watch-flexy ytd-rich-grid-renderer[hide-chips-bar-on-home] #header.ytd-rich-grid-renderer ytd-feed-filter-chip-bar-renderer.ytd-rich-grid-renderer {
- display: flex;
- height: 51px;
- margin-bottom: 8px
- }
-
- ytd-watch-flexy #chips-wrapper.ytd-feed-filter-chip-bar-renderer {
- position: relative;
- top: 0
- }
-
- ytd-watch-flexy ytd-feed-filter-chip-bar-renderer[fluid-width] #chips-content.ytd-feed-filter-chip-bar-renderer {
- padding: 0
- }
-
- ytd-watch-flexy yt-chip-cloud-chip-renderer.ytd-feed-filter-chip-bar-renderer, ytd-watch-flexy yt-chip-cloud-chip-renderer.ytd-feed-filter-chip-bar-renderer:first-of-type {
- margin: 8px;
- margin-left: 0
- }
-
- ytd-watch-flexy ytd-button-renderer.ytd-feed-filter-chip-bar-renderer {
- margin: 0;
- padding: 0 8px
- }
-
- /* More tweaks to be applied */
- #buttons.ytd-c4-tabbed-header-renderer {
- flex-direction: row-reverse !important
- }
-
- ytd-channel-tagline-renderer {
- display: block !important;
- padding: 0 !important
- }
-
- #content.ytd-channel-tagline-renderer::before {
- content: "More about this channel";
- font-weight: 500 !important
- }
-
- #content.ytd-channel-tagline-renderer {
- max-width: 162px !important
- }
-
- ytd-browse[page-subtype="channels"] .page-header-view-model-wiz__page-header-description {
- margin-top: 0px !important;
- max-width: 236px !important
- }
-
- ytd-browse[page-subtype="channels"] yt-description-preview-view-model .truncated-text-wiz__truncated-text-content:before {
- content: "More about this channel > ";
- font-weight: 500 !important
- }
-
- ytd-browse[page-subtype="channels"] button.truncated-text-wiz__absolute-button {
- display: none !important
- }
-
- #avatar.ytd-c4-tabbed-header-renderer, .yt-spec-avatar-shape__button--button-giant {
- width: 80px !important;
- height: 80px !important;
- margin: 0 24px 0 0 !important;
- flex: none !important;
- overflow: hidden !important
- }
-
- .yt-spec-avatar-shape__button--button-giant, .yt-spec-avatar-shape--avatar-size-giant, .yt-spec-avatar-shape__button--button-extra-extra-large, .yt-spec-avatar-shape--avatar-size-extra-extra-large {
- width: 80px !important;
- height: 80px !important;
- margin-right: 0px !important;
- }
-
- #avatar-editor.ytd-c4-tabbed-header-renderer {
- --ytd-channel-avatar-editor-size: 80px !important
- }
-
- #channel-name.ytd-c4-tabbed-header-renderer {
- margin-bottom: 0 !important
- }
-
- #channel-header-container.ytd-c4-tabbed-header-renderer {
- padding-top: 0 !important;
- align-items: center !important
- }
-
- #inner-header-container.ytd-c4-tabbed-header-renderer {
- margin-top: 0 !important;
- align-items: center !important
- }
-
- .yt-content-metadata-view-model-wiz--inline .yt-content-metadata-view-model-wiz__metadata-row {
- margin-top: 0 !important
- }
-
- yt-formatted-string#channel-pronouns.style-scope.ytd-c4-tabbed-header-renderer, #videos-count {
- display: none !important
- }
-
- .meta-item.ytd-c4-tabbed-header-renderer {
- display: block !important
- }
-
- div#channel-header-links.style-scope.ytd-c4-tabbed-header-renderer,
- .page-header-view-model-wiz__page-header-attribution {
- display: none !important
- }
-
- ytd-c4-tabbed-header-renderer[use-page-header-style] #channel-name.ytd-c4-tabbed-header-renderer,
- [page-subtype="channels"] .page-header-view-model-wiz__page-header-title--page-header-title-large {
- font-size: 2.4em !important;
- font-weight: 400 !important;
- line-height: var(--yt-channel-title-line-height, 3rem) !important;
- margin: 0 !important
- }
-
- span.delimiter.style-scope.ytd-c4-tabbed-header-renderer, .yt-content-metadata-view-model-wiz__delimiter {
- display: none !important
- }
-
- div#meta.style-scope.ytd-c4-tabbed-header-renderer {
- width: auto !important
- }
-
- ytd-c4-tabbed-header-renderer[use-page-header-style] #inner-header-container.ytd-c4-tabbed-header-renderer {
- flex-direction: row !important
- }
-
- div.page-header-banner.style-scope.ytd-c4-tabbed-header-renderer {
- margin-left: 0px !important;
- margin-right: 8px !important;
- border-radius: 0px !important
- }
-
- [has-inset-banner] #page-header-banner.ytd-tabbed-page-header {
- padding-left: 0 !important;
- padding-right: 0 !important
- }
-
- ytd-c4-tabbed-header-renderer[use-page-header-style] .page-header-banner.ytd-c4-tabbed-header-renderer,
- .yt-image-banner-view-model-wiz--inset {
- border-radius: 0px !important
- }
-
- .yt-content-metadata-view-model-wiz__metadata-text {
- margin-right: 8px !important
- }
-
- .yt-content-metadata-view-model-wiz__metadata-text, .truncated-text-wiz, .truncated-text-wiz__absolute-button {
- font-size: 1.4rem !important
- }
-
- .yt-tab-shape-wiz {
- padding: 0 32px !important;
- margin-right: 0 !important
- }
-
- .yt-tab-shape-wiz__tab {
- font-size: 14px !important;
- font-weight: 500 !important;
- letter-spacing: var(--ytd-tab-system-letter-spacing) !important;
- text-transform: uppercase !important
- }
-
- .yt-tab-group-shape-wiz__slider {
- display: none !important
- }
-
- ytd-browse[page-subtype="channels"] ytd-tabbed-page-header .yt-content-metadata-view-model-wiz__metadata-row--metadata-row-inline {
- display: flex
- }
-
- ytd-browse[page-subtype="channels"] ytd-tabbed-page-header .yt-content-metadata-view-model-wiz__metadata-text:last-of-type {
- display: none
- }
-
- ytd-browse[page-subtype="channels"] ytd-tabbed-page-header .yt-content-metadata-view-model-wiz__metadata-text:first-of-type {
- display: flex
- }
-
- ytd-browse[page-subtype="channels"] .yt-flexible-actions-view-model-wiz--inline {
- flex-direction: row-reverse
- }
-
- ytd-browse[page-subtype="channels"] .page-header-view-model-wiz__page-header-flexible-actions {
- margin-top: -56px
- }
-
- ytd-browse[page-subtype="channels"] .yt-flexible-actions-view-model-wiz__action-row {
- margin-top: 60px
- }
-
- ytd-browse[page-subtype="channels"] .yt-flexible-actions-view-model-wiz__action {
- padding-right: 8px
- }
-
- ytd-browse[page-subtype="channels"] span.yt-core-attributed-string--link-inherit-color {
- font-weight: 400 !important
- }
-
- ytd-browse[page-subtype="channels"] .page-header-view-model-wiz__page-header-headline-info {
- margin-bottom: 8px
- }
-
- #title.ytd-playlist-sidebar-primary-info-renderer,
- ytd-inline-form-renderer[component-style=INLINE_FORM_STYLE_TITLE] #text-displayed.ytd-inline-form-renderer {
- font-family: YouTube Sans !important;
- font-weight: 700 !important
- }
-
- ytd-comments-header-renderer[use-space-between] #title.ytd-comments-header-renderer {
- justify-content: start !important
- }
-
- #panel-button.ytd-comments-header-renderer {
- margin-left: 32px;
- margin-right: 8px
- }
-
- #panel-button .yt-spec-button-shape-next__icon {
- margin-right: 0
- }
-
- #panel-button .yt-spec-button-shape-next--size-m {
- padding-left: 12px;
- padding-right: 6px
- }
-
- #panel-button .yt-spec-button-shape-next__button-text-content {
- display: none !important
- }
-
- #panel-button .yt-spec-button-shape-next__icon path {
- d: path("M10 3H17V7H10V3ZM20 0H0V14H20V0ZM1 1H19V13H1V1Z");
- transform: scale(1.20)
- }
-
- div#end.style-scope.ytd-masthead .yt-spec-button-shape-next--size-m[aria-label="Create"] {
- height: 40px !important;
- border-radius: 50px !important;
- color: var(--yt-spec-icon-active-other) !important;
- background-color: transparent !important
- }
-
- div#end.style-scope.ytd-masthead .yt-spec-button-shape-next--size-m.yt-spec-button-shape-next--icon-leading[aria-label="Create"] .yt-spec-button-shape-next__button-text-content {
- display: none !important
- }
-
- div#end.style-scope.ytd-masthead .yt-spec-button-shape-next--size-m.yt-spec-button-shape-next--icon-leading[aria-label="Create"] .yt-spec-button-shape-next__icon {
- margin-left: -8px !important;
- margin-right: -8px !important
- }
-
- div#end.style-scope.ytd-masthead .yt-spec-button-shape-next--size-m.yt-spec-button-shape-next--icon-leading[aria-label="Create"] path {
- d: path("M14 13h-3v3H9v-3H6v-2h3V8h2v3h3v2zm3-7H3v12h14v-6.39l4 1.83V8.56l-4 1.83V6m1-1v3.83L22 7v8l-4-1.83V19H2V5h16z")
- }
-
- div#end.style-scope.ytd-masthead .yt-spec-icon-badge-shape--style-overlay.yt-spec-icon-badge-shape--type-cart-refresh .yt-spec-icon-badge-shape__badge {
- color: #fff !important
- }
-
- ytd-feed-filter-chip-bar-renderer[frosted-glass] ytd-button-renderer.ytd-feed-filter-chip-bar-renderer {
- background-color: transparent !important
- }
-
- ytd-feed-filter-chip-bar-renderer[frosted-glass] #left-arrow-button.ytd-feed-filter-chip-bar-renderer,
- ytd-feed-filter-chip-bar-renderer[frosted-glass] #right-arrow-button.ytd-feed-filter-chip-bar-renderer {
- background-color: var(--yt-spec-base-background) !important
- }
-
- ytd-feed-filter-chip-bar-renderer[frosted-glass] #left-arrow.ytd-feed-filter-chip-bar-renderer:after {
- background: linear-gradient(to right, var(--yt-spec-base-background) 20%, rgba(255, 255, 255, 0) 80%) !important
- }
-
- ytd-feed-filter-chip-bar-renderer[frosted-glass] #right-arrow.ytd-feed-filter-chip-bar-renderer:before {
- background: linear-gradient(to left, var(--yt-spec-base-background) 20%, rgba(255, 255, 255, 0) 80%) !important
- }
-
- ytd-masthead[frosted-glass=with-chipbar] #background.ytd-masthead,
- ytd-masthead[frosted-glass=without-chipbar] #background.ytd-masthead,
- ytd-app[frosted-glass-mode=with-chipbar] #frosted-glass.ytd-app,
- ytd-app[frosted-glass-mode=without-chipbar] #frosted-glass.ytd-app {
- background: var(--yt-spec-base-background) !important;
- backdrop-filter: none !important
- }
-
- .ytp-cairo-refresh-signature-moments .ytp-play-progress, ytd-thumbnail-overlay-resume-playback-renderer[enable-refresh-signature-moments-web] #progress.ytd-thumbnail-overlay-resume-playback-renderer, .YtThumbnailOverlayProgressBarHostWatchedProgressBarSegmentModern, .YtChapteredProgressBarChapteredPlayerBarChapterRefresh, .YtChapteredProgressBarChapteredPlayerBarFillRefresh, .YtProgressBarLineProgressBarPlayedRefresh, yt-page-navigation-progress[enable-refresh-signature-moments-web] #progress.yt-page-navigation-progress, ytd-progress-bar-line[enable-refresh-signature-moments-web] .progress-bar-played.ytd-progress-bar-line, #logo-icon > .yt-spec-icon-shape.yt-icon.style-scope.yt-icon-shape > div > svg > g:first-of-type > path:first-of-type {
- background: #ff0000 !important
- }
-
- [d*="M18 4v15.06l-5.42-3.87-.58-.42-.58.42L6 19.06V4h12m1-1H5v18l7-5 7 5V3z"] {
- d: path("M22 13h-4v4h-2v-4h-4v-2h4V7h2v4h4v2zm-8-6H2v1h12V7zM2 12h8v-1H2v1zm0 4h8v-1H2v1z")
- }`;
- if (typeof GM_addStyle !== "undefined") {
- GM_addStyle(css);
- } else {
- let styleNode = document.createElement("style");
- styleNode.appendChild(document.createTextNode(css));
- (document.querySelector("head") || document.documentElement).appendChild(styleNode);
- }
- })();
-
- // Integrate 'YouTube Video Resize Fix' script (special thanks to CY Fung)
- /* jshint esversion:8 */
-
- ((__CONTEXT01__) => {
- 'use strict';
-
-
- const win = this instanceof Window ? this : window;
-
- // Create a unique key for the script and check if it is already running
- const hkey_script = 'ahceihvpbosz';
- if (win[hkey_script]) throw new Error('Duplicated Userscript Calling'); // avoid duplicated scripting
- win[hkey_script] = true;
-
- const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0);
- const indr = o => insp(o).$ || o.$ || 0;
-
- /** @type {globalThis.PromiseConstructor} */
- const Promise = (async () => { })().constructor; // YouTube hacks Promise in WaterFox Classic and "Promise.resolve(0)" nevers resolve.
- const cleanContext = async (win) => {
- const waitFn = requestAnimationFrame; // shall have been binded to window
- try {
- let mx = 16; // MAX TRIAL
- const frameId = 'vanillajs-iframe-v1'
- let frame = document.getElementById(frameId);
- let removeIframeFn = null;
- if (!frame) {
- frame = document.createElement('iframe');
- frame.id = frameId;
- const blobURL = typeof webkitCancelAnimationFrame === 'function' && typeof kagi === 'undefined' ? (frame.src = URL.createObjectURL(new Blob([], { type: 'text/html' }))) : null; // avoid Brave Crash
- frame.sandbox = 'allow-same-origin'; // script cannot be run inside iframe but API can be obtained from iframe
- let n = document.createElement('noscript'); // wrap into NOSCRPIT to avoid reflow (layouting)
- n.appendChild(frame);
- while (!document.documentElement && mx-- > 0) await new Promise(waitFn); // requestAnimationFrame here could get modified by YouTube engine
- const root = document.documentElement;
- root.appendChild(n); // throw error if root is null due to exceeding MAX TRIAL
- if (blobURL) Promise.resolve().then(() => URL.revokeObjectURL(blobURL));
-
- removeIframeFn = (setTimeout) => {
- const removeIframeOnDocumentReady = (e) => {
- e && win.removeEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
- e = n;
- n = win = removeIframeFn = 0;
- setTimeout ? setTimeout(() => e.remove(), 200) : e.remove();
- }
- if (!setTimeout || document.readyState !== 'loading') {
- removeIframeOnDocumentReady();
- } else {
- win.addEventListener("DOMContentLoaded", removeIframeOnDocumentReady, false);
- }
- }
- }
- while (!frame.contentWindow && mx-- > 0) await new Promise(waitFn);
- const fc = frame.contentWindow;
- if (!fc) throw "window is not found."; // throw error if root is null due to exceeding MAX TRIAL
- try {
- const { requestAnimationFrame, setTimeout, clearTimeout } = fc;
- const res = { requestAnimationFrame, setTimeout, clearTimeout };
- for (let k in res) res[k] = res[k].bind(win); // necessary
- if (removeIframeFn) Promise.resolve(res.setTimeout).then(removeIframeFn);
- return res;
- } catch (e) {
- if (removeIframeFn) removeIframeFn();
- return null;
- }
- } catch (e) {
- console.warn(e);
- return null;
- }
- };
-
- const isWatchPageURL = (url) => {
- url = url || location;
- return location.pathname === '/watch' || location.pathname.startsWith('/live/')
- };
-
- cleanContext(win).then(__CONTEXT02__ => {
- if (!__CONTEXT02__) return null;
-
- const { ResizeObserver } = __CONTEXT01__;
- const { requestAnimationFrame, setTimeout, clearTimeout } = __CONTEXT02__;
- const elements = {};
- let rid1 = 0;
- let rid2 = 0;
- /** @type {MutationObserver | null} */
- let attrObserver = null;
- /** @type {ResizeObserver | null} */
- let resizeObserver = null;
- let isHTMLAttrApplied = false;
- const core = {
- begin() {
- document.addEventListener('yt-player-updated', core.hanlder, true);
- document.addEventListener('ytd-navigate-finish', core.hanlder, true);
- },
- hanlder: () => {
- rid1++;
- if (rid1 > 1e9) rid1 = 9;
- const tid = rid1;
- requestAnimationFrame(() => {
- if (tid !== rid1) return;
- core.runner();
- })
- },
- async runner() {
- if (!location.href.startsWith('https://www.youtube.com/')) return;
- if (!isWatchPageURL()) return;
-
- elements.ytdFlexy = document.querySelector('ytd-watch-flexy');
- elements.video = document.querySelector('ytd-watch-flexy #movie_player video, ytd-watch-flexy #movie_player audio.video-stream.html5-main-video');
- if (elements.ytdFlexy && elements.video) { } else return;
- elements.moviePlayer = elements.video.closest('#movie_player');
- if (!elements.moviePlayer) return;
-
- // resize Video
- let { ytdFlexy } = elements;
- if (!ytdFlexy.ElYTL) {
- ytdFlexy.ElYTL = 1;
- const ytdFlexyCnt = insp(ytdFlexy);
- if (typeof ytdFlexyCnt.calculateNormalPlayerSize_ === 'function') {
- ytdFlexyCnt.calculateNormalPlayerSize_ = core.resizeFunc(ytdFlexyCnt.calculateNormalPlayerSize_, 1);
- } else {
- console.warn('ytdFlexyCnt.calculateNormalPlayerSize_ is not a function.')
- }
- if (typeof ytdFlexyCnt.calculateCurrentPlayerSize_ === 'function') {
- ytdFlexyCnt.calculateCurrentPlayerSize_ = core.resizeFunc(ytdFlexyCnt.calculateCurrentPlayerSize_, 0);
- } else {
- console.warn('ytdFlexyCnt.calculateCurrentPlayerSize_ is not a function.')
- }
- }
- ytdFlexy = null;
-
- // when video is fetched
- elements.video.removeEventListener('canplay', core.triggerResizeDelayed, false);
- elements.video.addEventListener('canplay', core.triggerResizeDelayed, false);
-
- // when video is resized
- if (resizeObserver) {
- resizeObserver.disconnect();
- resizeObserver = null;
- }
- if (typeof ResizeObserver === 'function') {
- resizeObserver = new ResizeObserver(core.triggerResizeDelayed);
- resizeObserver.observe(elements.moviePlayer);
- }
-
- // MutationObserver:[collapsed] @ ytd-live-chat-frame#chat
- if (attrObserver) {
- attrObserver.takeRecords();
- attrObserver.disconnect();
- attrObserver = null;
- }
- let chat = document.querySelector('ytd-watch-flexy ytd-live-chat-frame#chat');
- if (chat) {
- // resize due to DOM update
- attrObserver = new MutationObserver(core.triggerResizeDelayed);
- attrObserver.observe(chat, { attributes: true, attributeFilter: ["collapsed"] });
- chat = null;
- }
-
- // resize on idle
- Promise.resolve().then(core.triggerResizeDelayed);
- },
- resizeFunc(originalFunc, kb) {
- return function () {
- rid2++;
- if (!isHTMLAttrApplied) {
- isHTMLAttrApplied = true;
- Promise.resolve(0).then(() => {
- document.documentElement.classList.add('youtube-video-resize-fix');
- }).catch(console.warn);
- }
- if (document.fullscreenElement === null) {
-
- // calculateCurrentPlayerSize_ shall be always return NaN to make correct positioning of toolbars
- if (!kb) return { width: NaN, height: NaN };
-
- let ret = core.calculateSize();
- if (ret.height > 0 && ret.width > 0) {
- return ret;
- }
- }
- return originalFunc.apply(this, arguments);
- }
- },
- calculateSize_() {
- const { moviePlayer, video } = elements;
- const rect1 = { width: video.videoWidth, height: video.videoHeight }; // native values independent of css rules
- if (rect1.width > 0 && rect1.height > 0) {
- const rect2 = moviePlayer.getBoundingClientRect();
- const aspectRatio = rect1.width / rect1.height;
- let h2 = rect2.width / aspectRatio;
- let w2 = rect2.height * aspectRatio;
- return { rect2, h2, w2 };
- }
- return null;
- },
- calculateSize() {
- let rs = core.calculateSize_();
- if (!rs) return { width: NaN, height: NaN };
- const { rect2, h2, w2 } = rs;
- if (h2 > rect2.height) {
- return { width: w2, height: rect2.height };
- } else {
- return { width: rect2.width, height: h2 };
- }
- },
- triggerResizeDelayed: () => {
- rid2++;
- if (rid2 > 1e9) rid2 = 9;
- const tid = rid2;
- requestAnimationFrame(() => {
- if (tid !== rid2) return;
- const { ytdFlexy } = elements;
- let r = false;
- const ytdFlexyCnt = insp(ytdFlexy);
- const windowSize_ = ytdFlexyCnt.windowSize_;
- if (windowSize_ && typeof ytdFlexyCnt.onWindowResized_ === 'function') {
- try {
- ytdFlexyCnt.onWindowResized_(windowSize_);
- r = true;
- } catch (e) { }
- }
- if (!r) window.dispatchEvent(new Event('resize'));
- })
- }
- };
- core.begin();
-
-
-
-
-
-
-
- // YouTube Watch Page Reflect (WPR)
-
-
-
- // This script enhances the functionality of YouTube pages by reflecting changes in the page state.
-
- (async function youTubeWPR() {
-
- let checkPageVisibilityChanged = false;
-
- // A WeakSet to keep track of elements being monitored for mutations.
- const monitorWeakSet = new WeakSet();
-
- /** @type {globalThis.PromiseConstructor} */
- const Promise = (async () => { })().constructor;
-
- // Function to reflect the current state of the YouTube page.
- async function _reflect() {
- await Promise.resolve();
-
- const youtubeWpr = document.documentElement.getAttribute("youtube-wpr");
- let s = '';
-
- // Check if the current page is the video watch page.
- if (isWatchPageURL()) {
- let watch = document.querySelector("ytd-watch-flexy");
- let chat = document.querySelector("ytd-live-chat-frame#chat");
-
- if (watch) {
- // Determine the state of the chat and video player on the watch page and generate a state string.
- s += !chat ? 'h0' : (chat.hasAttribute('collapsed') || !document.querySelector('iframe#chatframe')) ? 'h1' : 'h2';
- s += watch.hasAttribute('is-two-columns_') ? 's' : 'S';
- s += watch.hasAttribute('fullscreen') ? 'F' : 'f';
- s += watch.hasAttribute('theater') ? 'T' : 't';
- }
- }
-
- // Update the reflected state if it has changed.
- if (s !== youtubeWpr) {
- document.documentElement.setAttribute("youtube-wpr", s);
- }
-
- }
-
- // Function to reflect changes in specific attributes of monitored elements.
- async function reflect(nodeName, attrNames, forced) {
- await Promise.resolve();
-
- if (!forced) {
- let skip = true;
- for (const attrName of attrNames) {
- if (nodeName === 'ytd-live-chat-frame') {
- if (attrName === 'collapsed') skip = false;
- } else if (nodeName === 'ytd-watch-flexy') {
- if (attrName === 'is-two-columns_') skip = false;
- else if (attrName === 'fullscreen') skip = false;
- else if (attrName === 'theater') skip = false;
- }
- }
- if (skip) return;
- }
-
- // Log the mutated element and its attributes.
- // console.log(nodeName, attrNames);
-
- // Call _reflect() to update the reflected state.
- _reflect();
- }
-
- // Callback function for the MutationObserver that tracks mutations in monitored elements.
- function callback(mutationsList) {
- const attrNames = new Set();
- let nodeName = null;
- for (const mutation of mutationsList) {
- if (nodeName === null && mutation.target) nodeName = mutation.target.nodeName.toLowerCase();
- attrNames.add(mutation.attributeName);
- }
- reflect(nodeName, attrNames, false);
- }
-
- function getParent(element) {
- return element.__shady_native_parentNode || element.__shady_parentNode || element.parentNode;
- }
-
- let lastPageTypeChanged = 0;
- function chatContainerMutationHandler() {
- if (Date.now() - lastPageTypeChanged < 800) _reflect();
- }
-
- // Function to start monitoring an element for mutations.
- function monitor(element) {
- if (!element) return;
- if (monitorWeakSet.has(element)) {
- return;
- }
-
- monitorWeakSet.add(element);
-
- const observer = new MutationObserver(callback);
- observer.observe(element, { attributes: true });
-
- if (element.id === 'chat') {
- const parentNode = getParent(element);
- if (parentNode instanceof Element && parentNode.id === 'chat-container' && !monitorWeakSet.has(parentNode)) {
- monitorWeakSet.add(parentNode);
- const observer = new MutationObserver(chatContainerMutationHandler);
- observer.observe(parentNode, { childList: true, subtree: false });
- }
- }
-
- return 1;
- }
-
- let timeout = 0;
-
- // Function to monitor relevant elements and update the reflected state.
- let g = async (forced) => {
- await Promise.resolve();
- let b = 0;
- b = b | monitor(document.querySelector("ytd-watch-flexy"));
- b = b | monitor(document.querySelector("ytd-live-chat-frame#chat"));
- if (b || forced) {
- _reflect();
- }
- }
- // let renderId = 0;
- // Event handler function that triggers when the page finishes navigation or page data updates.
- let eventHandlerFunc = async (evt) => {
- checkPageVisibilityChanged = true;
- timeout = Date.now() + 800;
- g(1);
- if (evt.type === 'yt-navigate-finish') {
- // delay required when page type is changed for #chat (home -> watch).
- setTimeout(() => {
- g(1);
- }, 80);
- } else if (evt.type === 'yt-page-type-changed') {
- lastPageTypeChanged = Date.now();
- // setTimeout(() => {
- // if (renderId > 1e9) renderId = 9;
- // const t = ++renderId;
- // requestAnimationFrame(() => {
- // if (t !== renderId) return;
- // g(1);
- // });
- // }, 180);
- if (typeof requestIdleCallback === 'function') {
- requestIdleCallback(() => {
- g(1);
- });
- }
- }
- }
-
- let loadState = 0;
-
- // Function to initialize the script and start monitoring the page.
- async function actor() {
- if (loadState === 0) {
- if (!document.documentElement.hasAttribute("youtube-wpr")) {
- loadState = 1;
- document.documentElement.setAttribute("youtube-wpr", "");
- document.addEventListener("yt-navigate-finish", eventHandlerFunc, false);
- document.addEventListener("yt-page-data-updated", eventHandlerFunc, false);
- document.addEventListener("yt-page-type-changed", eventHandlerFunc, false);
- } else {
- loadState = -1;
- document.removeEventListener("yt-page-data-fetched", actor, false);
- return;
- }
- }
- if (loadState === 1) {
- timeout = Date.now() + 800;
- // Function to continuously monitor elements and update the reflected state.
- let pf = () => {
- g(0);
- if (Date.now() < timeout) requestAnimationFrame(pf);
- };
- pf();
- }
- }
-
- // Event listener that triggers when page data is fetched.
- document.addEventListener("yt-page-data-fetched", actor, false);
-
- // Update after visibility changed (looks like there are bugs due to inactive tab)
- document.addEventListener('visibilitychange', () => {
- if (document.visibilityState !== 'visible') return;
- if (checkPageVisibilityChanged) {
- checkPageVisibilityChanged = false;
- setTimeout(() => {
- g(1);
- }, 100);
- requestAnimationFrame(() => {
- g(1);
- });
- }
- }, false);
-
-
- })();
-
- });
-
- })({ ResizeObserver });