From 6b56ee085de96bafda66165e90838f8ff8f049f1 Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Sun, 28 Apr 2024 16:55:43 +0200 Subject: [PATCH 01/24] Update satus.js special key signalling default option, remove instead of storing --- menu/satus.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/menu/satus.js b/menu/satus.js index 680575a56..e75233422 100644 --- a/menu/satus.js +++ b/menu/satus.js @@ -791,10 +791,18 @@ satus.render = function(skeleton, container, property, childrenOnly, prepend, sk set: function(val) { value = val; - if (satus.storage.get(key) != val) { - satus.storage.set(key, val); - - parent.dispatchEvent(new CustomEvent('change')); + if (skeleton.storage !== false) { + if (val === 'satus_remove') { + // 'satus_remove' is a special key signalling default option, remove instead of storing + satus.storage.remove(key); + + parent.dispatchEvent(new CustomEvent('change')); + } else if (satus.storage.get(key) != val) { + // only store if actually different value + satus.storage.set(key, val); + + parent.dispatchEvent(new CustomEvent('change')); + } } } } From 5680053d8951ff8310cd46e157dc3b8ebc87330c Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Mon, 29 Apr 2024 07:17:41 +0200 Subject: [PATCH 02/24] Update satus.js removing check already performed above --- menu/satus.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/menu/satus.js b/menu/satus.js index e75233422..e3a8682ab 100644 --- a/menu/satus.js +++ b/menu/satus.js @@ -791,18 +791,16 @@ satus.render = function(skeleton, container, property, childrenOnly, prepend, sk set: function(val) { value = val; - if (skeleton.storage !== false) { - if (val === 'satus_remove') { - // 'satus_remove' is a special key signalling default option, remove instead of storing - satus.storage.remove(key); + if (val === 'satus_remove') { + // 'satus_remove' is a special key signalling default option, remove instead of storing + satus.storage.remove(key); - parent.dispatchEvent(new CustomEvent('change')); - } else if (satus.storage.get(key) != val) { - // only store if actually different value - satus.storage.set(key, val); + parent.dispatchEvent(new CustomEvent('change')); + } else if (satus.storage.get(key) != val) { + // only store if actually different value + satus.storage.set(key, val); - parent.dispatchEvent(new CustomEvent('change')); - } + parent.dispatchEvent(new CustomEvent('change')); } } } From 2a02ed44716e9b09b47ea96dbca1c3164af4625c Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Mon, 29 Apr 2024 07:20:15 +0200 Subject: [PATCH 03/24] Update satus.js default switch to off, removes need for defining every switch in menu skeleton --- menu/satus.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menu/satus.js b/menu/satus.js index e3a8682ab..08b72b8bf 100644 --- a/menu/satus.js +++ b/menu/satus.js @@ -2473,7 +2473,7 @@ satus.components.checkbox = function(component, skeleton) { --------------------------------------------------------------*/ satus.components.switch = function(component, skeleton) { - var value = satus.isset(component.storage.value) ? component.storage.value : skeleton.value; + let value = component.storage?.value || skeleton.value || false; if (satus.isFunction(value)) { value = value(); From 36131ca1a7bacdd8b0741cad668c3c7edc1d6732 Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Mon, 29 Apr 2024 07:22:40 +0200 Subject: [PATCH 04/24] Update satus.js switch.flip only saves active option, removes when disabled --- menu/satus.js | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/menu/satus.js b/menu/satus.js index 08b72b8bf..7a89b5ad2 100644 --- a/menu/satus.js +++ b/menu/satus.js @@ -2495,22 +2495,39 @@ satus.components.switch = function(component, skeleton) { }; satus.components.switch.flip = function(val) { + let where = this; + + function flipTrue() { + where.dataset.value = 'true'; + if (where.skeleton.value == true) { + // skeleton.value: true makes this a default true flip switch where the only active state we save is false + where.storage.value = 'satus_remove'; + } else { + where.storage.value = true; + } + }; + function flipFalse() { + where.dataset.value = 'false'; + if (where.skeleton.value == true) { + // skeleton.value: true makes this a default true flip switch where the only active state we save is false + where.storage.value = false; + } else { + where.storage.value = 'satus_remove'; + } + }; + switch(val) { case true: - this.dataset.value = 'true'; - this.storage.value = true; + flipTrue(); break; case false: - this.dataset.value = 'false'; - this.storage.value = false; + flipFalse(); break; case undefined: - if (this.dataset.value === 'true') { - this.dataset.value = 'false'; - this.storage.value = false; + if (this.dataset.value === 'false') { + flipTrue(); } else { - this.dataset.value = 'true'; - this.storage.value = true; + flipFalse(); } break; } From 277f681e8a537ff1f68f21b177a77d66ef354a71 Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Mon, 29 Apr 2024 08:55:26 +0200 Subject: [PATCH 05/24] Update player.js use new special 'satus_remove' value for default option --- menu/skeleton-parts/player.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/menu/skeleton-parts/player.js b/menu/skeleton-parts/player.js index d82fc85bf..cbe882f44 100644 --- a/menu/skeleton-parts/player.js +++ b/menu/skeleton-parts/player.js @@ -6,9 +6,7 @@ extension.skeleton.main.layers.section.player = { component: 'button', variant: 'player', category: true, - on: { - click: {} - }, + on: {}, icon: { component: 'span', @@ -702,7 +700,7 @@ extension.skeleton.main.layers.section.player.on.click = { id: 'player_quality', options: [{ text: 'auto', - value: 'auto' + value: 'satus_remove' }, { text: '144p', value: 'tiny' From 68f9df2f7c9a00e63ec8bdc5d71812ecd8fee68a Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Mon, 29 Apr 2024 09:10:03 +0200 Subject: [PATCH 06/24] Update player.js switch.flip defaults to value:false, no need for explicit declarations anymore --- menu/skeleton-parts/player.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/menu/skeleton-parts/player.js b/menu/skeleton-parts/player.js index cbe882f44..f1eab871b 100644 --- a/menu/skeleton-parts/player.js +++ b/menu/skeleton-parts/player.js @@ -845,7 +845,6 @@ extension.skeleton.main.layers.section.player.on.click = { block_vp9: { component: 'switch', text: 'blockVp9', - value: false, custom: true, on: { click: function () { @@ -877,7 +876,6 @@ extension.skeleton.main.layers.section.player.on.click = { block_h264: { component: 'switch', text: 'blockH264', - value: false, custom: true, on: { click: function () { @@ -947,7 +945,6 @@ extension.skeleton.main.layers.section.player.on.click = { component: 'switch', text: 'codecH264', storage: 'player_h264', - value: false, custom: true, on: { click: function () { From 1bdc8192f0fb769c3fc5665487dbb8ca4c0c9499 Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Mon, 29 Apr 2024 09:13:04 +0200 Subject: [PATCH 07/24] Update player.js subtitles_language dont store default option --- menu/skeleton-parts/player.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menu/skeleton-parts/player.js b/menu/skeleton-parts/player.js index f1eab871b..691164b7f 100644 --- a/menu/skeleton-parts/player.js +++ b/menu/skeleton-parts/player.js @@ -160,7 +160,7 @@ extension.skeleton.main.layers.section.player.on.click = { text: 'language', id: 'language_closed_caption', options: [{ - value: 'default', + value: 'satus_remove', text: 'default_CC' }, { value: 'af', From b2fd294c7f7c4bc013048ac471fdf9e1195a3277 Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Mon, 29 Apr 2024 10:41:56 +0200 Subject: [PATCH 08/24] Update player.js more concise subtitlesLanguage --- .../web-accessible/www.youtube.com/player.js | 28 ++++++------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/js&css/web-accessible/www.youtube.com/player.js b/js&css/web-accessible/www.youtube.com/player.js index aa9ba3135..e9b7a0cfd 100644 --- a/js&css/web-accessible/www.youtube.com/player.js +++ b/js&css/web-accessible/www.youtube.com/player.js @@ -203,26 +203,16 @@ ImprovedTube.subtitles = function () { SUBTITLES LANGUAGE ------------------------------------------------------------------------------*/ ImprovedTube.subtitlesLanguage = function () { - var option = this.storage.subtitles_language; - if (this.isset(option) && option !== 'default') { - var player = this.elements.player, - button = this.elements.player_subtitles_button; + const option = this.storage.subtitles_language, + player = this.elements.player, + button = this.elements.player_subtitles_button; - if (player && player.getOption && button && button.getAttribute('aria-pressed') === 'true') { - var tracklist = this.elements.player.getOption('captions', 'tracklist', { - includeAsr: true - }); + if (option && player && player.getOption && button && button.getAttribute('aria-pressed') === 'true') { + const tracklists = player.getOption('captions', 'tracklist', {includeAsr: true}), + matchedTrack = tracklists.find(element => element.languageCode.includes(option) && (!element.vss_id.includes("a.") || this.storage.auto_generate)); - var matchTrack = false; - for (var i =0, l = tracklist.length; i Date: Mon, 29 Apr 2024 10:57:31 +0200 Subject: [PATCH 09/24] Update player.js subtitles_font_family 'Proportional Sans-Serif' is YT default --- menu/skeleton-parts/player.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menu/skeleton-parts/player.js b/menu/skeleton-parts/player.js index 691164b7f..4b8c0a4d9 100644 --- a/menu/skeleton-parts/player.js +++ b/menu/skeleton-parts/player.js @@ -509,7 +509,7 @@ extension.skeleton.main.layers.section.player.on.click = { value: 3 }, { text: 'Proportional Sans-Serif', - value: 4 + value: 'satus_remove' }, { text: 'Casual', value: 5 From ab95846fb4e6e6f3c3296fd3ab8782ab0c97142e Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Mon, 29 Apr 2024 10:58:48 +0200 Subject: [PATCH 10/24] Update player.js more concise subtitlesFontFamily --- .../web-accessible/www.youtube.com/player.js | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/js&css/web-accessible/www.youtube.com/player.js b/js&css/web-accessible/www.youtube.com/player.js index e9b7a0cfd..6115902b6 100644 --- a/js&css/web-accessible/www.youtube.com/player.js +++ b/js&css/web-accessible/www.youtube.com/player.js @@ -220,20 +220,16 @@ ImprovedTube.subtitlesLanguage = function () { SUBTITLES FONT FAMILY ------------------------------------------------------------------------------*/ ImprovedTube.subtitlesFontFamily = function () { - var option = this.storage.subtitles_font_family; - - if (this.isset(option)) { - var player = this.elements.player, - button = this.elements.player_subtitles_button; - - if (player && player.getSubtitlesUserSettings && button && button.getAttribute('aria-pressed') === 'true') { - var settings = player.getSubtitlesUserSettings(); + const option = this.storage.subtitles_font_family, + player = this.elements.player, + button = this.elements.player_subtitles_button; - if (settings) { - settings.fontFamily = Number(option); + if (option && player && player.getSubtitlesUserSettings && button && button.getAttribute('aria-pressed') === 'true') { + let settings = player.getSubtitlesUserSettings(); - player.updateSubtitlesUserSettings(settings); - } + if (settings) { + settings.fontFamily = Number(option); + player.updateSubtitlesUserSettings(settings); } } }; From defabdc6d3a2349197e050c09ad71c6ee1d3a46d Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Mon, 29 Apr 2024 13:40:12 +0200 Subject: [PATCH 11/24] satus.js select selectElement value is either stored value, or one with default special 'satus_remove' value --- menu/satus.js | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/menu/satus.js b/menu/satus.js index 7a89b5ad2..cd70d6457 100644 --- a/menu/satus.js +++ b/menu/satus.js @@ -1581,7 +1581,7 @@ satus.components.chart.bar = function(component, skeleton) { >>> SELECT --------------------------------------------------------------*/ satus.components.select = function(component, skeleton) { - var content = component.createChildElement('div', 'content'); + let content = component.createChildElement('div', 'content'); component.childrenContainer = content; component.valueElement = document.createElement('span'); @@ -1596,19 +1596,13 @@ satus.components.select = function(component, skeleton) { if (satus.isFunction(component.options)) { component.options = component.options(); - - if (!satus.isset(component.options)) { - component.options = []; - } } - for (var i = 0, l = component.options.length; i < l; i++) { + for (let i = 0, l = component.options.length; i < l; i++) { var option = document.createElement('option'); option.value = component.options[i].value; - satus.text(option, component.options[i].text); - component.selectElement.appendChild(option); } @@ -1632,18 +1626,18 @@ satus.components.select = function(component, skeleton) { }; component.selectElement.addEventListener('change', function() { - var component = this.parentNode; + let component = this.parentNode; component.storage.value = this.value; component.render(); }); - component.value = component.storage.value || component.options[0].value; + // initial select selectElement value is either stored value, or one with default special 'satus_remove' value, failing that first element is selected + component.value = component.storage.value || (component.options.find(element => element.value == 'satus_remove') ? 'satus_remove': false) || component.options[0].value; component.render(); }; - /*-------------------------------------------------------------- >>> DIVIDER --------------------------------------------------------------*/ From 52a9b9f9e6d1df2f693f1a15541603b623d7b26e Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Mon, 29 Apr 2024 13:45:29 +0200 Subject: [PATCH 12/24] Update player.js more default 'satus_remove' switches --- menu/skeleton-parts/player.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/menu/skeleton-parts/player.js b/menu/skeleton-parts/player.js index 4b8c0a4d9..8bf5b2598 100644 --- a/menu/skeleton-parts/player.js +++ b/menu/skeleton-parts/player.js @@ -526,7 +526,7 @@ extension.skeleton.main.layers.section.player.on.click = { text: 'fontColor', options: [{ text: 'white', - value: '#fff' + value: 'satus_remove' }, { text: 'yellow', value: '#ff0' @@ -561,7 +561,7 @@ extension.skeleton.main.layers.section.player.on.click = { value: -1 }, { text: '100%', - value: 0 + value: 'satus_remove' }, { text: '150%', value: 1 @@ -602,7 +602,7 @@ extension.skeleton.main.layers.section.player.on.click = { value: '#f00' }, { text: 'black', - value: '#000' + value: 'satus_remove' }] }, subtitles_background_opacity: { @@ -639,7 +639,7 @@ extension.skeleton.main.layers.section.player.on.click = { value: '#f00' }, { text: 'black', - value: '#000' + value: 'satus_remove' }] }, subtitles_window_opacity: { @@ -655,7 +655,7 @@ extension.skeleton.main.layers.section.player.on.click = { text: 'characterEdgeStyle', options: [{ text: 'none', - value: 0 + value: 'satus_remove' }, { text: 'dropShadow', value: 4 From 14863f2e5d06e1c65f58618c2afb1e36928ab5f2 Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Mon, 29 Apr 2024 13:57:40 +0200 Subject: [PATCH 13/24] Update player.js player_screenshot_save_as default --- menu/skeleton-parts/player.js | 50 +++++++++++++++++------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/menu/skeleton-parts/player.js b/menu/skeleton-parts/player.js index 8bf5b2598..62bc5c59f 100644 --- a/menu/skeleton-parts/player.js +++ b/menu/skeleton-parts/player.js @@ -1068,7 +1068,7 @@ extension.skeleton.main.layers.section.player.on.click = { text: 'saveAs', options: [{ text: 'file', - value: 'file' + value: 'satus_remove' }, { text: 'clipboard', value: 'clipboard' @@ -1105,28 +1105,28 @@ extension.skeleton.main.layers.section.player.on.click = { component: 'section', variant: 'card', title: 'extraButtonsBelowThePlayer', - below_player_screenshot: { - component: 'switch', - text: 'screenshot', - value: true - }, - below_player_pip: { - component: 'switch', - text: 'pictureInPicture', - value: true - }, - below_player_loop: { - component: 'switch', - text: 'loop', - value: true - } - }, - player_hide_controls_options: { - component: "button", - text: "hidePlayerControlsBarButtons", - on: { - click: 'main.layers.section.appearance.on.click.player.on.click.player_hide_controls_options.on.click' - } - }, - } + below_player_screenshot: { + component: 'switch', + text: 'screenshot', + value: true + }, + below_player_pip: { + component: 'switch', + text: 'pictureInPicture', + value: true + }, + below_player_loop: { + component: 'switch', + text: 'loop', + value: true + } + }, + player_hide_controls_options: { + component: "button", + text: "hidePlayerControlsBarButtons", + on: { + click: 'main.layers.section.appearance.on.click.player.on.click.player_hide_controls_options.on.click' + } + }, + } }; From 4abaeebf04e61389f340adda2e7751a890a6484d Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Mon, 29 Apr 2024 14:31:34 +0200 Subject: [PATCH 14/24] Update player.js screenshot respecting removed default player_screenshot_save_as fixed embed_subtitle setting - it wasnt working with default embed_subtitle.value: true --- .../web-accessible/www.youtube.com/player.js | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/js&css/web-accessible/www.youtube.com/player.js b/js&css/web-accessible/www.youtube.com/player.js index 6115902b6..84b5dd885 100644 --- a/js&css/web-accessible/www.youtube.com/player.js +++ b/js&css/web-accessible/www.youtube.com/player.js @@ -611,7 +611,7 @@ ImprovedTube.playerLoudnessNormalization = function () { SCREENSHOT ------------------------------------------------------------------------------*/ ImprovedTube.screenshot = function () { - var video = ImprovedTube.elements.video, + const video = ImprovedTube.elements.video, style = document.createElement('style'), cvs = document.createElement('canvas'), ctx = cvs.getContext('2d'); @@ -625,27 +625,28 @@ ImprovedTube.screenshot = function () { setTimeout(function () { ctx.drawImage(video, 0, 0, cvs.width, cvs.height); - var subText = ''; - var captionElements = document.querySelectorAll('.captions-text .ytp-caption-segment'); - captionElements.forEach(function (caption) {subText += caption.textContent.trim() + ' ';}); - - if(ImprovedTube.storage.embed_subtitle === true){ImprovedTube.renderSubtitle(ctx,captionElements);} - - cvs.toBlob(function (blob) { - if (ImprovedTube.storage.player_screenshot_save_as !== 'clipboard') { - var a = document.createElement('a'); - a.href = URL.createObjectURL(blob); console.log("screeeeeeenshot tada!"); + let subText = '', + captionElements = document.querySelectorAll('.captions-text .ytp-caption-segment'); + captionElements.forEach(function (caption) {subText += caption.textContent.trim() + ' ';}); - a.download = (ImprovedTube.videoId() || location.href.match) + ' ' + new Date(ImprovedTube.elements.player.getCurrentTime() * 1000).toISOString().substr(11, 8).replace(/:/g, '-') + ' ' + ImprovedTube.videoTitle() + (subText ? ' - ' + subText.trim() : '') + '.png'; + if (ImprovedTube.storage.embed_subtitle != false) { + ImprovedTube.renderSubtitle(ctx,captionElements); + } - a.click(); - } else { + cvs.toBlob(function (blob) { + if (ImprovedTube.storage.player_screenshot_save_as == 'clipboard') { navigator.clipboard.write([ new ClipboardItem({ 'image/png': blob }) ]); + } else { + let a = document.createElement('a'); + a.href = URL.createObjectURL(blob); + console.log("screeeeeeenshot tada!"); + a.download = (ImprovedTube.videoId() || location.href.match) + ' ' + new Date(ImprovedTube.elements.player.getCurrentTime() * 1000).toISOString().substr(11, 8).replace(/:/g, '-') + ' ' + ImprovedTube.videoTitle() + (subText ? ' - ' + subText.trim() : '') + '.png'; + a.click(); } }); From 15277d467f0ee1dcdc855dac0992a28337b7264a Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Mon, 29 Apr 2024 14:34:27 +0200 Subject: [PATCH 15/24] Update player.js single subtitlesUserSettings function, fixed for default options --- .../web-accessible/www.youtube.com/player.js | 212 ++++-------------- 1 file changed, 43 insertions(+), 169 deletions(-) diff --git a/js&css/web-accessible/www.youtube.com/player.js b/js&css/web-accessible/www.youtube.com/player.js index 84b5dd885..6ff89a269 100644 --- a/js&css/web-accessible/www.youtube.com/player.js +++ b/js&css/web-accessible/www.youtube.com/player.js @@ -218,187 +218,61 @@ ImprovedTube.subtitlesLanguage = function () { }; /*------------------------------------------------------------------------------ SUBTITLES FONT FAMILY -------------------------------------------------------------------------------*/ -ImprovedTube.subtitlesFontFamily = function () { - const option = this.storage.subtitles_font_family, - player = this.elements.player, - button = this.elements.player_subtitles_button; - - if (option && player && player.getSubtitlesUserSettings && button && button.getAttribute('aria-pressed') === 'true') { - let settings = player.getSubtitlesUserSettings(); - - if (settings) { - settings.fontFamily = Number(option); - player.updateSubtitlesUserSettings(settings); - } - } -}; -/*------------------------------------------------------------------------------ SUBTITLES FONT COLOR -------------------------------------------------------------------------------*/ -ImprovedTube.subtitlesFontColor = function () { - var option = this.storage.subtitles_font_color; - - if (this.isset(option)) { - var player = this.elements.player, - button = this.elements.player_subtitles_button; - - if (player && player.getSubtitlesUserSettings && button && button.getAttribute('aria-pressed') === 'true') { - var settings = player.getSubtitlesUserSettings(); - - if (settings) { - settings.color = option; - - player.updateSubtitlesUserSettings(settings); - } - } - } -}; -/*------------------------------------------------------------------------------ SUBTITLES FONT SIZE -------------------------------------------------------------------------------*/ -ImprovedTube.subtitlesFontSize = function () { - var option = this.storage.subtitles_font_size; - - if (this.isset(option)) { - var player = this.elements.player, - button = this.elements.player_subtitles_button; - - if (player && player.getSubtitlesUserSettings && button && button.getAttribute('aria-pressed') === 'true') { - var settings = player.getSubtitlesUserSettings(); - - if (settings) { - settings.fontSizeIncrement = Number(option); - - player.updateSubtitlesUserSettings(settings); - } - } - } -}; -/*------------------------------------------------------------------------------ SUBTITLES BACKGROUND COLOR -------------------------------------------------------------------------------*/ -ImprovedTube.subtitlesBackgroundColor = function () { - var option = this.storage.subtitles_background_color; - - if (this.isset(option)) { - var player = this.elements.player, - button = this.elements.player_subtitles_button; - - if (player && player.getSubtitlesUserSettings && button && button.getAttribute('aria-pressed') === 'true') { - var settings = player.getSubtitlesUserSettings(); - - if (settings) { - settings.background = option; - - player.updateSubtitlesUserSettings(settings); - } - } - } -}; -/*------------------------------------------------------------------------------ SUBTITLES BACKGROUND OPACITY -------------------------------------------------------------------------------*/ -ImprovedTube.subtitlesBackgroundOpacity = function () { - var option = this.storage.subtitles_background_opacity; - - if (this.isset(option)) { - var player = this.elements.player, - button = this.elements.player_subtitles_button; - - if (player && player.getSubtitlesUserSettings && button && button.getAttribute('aria-pressed') === 'true') { - var settings = player.getSubtitlesUserSettings(); - - if (settings) { - settings.backgroundOpacity = option / 100; - - player.updateSubtitlesUserSettings(settings); - } - } - } -}; -/*------------------------------------------------------------------------------ SUBTITLES WINDOW COLOR -------------------------------------------------------------------------------*/ -ImprovedTube.subtitlesWindowColor = function () { - var option = this.storage.subtitles_window_color; - - if (this.isset(option)) { - var player = this.elements.player, - button = this.elements.player_subtitles_button; - - if (player && player.getSubtitlesUserSettings && button && button.getAttribute('aria-pressed') === 'true') { - var settings = player.getSubtitlesUserSettings(); - - if (settings) { - settings.windowColor = option; - - player.updateSubtitlesUserSettings(settings); - } - } - } -}; -/*------------------------------------------------------------------------------ SUBTITLES WINDOW OPACITY -------------------------------------------------------------------------------*/ -ImprovedTube.subtitlesWindowOpacity = function () { - var option = this.storage.subtitles_window_opacity; - - if (this.isset(option)) { - var player = this.elements.player, - button = this.elements.player_subtitles_button; - - if (player && player.getSubtitlesUserSettings && button && button.getAttribute('aria-pressed') === 'true') { - var settings = player.getSubtitlesUserSettings(); - - if (settings) { - settings.windowOpacity = Number(option) / 100; - - player.updateSubtitlesUserSettings(settings); - } - } - } -}; -/*------------------------------------------------------------------------------ SUBTITLES CHARACTER EDGE STYLE -------------------------------------------------------------------------------*/ -ImprovedTube.subtitlesCharacterEdgeStyle = function () { - var option = this.storage.subtitles_character_edge_style; - - if (this.isset(option)) { - var player = this.elements.player, - button = this.elements.player_subtitles_button; - - if (player && player.getSubtitlesUserSettings && button && button.getAttribute('aria-pressed') === 'true') { - var settings = player.getSubtitlesUserSettings(); - - if (settings) { - settings.charEdgeStyle = Number(option); - - player.updateSubtitlesUserSettings(settings); - } - } - } -}; -/*------------------------------------------------------------------------------ SUBTITLES FONT OPACITY +default = { + "fontFamily": 4, + "color": "#fff", + "fontSizeIncrement": 0, + "background": "#080808", + "backgroundOpacity": 0.75, + "windowColor": "#080808", + "windowOpacity": 0, + "charEdgeStyle": 0, + "textOpacity": 1, +}, ------------------------------------------------------------------------------*/ -ImprovedTube.subtitlesFontOpacity = function () { - var option = this.storage.subtitles_font_opacity; - - if (this.isset(option)) { - var player = this.elements.player, - button = this.elements.player_subtitles_button; - - if (player && player.getSubtitlesUserSettings && button && button.getAttribute('aria-pressed') === 'true') { - var settings = player.getSubtitlesUserSettings(); - - if (settings) { - settings.textOpacity = option / 100; +ImprovedTube.subtitlesUserSettings = function () { + const ourSettings = [ + ['fontFamily', 'number', this.storage.subtitles_font_family], + ['color', 'color', this.storage.subtitles_font_color], + ['fontSizeIncrement', 'number', this.storage.subtitles_font_size], + ['background', 'color', this.storage.subtitles_background_color], + ['backgroundOpacity', 'fraction', this.storage.subtitles_background_opacity], + ['windowColor', 'color', this.storage.subtitles_window_color], + ['windowOpacity', 'fraction', this.storage.subtitles_window_opacity], + ['charEdgeStyle', 'number', this.storage.subtitles_character_edge_style], + ['textOpacity', 'fraction', this.storage.subtitles_font_opacity] + ], + option = ourSettings.filter(element => element[2]), + player = this.elements.player, + button = this.elements.player_subtitles_button; - player.updateSubtitlesUserSettings(settings); + if (option.length && player.getSubtitlesUserSettings && button && button.getAttribute('aria-pressed') === 'true') { + let settings = player.getSubtitlesUserSettings(); + + for (const value of option) { + switch(value[1]) { + case 'number': + settings[value[0]] = Number(value[2]); + break; + + case 'color': + settings[value[0]] = value[2]; + break; + + case 'fraction': + settings[value[0]] = Number(option) / 100; + break; } } + player.updateSubtitlesUserSettings(settings); } }; /*------------------------------------------------------------------------------ From 9c45f39b11cf8b2fadb98d0cd75f1bb2de2d329b Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Mon, 29 Apr 2024 14:41:11 +0200 Subject: [PATCH 16/24] Update functions.js subtitles* functions combined into subtitlesUserSettings() subtitlesUserSettings() = ImprovedTube.subtitlesFontFamily(); ImprovedTube.subtitlesUserSettings(); ImprovedTube.subtitlesFontColor(); ImprovedTube.subtitlesFontSize(); ImprovedTube.subtitlesBackgroundColor(); ImprovedTube.subtitlesWindowColor(); ImprovedTube.subtitlesWindowOpacity(); ImprovedTube.subtitlesCharacterEdgeStyle(); ImprovedTube.subtitlesFontOpacity(); ImprovedTube.subtitlesBackgroundOpacity(); --- js&css/web-accessible/functions.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/js&css/web-accessible/functions.js b/js&css/web-accessible/functions.js index 7c62691da..172dac687 100644 --- a/js&css/web-accessible/functions.js +++ b/js&css/web-accessible/functions.js @@ -361,15 +361,7 @@ ImprovedTube.initPlayer = function () { ImprovedTube.playerPlaybackSpeed(); ImprovedTube.subtitles(); ImprovedTube.subtitlesLanguage(); - ImprovedTube.subtitlesFontFamily(); - ImprovedTube.subtitlesFontColor(); - ImprovedTube.subtitlesFontSize(); - ImprovedTube.subtitlesBackgroundColor(); - ImprovedTube.subtitlesWindowColor(); - ImprovedTube.subtitlesWindowOpacity(); - ImprovedTube.subtitlesCharacterEdgeStyle(); - ImprovedTube.subtitlesFontOpacity(); - ImprovedTube.subtitlesBackgroundOpacity(); + ImprovedTube.subtitlesUserSettings(); ImprovedTube.subtitlesDisableLyrics(); ImprovedTube.playerQuality(); ImprovedTube.playerVolume(); From 373b0351b0f1498aa66f3f4f7d64de72e2d95ba4 Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Mon, 29 Apr 2024 14:43:32 +0200 Subject: [PATCH 17/24] Update core.js handler for subtitlesUserSettings settings change --- js&css/web-accessible/core.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/js&css/web-accessible/core.js b/js&css/web-accessible/core.js index 631d436a0..243b69eee 100644 --- a/js&css/web-accessible/core.js +++ b/js&css/web-accessible/core.js @@ -358,6 +358,18 @@ document.addEventListener('it-message-from-extension', function () { case 'blocklistActivate': if (ImprovedTube.storage.blocklist_activate === true) {document.querySelectorAll('.it-add-to-blocklist').forEach(e => e.remove());} break + + case 'subtitlesFontFamily': + case 'subtitlesFontColor': + case 'subtitlesFontSize': + case 'subtitlesBackgroundColor': + case 'subtitlesWindowColor': + case 'subtitlesWindowOpacity': + case 'subtitlesCharacterEdgeStyle': + case 'subtitlesFontOpacity': + case 'subtitlesBackgroundOpacity': + ImprovedTube.subtitlesUserSettings(); + break } if (ImprovedTube[camelized_key]) { From 9e785b98424a91d041cd741c96a32ed813a9034c Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Mon, 29 Apr 2024 16:06:14 +0200 Subject: [PATCH 18/24] Update player.js optimizing down, confirm.modal cancels are optional --- menu/skeleton-parts/player.js | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/menu/skeleton-parts/player.js b/menu/skeleton-parts/player.js index 62bc5c59f..1acb3ca9c 100644 --- a/menu/skeleton-parts/player.js +++ b/menu/skeleton-parts/player.js @@ -858,8 +858,6 @@ extension.skeleton.main.layers.section.player.on.click = { ok: function () { where.flip(true); where.parentElement.skeleton.sanitize(); - }, - cancel: function () { } }, extension.skeleton.rendered); } else { @@ -889,8 +887,6 @@ extension.skeleton.main.layers.section.player.on.click = { ok: function () { where.flip(true); where.parentElement.skeleton.sanitize(); - }, - cancel: function () { } }, extension.skeleton.rendered); } else { @@ -905,13 +901,10 @@ extension.skeleton.main.layers.section.player.on.click = { } }, sanitize: function () { - if (satus.storage.get('player_h264')) { - if ((!satus.storage.get('block_vp9') || !satus.storage.get('block_av1') && satus.storage.get('block_h264')) || - (satus.storage.get('block_vp9') && satus.storage.get('block_av1') && satus.storage.get('block_h264'))) { - satus.storage.set('player_h264', false); - } - } else if (satus.storage.get('block_vp9') && satus.storage.get('block_av1') && !satus.storage.get('block_h264')) { + if (satus.storage.get('block_vp9') && satus.storage.get('block_av1') && !satus.storage.get('block_h264')) { satus.storage.set('player_h264', true); + } else { + satus.storage.remove('player_h264'); } } } @@ -925,7 +918,7 @@ extension.skeleton.main.layers.section.player.on.click = { }, on: { render: function () { - var codecs = (satus.storage.get('block_h264') ? '' : 'h.264 ') + (satus.storage.get('block_vp9') ? '' : 'vp9 ') + (satus.storage.get('block_av1') ? '' : 'av1'); + let codecs = (satus.storage.get('block_h264') ? '' : 'h.264 ') + (satus.storage.get('block_vp9') ? '' : 'vp9 ') + (satus.storage.get('block_av1') ? '' : 'av1'); if (codecs.includes('h.264') || codecs.includes('vp9')) { this.style = ''; @@ -948,14 +941,14 @@ extension.skeleton.main.layers.section.player.on.click = { custom: true, on: { click: function () { - let skeleton = this.parentNode.skeleton; // refresh player_codecs/optimize_codec_for_hardware_acceleration elements when we change codecs - let refresh = function () { + function refresh() { document.getElementById('player_quality').dispatchEvent(new CustomEvent('render')); document.getElementById('player_codecs').dispatchEvent(new CustomEvent('render')); document.getElementById('optimize_codec_for_hardware_acceleration').dispatchEvent(new CustomEvent('render')); document.getElementById('player_quality_without_focus').dispatchEvent(new CustomEvent('render')); - } + }; + if (this.dataset.value === 'false') { let where = this; satus.render({ @@ -967,20 +960,18 @@ extension.skeleton.main.layers.section.player.on.click = { where.flip(true); satus.storage.set('block_vp9', true); satus.storage.set('block_av1', true); - satus.storage.set('block_h264', false); + satus.storage.remove('block_h264'); refresh(); - }, - cancel: function () { - // nothing happens when we cancel } }, extension.skeleton.rendered); } else { // manually turn switch OFF this.flip(false); // reset all codecs to unlocked state - satus.storage.set('block_vp9', false); - satus.storage.set('block_av1', false); - satus.storage.set('block_h264', false); + satus.storage.remove('block_vp9'); + satus.storage.remove('block_av1'); + satus.storage.remove('block_h264'); + satus.storage.remove('player_h264'); refresh(); } } From 13b4494f8661e923e80a4b73512a16197a92a097 Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Mon, 29 Apr 2024 19:27:44 +0200 Subject: [PATCH 19/24] Update satus.js make sliders remove default value I broke half the sliders with https://github.com/code-charity/youtube/commit/220d429107a9fa3f11633a4529d83dce7f2d0e86, fixed now --- menu/satus.js | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/menu/satus.js b/menu/satus.js index cd70d6457..d70a96340 100644 --- a/menu/satus.js +++ b/menu/satus.js @@ -2012,29 +2012,29 @@ satus.components.radio = function(component, skeleton) { /*-------------------------------------------------------------- >>> SLIDER --------------------------------------------------------------*/ - satus.components.slider = function(component, skeleton) { - var content = component.createChildElement('div', 'content'), + const content = component.createChildElement('div', 'content'), children_container = content.createChildElement('div', 'children-container'), text_input = content.createChildElement('input'), track_container = component.createChildElement('div', 'track-container'), input = track_container.createChildElement('input', 'input'); - component.childrenContainer = children_container; - component.textInput = text_input; - component.input = input; - component.track = track_container.createChildElement('div', 'track'); - - text_input.type = 'text'; - input.type = 'range'; input.min = skeleton.min || 0; input.max = skeleton.max || 1; input.step = skeleton.step || 1; input.value = component.storage?.value || skeleton.value || 0; + component.childrenContainer = children_container; + component.input = input; + component.track = track_container.createChildElement('div', 'track'); + component.track.style.width = 100 / (input.max - input.min) * (input.value - input.min) + '%'; + component.textInput = text_input; + component.textInput.type = 'text'; + component.textInput.value = input.value; + text_input.addEventListener('blur', function() { - var component = this.parentNode.parentNode; + const component = this.parentNode.parentNode; component.input.value = Number(this.value.replace(/[^0-9.]/g, '')); @@ -2043,7 +2043,7 @@ satus.components.slider = function(component, skeleton) { text_input.addEventListener('keydown', function(event) { if (event.key === 'Enter') { - var component = this.parentNode.parentNode; + const component = this.parentNode.parentNode; component.input.value = Number(this.value.replace(/[^0-9.]/g, '')); @@ -2052,7 +2052,7 @@ satus.components.slider = function(component, skeleton) { }); input.addEventListener('input', function() { - var component = this.parentNode.parentNode; + const component = this.parentNode.parentNode; component.value = Number(this.value); @@ -2060,17 +2060,22 @@ satus.components.slider = function(component, skeleton) { }); component.update = function() { - var input = this.input; + const input = this.input; this.textInput.value = input.value; + if (component.storage) { + if (component.skeleton.value == Number(input.value)) { + component.storage.value = 'satus_remove'; + } else { + component.storage.value = Number(input.value); + } + } this.track.style.width = 100 / (input.max - input.min) * (input.value - input.min) + '%'; }; - component.update(); - if (skeleton.on) { - for (var type in skeleton.on) { + for (const type in skeleton.on) { input.addEventListener(type, function(event) { this.parentNode.parentNode.dispatchEvent(new Event(event.type)); }); From 0238a7e0bac27e1c03bfafe3fc0add240a3ac3c5 Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Mon, 29 Apr 2024 19:47:08 +0200 Subject: [PATCH 20/24] Update satus.js nicer looking --- menu/satus.js | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/menu/satus.js b/menu/satus.js index d70a96340..330705efb 100644 --- a/menu/satus.js +++ b/menu/satus.js @@ -3195,9 +3195,8 @@ satus.user.device.connection = function() { /*-------------------------------------------------------------- # SEARCH --------------------------------------------------------------*/ - satus.search = function(query, object, callback) { - var elements = ['switch', 'select', 'slider', 'shortcut', 'radio', 'color-picker', 'label', 'button'], + let elements = ['switch', 'select', 'slider', 'shortcut', 'radio', 'color-picker', 'label', 'button'], threads = 0, results = {}, excluded = [ @@ -3216,9 +3215,8 @@ satus.search = function(query, object, callback) { function parse(items, parent) { threads++; - for (const key in items) { + for (const [key, item] of Object.entries(items)) { if (!excluded.includes(key)) { - var item = items[key]; if (item.component && item.text // list of elements we allow search on @@ -3231,12 +3229,10 @@ satus.search = function(query, object, callback) { results[key] = Object.assign({}, item); } - if ( - satus.isObject(item) && - !satus.isArray(item) && - !satus.isElement(item) && - !satus.isFunction(item) - ) { + if (satus.isObject(item) + && !satus.isArray(item) + && !satus.isElement(item) + && !satus.isFunction(item)) { parse(item, items); } } From d18cea67d892a9c647ff17590e050764a8c2fd2f Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Tue, 30 Apr 2024 13:33:04 +0200 Subject: [PATCH 21/24] Update player.js reworking component: 'switch' from "custom: true" to variant: 'manual' removing one redundant storage manipulation now that switches do it automatically --- menu/skeleton-parts/player.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/menu/skeleton-parts/player.js b/menu/skeleton-parts/player.js index 1acb3ca9c..f8f4858a8 100644 --- a/menu/skeleton-parts/player.js +++ b/menu/skeleton-parts/player.js @@ -844,8 +844,8 @@ extension.skeleton.main.layers.section.player.on.click = { }, block_vp9: { component: 'switch', + variant: 'manual', text: 'blockVp9', - custom: true, on: { click: function () { if (this.dataset.value === 'false') { @@ -873,8 +873,8 @@ extension.skeleton.main.layers.section.player.on.click = { }, block_h264: { component: 'switch', + variant: 'manual', text: 'blockH264', - custom: true, on: { click: function () { if (this.dataset.value === 'false') { @@ -936,9 +936,9 @@ extension.skeleton.main.layers.section.player.on.click = { }, h264: { component: 'switch', + variant: 'manual', text: 'codecH264', storage: 'player_h264', - custom: true, on: { click: function () { // refresh player_codecs/optimize_codec_for_hardware_acceleration elements when we change codecs @@ -971,7 +971,6 @@ extension.skeleton.main.layers.section.player.on.click = { satus.storage.remove('block_vp9'); satus.storage.remove('block_av1'); satus.storage.remove('block_h264'); - satus.storage.remove('player_h264'); refresh(); } } From 3342afc02da8c04b62f940d96a65723245b309dd Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Tue, 30 Apr 2024 14:03:39 +0200 Subject: [PATCH 22/24] Update satus.js switch variant: 'manual' instead of custom: true --- menu/satus.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/menu/satus.js b/menu/satus.js index 330705efb..c2990ece7 100644 --- a/menu/satus.js +++ b/menu/satus.js @@ -67,6 +67,8 @@ text(element, value) components.modal(component, skeleton) components.modal.confirm +// modal variant: 'confirm' supports two forms: Full with user providing own skeleton.buttons, and simplified with only function +// declarations for optional ok() and cancel(). Simplified takes care of closing popup on its own. components.grid components.textField chart chart.bar @@ -81,7 +83,9 @@ components.divider() base(component) section shortcut checkbox components.switch -components.switch.flip +components.switch.flip(state) +//switch variant: 'manual' disables automatic flipping on click, user provided on.click function should handle this +//by calling this.flip(true|false) manually. ---------------------------------------------------------------- >>> COLOR: String to array @@ -2485,8 +2489,8 @@ satus.components.switch = function(component, skeleton) { component.dataset.value = value; component.flip = satus.components.switch.flip; - // 'custom' disables default onclick, user provided function should handle this functionality manually - if (!skeleton.custom) { + // switch variant: 'manual' disables automatic flipping on click, user provided function should handle switching manually + if (skeleton.variant != 'manual') { component.addEventListener('click', function() { this.flip(); }, true); From 1253b9e53dffd6e98c31d0f1b0ae90ef9f3de6a9 Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Tue, 30 Apr 2024 15:49:12 +0200 Subject: [PATCH 23/24] Update satus.js checkbox respects storage:false and value:true, automatically deletes unused config --- menu/satus.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/menu/satus.js b/menu/satus.js index c2990ece7..eab526047 100644 --- a/menu/satus.js +++ b/menu/satus.js @@ -2447,7 +2447,6 @@ satus.components.shortcut = function(component, skeleton) { /*-------------------------------------------------------------- >>> CHECKBOX --------------------------------------------------------------*/ - satus.components.checkbox = function(component, skeleton) { component.input = component.createChildElement('input'); component.input.type = 'checkbox'; @@ -2456,18 +2455,28 @@ satus.components.checkbox = function(component, skeleton) { component.childrenContainer = component.createChildElement('div', 'content'); - component.dataset.value = component.storage.value || skeleton.value; - component.input.checked = component.storage.value || skeleton.value; + component.dataset.value = component.storage?.value || skeleton.value || false; + component.input.checked = component.storage?.value || skeleton.value || false; component.input.addEventListener('change', function() { - var component = this.parentNode; + const component = this.parentNode; if (this.checked === true) { - component.storage.value = true; component.dataset.value = 'true'; + if (component.skeleton.value == true) { + // skeleton.value: true makes this a default true checkbox where the only active state we save is false + component.storage.value = 'satus_remove'; + } else { + component.storage.value = true; + } } else { - component.storage.value = false; component.dataset.value = 'false'; + if (component.skeleton.value == true) { + // skeleton.value: true makes this a default true checkbox where the only active state we save is false + component.storage.value = false; + } else { + component.storage.value = 'satus_remove'; + } } }); }; From 2cf132f6cfa65a77fdd5fa91a735a0440db54ad1 Mon Sep 17 00:00:00 2001 From: Rasz_pl Date: Wed, 1 May 2024 11:17:42 +0200 Subject: [PATCH 24/24] Update satus.js more comments explaining functionality, simplifying code --- menu/satus.js | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/menu/satus.js b/menu/satus.js index eab526047..2b2c233c2 100644 --- a/menu/satus.js +++ b/menu/satus.js @@ -71,14 +71,19 @@ components.modal.confirm // declarations for optional ok() and cancel(). Simplified takes care of closing popup on its own. components.grid components.textField - chart chart.bar + chart + chart.bar select components.divider() base(component) section - alert time sidebar + alert + time + sidebar layers list colorPicker - radio slider + radio +// radio button controls storage.key defined by radio.group: 'key' + slider tabs shortcut checkbox @@ -1585,13 +1590,10 @@ satus.components.chart.bar = function(component, skeleton) { >>> SELECT --------------------------------------------------------------*/ satus.components.select = function(component, skeleton) { - let content = component.createChildElement('div', 'content'); - - component.childrenContainer = content; + component.childrenContainer = component.createChildElement('div', 'content'); component.valueElement = document.createElement('span'); - component.selectElement = document.createElement('select'); - component.valueElement.className = 'satus-select__value'; + component.selectElement = document.createElement('select'); component.appendChild(component.valueElement); component.appendChild(component.selectElement); @@ -1602,11 +1604,11 @@ satus.components.select = function(component, skeleton) { component.options = component.options(); } - for (let i = 0, l = component.options.length; i < l; i++) { - var option = document.createElement('option'); + for (const options of component.options) { + const option = document.createElement('option'); - option.value = component.options[i].value; - satus.text(option, component.options[i].text); + option.value = options.value; + satus.text(option, options.text); component.selectElement.appendChild(option); } @@ -3209,9 +3211,7 @@ satus.user.device.connection = function() { # SEARCH --------------------------------------------------------------*/ satus.search = function(query, object, callback) { - let elements = ['switch', 'select', 'slider', 'shortcut', 'radio', 'color-picker', 'label', 'button'], - threads = 0, - results = {}, + const included = ['switch', 'select', 'slider', 'shortcut', 'radio', 'color-picker', 'label', 'button'], excluded = [ 'baseProvider', 'layersProvider', @@ -3222,6 +3222,8 @@ satus.search = function(query, object, callback) { 'parentElement', 'rendered' ]; + let threads = 0, + results = {}; query = query.toLowerCase(); @@ -3233,7 +3235,7 @@ satus.search = function(query, object, callback) { if (item.component && item.text // list of elements we allow search on - && elements.includes(item.component) + && included.includes(item.component) // only pass buttons whose parents are variant: 'card' or special case 'appearance' (this one abuses variant tag for CSS) && (item.component != 'button' || item.parentObject?.variant == "card" || item.parentObject?.variant == "appearance") // try to match query against localized description, fallback on component name