From 139336a41d93585c06fa315038b90c14bc00682c Mon Sep 17 00:00:00 2001 From: ririxi Date: Tue, 12 Mar 2024 02:19:13 +0100 Subject: [PATCH 01/54] fix(reddit): use `fetch` instead of `CosmosAsync` (#2892) --- CustomApps/reddit/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CustomApps/reddit/index.js b/CustomApps/reddit/index.js index 51735e31cd..e6633ad946 100644 --- a/CustomApps/reddit/index.js +++ b/CustomApps/reddit/index.js @@ -298,7 +298,7 @@ async function getSubreddit(after = "") { url += `&t=${sortConfig.time}`; } - return await Spicetify.CosmosAsync.get(url); + return await fetch(url, { method: "GET" }).then(res => res.json()); } async function fetchPlaylist(post) { From a5f21543b6372e6576536be07de6cdfecd032077 Mon Sep 17 00:00:00 2001 From: ririxi Date: Tue, 12 Mar 2024 02:19:24 +0100 Subject: [PATCH 02/54] fix: implement missing class for cards for `1.2.33` and higher (#2894) --- src/backup/backup.go | 3 +-- src/preprocess/preprocess.go | 9 +++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/backup/backup.go b/src/backup/backup.go index 48e00d0050..e8776a59dc 100644 --- a/src/backup/backup.go +++ b/src/backup/backup.go @@ -14,8 +14,7 @@ func Start(appPath, backupPath string) error { // Extract all SPA files from backupPath to extractPath func Extract(backupPath, extractPath string) { - // TODO: "settings" no longer exists in > 1.1.62, remove it when Linux Spotify is updated. - for _, app := range []string{"xpui", "login", "settings"} { + for _, app := range []string{"xpui", "login"} { appPath := filepath.Join(backupPath, app+".spa") appExtractToFolder := filepath.Join(extractPath, app) diff --git a/src/preprocess/preprocess.go b/src/preprocess/preprocess.go index 006e50ad75..e5be326d8a 100644 --- a/src/preprocess/preprocess.go +++ b/src/preprocess/preprocess.go @@ -124,14 +124,11 @@ func Start(version string, extractedAppsPath string, flags Flag) { if flags.RemoveRTL { content = removeRTL(content) } - // Temporary fix for top bar opacity bug if fileName == "xpui.css" { content = fmt.Sprintf(`%s - .main-topBar-topbarContent:not(.main-topBar-topbarContentFadeIn)>* { - opacity: unset !important; - } - .main-entityHeader-topbarContent:not(.main-entityHeader-topbarContentFadeIn)>* { - opacity: 0 !important; + .main-gridContainer-fixedWidth { + grid-template-columns: repeat(auto-fill, var(--column-width)); + width: calc((var(--column-count) - 1) * var(--grid-gap)) + var(--column-count) * var(--column-width)); }`, content) } return content From 4741c931611f95505548adab26ed0753c853c8d5 Mon Sep 17 00:00:00 2001 From: ririxi Date: Tue, 12 Mar 2024 03:43:59 +0100 Subject: [PATCH 03/54] ci: remove 'update the homebrew tap' step (#2896) --- .github/workflows/build.yml | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f60b6715e7..2394cd1332 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -98,19 +98,6 @@ jobs: with: url: https://vps.itsmeow.dev/spicetify-update method: GET - - name: Update Homebrew tap - uses: mislav/bump-homebrew-formula-action@v3 - if: ${{ !contains(github.ref, '-') }} - with: - formula-name: spicetify-cli - formula-path: spicetify-cli.rb - homebrew-tap: spicetify/homebrew-tap - base-branch: main - download-url: https://github.com/spicetify/spicetify-cli/archive/${{ github.ref_name }}.tar.gz - commit-message: | - feat: {{version}} release - env: - COMMITTER_TOKEN: ${{ secrets.SPICETIFY_GITHUB_TOKEN }} - name: Update Winget package uses: vedantmgoyal2009/winget-releaser@v2 with: From 03668a3c5a67531e3de41720e49c7383102f75a0 Mon Sep 17 00:00:00 2001 From: ririxi Date: Tue, 12 Mar 2024 03:55:56 +0100 Subject: [PATCH 04/54] fix: disable sentry completely (#2898) --- src/preprocess/preprocess.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/preprocess/preprocess.go b/src/preprocess/preprocess.go index e5be326d8a..c239d07491 100644 --- a/src/preprocess/preprocess.go +++ b/src/preprocess/preprocess.go @@ -89,7 +89,7 @@ func Start(version string, extractedAppsPath string, flags Flag) { switch extension { case ".js": utils.ModifyFile(path, func(content string) string { - if flags.DisableSentry && fileName == "vendor~xpui.js" { + if flags.DisableSentry && fileName == "xpui.js" { content = disableSentry(content) } @@ -303,8 +303,8 @@ func colorVariableReplaceForJS(content string) string { } func disableSentry(input string) string { - utils.Replace(&input, `(?:prototype\.)?bindClient(?:=function)?\(\w+\)\{`, func(submatches ...string) string { - return fmt.Sprintf("%sreturn;", submatches[0]) + utils.Replace(&input, `(\("[^"]+sentry.io)/`, func(submatches ...string) string { + return fmt.Sprintf(",%s", submatches[0]) }) return input } From ef0b493aafeadc28f23f23c1a04cbd2eb014b053 Mon Sep 17 00:00:00 2001 From: ririxi Date: Tue, 12 Mar 2024 11:45:43 +0100 Subject: [PATCH 05/54] fix: properly set every value in state (#2899) --- jsHelper/spicetifyWrapper.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/jsHelper/spicetifyWrapper.js b/jsHelper/spicetifyWrapper.js index dfbdccd744..f23973b03c 100644 --- a/jsHelper/spicetifyWrapper.js +++ b/jsHelper/spicetifyWrapper.js @@ -1439,11 +1439,11 @@ Spicetify.ContextMenuV2 = (() => { this._divider = divider; this._element = Spicetify.ReactJSX.jsx(() => { - const [_children, setChildren] = Spicetify.React.useState(children); - const [_disabled, setDisabled] = Spicetify.React.useState(disabled); - const [_leadingIcon, setLeadingIcon] = Spicetify.React.useState(leadingIcon); - const [_trailingIcon, setTrailingIcon] = Spicetify.React.useState(trailingIcon); - const [_divider, setDivider] = Spicetify.React.useState(divider); + const [_children, setChildren] = Spicetify.React.useState(this._children); + const [_disabled, setDisabled] = Spicetify.React.useState(this._disabled); + const [_leadingIcon, setLeadingIcon] = Spicetify.React.useState(this._leadingIcon); + const [_trailingIcon, setTrailingIcon] = Spicetify.React.useState(this._trailingIcon); + const [_divider, setDivider] = Spicetify.React.useState(this._divider); Spicetify.React.useEffect(() => { this._setChildren = setChildren; @@ -1535,11 +1535,11 @@ Spicetify.ContextMenuV2 = (() => { this._leadingIcon = leadingIcon; this._items = items; this._element = Spicetify.ReactJSX.jsx(() => { - const [_text, setText] = Spicetify.React.useState(text); - const [_disabled, setDisabled] = Spicetify.React.useState(disabled); - const [_leadingIcon, setLeadingIcon] = Spicetify.React.useState(leadingIcon); - const [_divider, setDivider] = Spicetify.React.useState(divider); - const [_items, setItems] = Spicetify.React.useState(items); + const [_text, setText] = Spicetify.React.useState(this._text); + const [_disabled, setDisabled] = Spicetify.React.useState(this._disabled); + const [_leadingIcon, setLeadingIcon] = Spicetify.React.useState(this._leadingIcon); + const [_divider, setDivider] = Spicetify.React.useState(this._divider); + const [_items, setItems] = Spicetify.React.useState(this._items); Spicetify.React.useEffect(() => { this._setText = setText; From e181309ede8c3d5bc649edc523fcf6fb4fdfd9f6 Mon Sep 17 00:00:00 2001 From: ririxi Date: Tue, 12 Mar 2024 11:45:59 +0100 Subject: [PATCH 06/54] fix: repair helpers to work on newer versions (#2888) --- jsHelper/homeConfig.js | 2 +- jsHelper/sidebarConfig.js | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/jsHelper/homeConfig.js b/jsHelper/homeConfig.js index a2a56477f2..6c086e45c1 100644 --- a/jsHelper/homeConfig.js +++ b/jsHelper/homeConfig.js @@ -165,7 +165,7 @@ SpicetifyHomeConfig = {}; await new Promise(res => Spicetify.Events.webpackLoaded.on(res)); - const menu = new Spicetify.Menu.Item("Home config", true, self => { + const menu = new Spicetify.Menu.Item("Home config", false, self => { self.isEnabled = !self.isEnabled; if (self.isEnabled) { injectInteraction(); diff --git a/jsHelper/sidebarConfig.js b/jsHelper/sidebarConfig.js index 637ca78772..b0561600ce 100644 --- a/jsHelper/sidebarConfig.js +++ b/jsHelper/sidebarConfig.js @@ -172,7 +172,7 @@ color: var(--spice-button-disabled); await new Promise(res => Spicetify.Events.webpackLoaded.on(res)); new Spicetify.Menu.Item( "Sidebar config", - true, + false, self => { self.isEnabled = !self.isEnabled; if (self.isEnabled) { @@ -185,6 +185,19 @@ color: var(--spice-button-disabled); ).register(); })(); + function initConfig() { + const libraryX = document.querySelector(".main-yourLibraryX-navItems"); + const libraryLegacy = document.querySelector(".main-navBar-entryPoints"); + + if (!libraryLegacy && !libraryX) { + setTimeout(initConfig, 300); + return; + } + + if (libraryX) InitSidebarXConfig(); + else InitSidebarConfig(); + } + function InitSidebarConfig() { // STICKY container const legacyAppItems = document.querySelector(".main-navBar-entryPoints"); @@ -305,8 +318,7 @@ color: var(--spice-button-disabled); appendItems(); } - InitSidebarConfig(); - InitSidebarXConfig(); + initConfig(); // Rearrange sidebar when dynamically switching in Experimental Features new MutationObserver(mutations => { From c9b62501a25e9b891ee8f4e35c9573792fe88ef0 Mon Sep 17 00:00:00 2001 From: Thomas Fitzpatrick <22730962+ohitstom@users.noreply.github.com> Date: Tue, 12 Mar 2024 11:21:45 +0000 Subject: [PATCH 07/54] fix(homeConfig): support all versions (#2897) --- jsHelper/homeConfig.js | 44 ++++++++++++++++++++++++++------------- jsHelper/sidebarConfig.js | 2 +- src/apply/apply.go | 4 ++-- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/jsHelper/homeConfig.js b/jsHelper/homeConfig.js index 6c086e45c1..7b5490df83 100644 --- a/jsHelper/homeConfig.js +++ b/jsHelper/homeConfig.js @@ -50,8 +50,14 @@ SpicetifyHomeConfig = {}; down.innerText = "Down"; const lower = document.createElement("button"); const stick = document.createElement("button"); - const style = document.createElement("style"); - style.innerHTML = ` + const sectionStyle = document.createElement("style"); + sectionStyle.innerHTML = ` +.main-home-content section { + order: 0 !important; +} +`; + const containerStyle = document.createElement("style"); + containerStyle.innerHTML = ` #spicetify-home-config { position: relative; width: 100%; @@ -60,6 +66,7 @@ SpicetifyHomeConfig = {}; justify-content: center; align-items: flex-start; gap: 5px; + z-index: 9999; } #spicetify-home-config button { min-width: 60px; @@ -76,7 +83,8 @@ SpicetifyHomeConfig = {}; const container = document.createElement("div"); container.id = "spicetify-home-config"; - container.append(style, up, down, lower, stick); + container.append(containerStyle, up, down, lower, stick); + document.head.append(sectionStyle); let elem = []; function injectInteraction() { @@ -165,18 +173,26 @@ SpicetifyHomeConfig = {}; await new Promise(res => Spicetify.Events.webpackLoaded.on(res)); - const menu = new Spicetify.Menu.Item("Home config", false, self => { - self.isEnabled = !self.isEnabled; - if (self.isEnabled) { - injectInteraction(); - } else { - removeInteraction(); - } - }); - SpicetifyHomeConfig.addToMenu = () => menu.register(); + SpicetifyHomeConfig.menu = new Spicetify.Menu.Item( + "Home config", + false, + self => { + self.setState(!self.isEnabled); + if (self.isEnabled) { + injectInteraction(); + } else { + removeInteraction(); + } + }, + Spicetify.SVGIcons["grid-view"] + ); + + SpicetifyHomeConfig.addToMenu = () => { + SpicetifyHomeConfig.menu.register(); + }; SpicetifyHomeConfig.removeMenu = () => { - menu.isEnabled = false; - menu.deregister(); + SpicetifyHomeConfig.menu.setState(false); + SpicetifyHomeConfig.menu.deregister(); }; await new Promise(res => Spicetify.Events.platformLoaded.on(res)); diff --git a/jsHelper/sidebarConfig.js b/jsHelper/sidebarConfig.js index b0561600ce..73c5c113e5 100644 --- a/jsHelper/sidebarConfig.js +++ b/jsHelper/sidebarConfig.js @@ -174,7 +174,7 @@ color: var(--spice-button-disabled); "Sidebar config", false, self => { - self.isEnabled = !self.isEnabled; + self.setState(!self.isEnabled); if (self.isEnabled) { injectInteraction(); } else { diff --git a/src/apply/apply.go b/src/apply/apply.go index 425472abd7..3daede5fd0 100644 --- a/src/apply/apply.go +++ b/src/apply/apply.go @@ -369,9 +369,9 @@ func insertHomeConfig(jsPath string, flags Flag) { utils.ModifyFile(jsPath, func(content string) string { utils.ReplaceOnce( &content, - `([\w$_\.]+\.sections\.items)(\.map)`, + `(createDesktopHomeFeatureActivationShelfEventFactory.*?)([\w\.]+)(\.map)`, func(submatches ...string) string { - return fmt.Sprintf("SpicetifyHomeConfig.arrange(%s)%s", submatches[1], submatches[2]) + return fmt.Sprintf("%sSpicetifyHomeConfig.arrange(%s)%s", submatches[1], submatches[2], submatches[3]) }) return content }) From c77801a594ccca5aaa683778c59bc3d87b934a67 Mon Sep 17 00:00:00 2001 From: ririxi Date: Wed, 13 Mar 2024 20:10:42 +0100 Subject: [PATCH 08/54] fix(styledClassName): add another key and exclude one (#2902) --- jsHelper/spicetifyWrapper.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/jsHelper/spicetifyWrapper.js b/jsHelper/spicetifyWrapper.js index f23973b03c..c75b09a284 100644 --- a/jsHelper/spicetifyWrapper.js +++ b/jsHelper/spicetifyWrapper.js @@ -965,7 +965,8 @@ Spicetify._getStyledClassName = (args, component) => { "position", "data-encore-id", "$size", - "$iconColor" + "$iconColor", + "$variant" ]; const customKeys = ["padding", "blocksize"]; @@ -988,7 +989,7 @@ Spicetify._getStyledClassName = (args, component) => { } } - const excludedKeys = ["children", "className", "style", "dir", "key", "ref", "as", "$autoMirror", ""]; + const excludedKeys = ["children", "className", "style", "dir", "key", "ref", "as", "$autoMirror", "$hasFocus", ""]; const excludedPrefix = ["aria-"]; const childrenProps = ["iconLeading", "iconTrailing", "iconOnly"]; @@ -1002,7 +1003,8 @@ Spicetify._getStyledClassName = (args, component) => { for (const key of booleanKeys) { if (excludedKeys.includes(key)) continue; if (excludedPrefix.some(prefix => key.startsWith(prefix))) continue; - className += `-${key}`; + const sanitizedKey = key.startsWith("$") ? key.slice(1) : key; + className += `-${sanitizedKey}`; } const customEntries = Object.entries(element).filter( @@ -1010,7 +1012,8 @@ Spicetify._getStyledClassName = (args, component) => { ); for (const [key, value] of customEntries) { - className += `-${key}_${value.replace(/[^a-z0-9]/gi, "_")}`; + const sanitizedKey = key.startsWith("$") ? key.slice(1) : key; + className += `-${sanitizedKey}_${value.replace(/[^a-z0-9]/gi, "_")}`; } return className; From 5e1dce1a498c49f3b45b0153c7ab8f542f7dcc21 Mon Sep 17 00:00:00 2001 From: ririxi Date: Wed, 13 Mar 2024 22:26:30 +0100 Subject: [PATCH 09/54] fix(wrapper/MenuItem): set `isEnabled` not `_isEnabled` (#2905) --- jsHelper/spicetifyWrapper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsHelper/spicetifyWrapper.js b/jsHelper/spicetifyWrapper.js index c75b09a284..068e0841bb 100644 --- a/jsHelper/spicetifyWrapper.js +++ b/jsHelper/spicetifyWrapper.js @@ -1649,7 +1649,7 @@ Spicetify.Menu = (() => { constructor(children, isEnabled, onClick, leadingIcon) { super({ children, leadingIcon, onClick: (_, self) => onClick(self), shouldAdd }); - this._isEnabled = isEnabled; + this.isEnabled = isEnabled; } setState(state) { From c904733e22c75ca3d1b20de9bc77c466434a7f9a Mon Sep 17 00:00:00 2001 From: ririxi Date: Thu, 21 Mar 2024 02:34:56 +0100 Subject: [PATCH 10/54] fix(lyrics-plus): access props when copying translated lyrics (#2908) --- CustomApps/lyrics-plus/Pages.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CustomApps/lyrics-plus/Pages.js b/CustomApps/lyrics-plus/Pages.js index dcfa9d47fd..b84307ad17 100755 --- a/CustomApps/lyrics-plus/Pages.js +++ b/CustomApps/lyrics-plus/Pages.js @@ -456,7 +456,7 @@ const SyncedExpandedLyricsPage = react.memo(({ lyrics, provider, copyright, isKa }); const UnsyncedLyricsPage = react.memo(({ lyrics, provider, copyright }) => { - const rawLyrics = lyrics.map(lyrics => lyrics.text).join("\n"); + const rawLyrics = lyrics.map(lyrics => (typeof lyrics.text !== "object" ? lyrics.text : lyrics.text?.props?.children?.[0])).join("\n"); return react.createElement( "div", From 2a005def587a050bcde2f55babcdebdbaf6b338a Mon Sep 17 00:00:00 2001 From: ririxi Date: Thu, 21 Mar 2024 16:19:50 +0100 Subject: [PATCH 11/54] feat: add support for new global navbar (#2911) --- css-map.json | 17 ++- jsHelper/expFeatures.js | 2 +- jsHelper/spicetifyWrapper.js | 240 +++++++++++++++-------------------- src/apply/apply.go | 80 ++++++------ src/utils/utils.go | 4 +- 5 files changed, 159 insertions(+), 184 deletions(-) diff --git a/css-map.json b/css-map.json index 73a86e387d..ed66e89b30 100644 --- a/css-map.json +++ b/css-map.json @@ -1218,5 +1218,20 @@ "N5cWYDvyLrfnyMZuqQHo": "npv-nowPlayingBar-left", "gIobRDHAxkAvUaF4_OOL": "npv-nowPlayingBar-center", "FTi9QEhetf4Q4__5sb4S": "npv-nowPlayingBar-right", - "Gw7E7MkWci1ttQhb4EK0": "npv-exitFullScreenButton-button" + "Gw7E7MkWci1ttQhb4EK0": "npv-exitFullScreenButton-button", + "KAq2kDjXj2VS4eXrFL4i": "main-userWidget-box", + "LKfKy7bXKmlkMEANVJMS": "main-avatar-avatar", + "nRSfonXHVr6utXYgk2Ui": "main-globalNav-mainNav", + "Z6t_8rA6LOBrX3huqRJG": "main-globalNav-historyButtonsContainer", + "VizXsWMIuNfKGN5pMyox": "main-globalNav-historyButtons", + "rBX1EWVZ2EaPwP4y1Gkd": "main-globalNav-icon", + "W02pQCvfy5Bin7z4EAzo": "main-globalNav-searchSection", + "QrpHSphgBSqzODEHqr_t": "main-globalNav-searchContainer", + "jdlOKroADlFeZZQeTdp8": "main-globalNav-link-icon", + "PvsV2JgJRDME1vDn6IJL": "main-globalNav-searchInputSection", + "fksI89zEXwqKWm1O6sJm": "main-globalNav-searchInputContainer", + "OomFKn3bsxs5JfNUoWhz": "main-globalNav-buddyFeed", + "rQ6LXqVlEOGZdGIG0LgP": "main-contextMenu-menuItem", + "mWj8N7D_OlsbDgtQx5GW": "main-contextMenu-menuItemButton", + "NbcaczStd8vD2rHWwaKv": "main-contextMenu-menu" } diff --git a/jsHelper/expFeatures.js b/jsHelper/expFeatures.js index dbe730e225..289fc2ab69 100644 --- a/jsHelper/expFeatures.js +++ b/jsHelper/expFeatures.js @@ -273,7 +273,7 @@ ${Spicetify.SVGIcons.search} new Spicetify.Menu.Item( "Experimental features", - true, + false, () => { Spicetify.PopupModal.display({ title: "Experimental features", diff --git a/jsHelper/spicetifyWrapper.js b/jsHelper/spicetifyWrapper.js index 068e0841bb..9cef546094 100644 --- a/jsHelper/spicetifyWrapper.js +++ b/jsHelper/spicetifyWrapper.js @@ -429,6 +429,9 @@ window.Spicetify = { } catch {} }); const functionModules = modules.filter(module => typeof module === "function"); + const exportedReactObjects = Object.groupBy(modules.filter(Boolean), x => x.$$typeof); + const exportedMemos = exportedReactObjects[Symbol.for("react.memo")]; + const exportedMemoFRefs = exportedMemos.filter(m => m.type.$$typeof === Symbol.for("react.forward_ref")); const knownMenuTypes = ["album", "show", "artist", "track"]; const menus = modules @@ -551,6 +554,7 @@ window.Spicetify = { Routes: functionModules.find(m => m.toString().match(/\([\w$]+\)\{let\{children:[\w$]+,location:[\w$]+\}=[\w$]+/)), Route: functionModules.find(m => m.toString().match(/^function [\w$]+\([\w$]+\)\{\(0,[\w$]+\.[\w$]+\)\(\!1\)\}$/)), StoreProvider: functionModules.find(m => m.toString().includes("notifyNestedSubs") && m.toString().includes("serverState")), + Navigation: exportedMemoFRefs.find(m => m.type.render.toString().includes("navigationalRoot")), ...Object.fromEntries(menus) }, ReactHook: { @@ -848,6 +852,7 @@ window.Spicetify = { })(); Spicetify.Events.webpackLoaded.fire(); + refreshNavLinks?.(); })(); Spicetify.Events = (() => { @@ -1391,6 +1396,26 @@ Spicetify.SVGIcons = { return document.head.appendChild(fontStyle); })(); +function parseIcon(icon, size = 16) { + if (icon && Spicetify.SVGIcons[icon]) { + return `${Spicetify.SVGIcons[icon]}`; + } + return icon || ""; +} + +function createIconComponent(icon, size = 16) { + return Spicetify.React.createElement( + Spicetify.ReactComponent.IconComponent, + { + iconSize: size, + dangerouslySetInnerHTML: { + __html: parseIcon(icon) + } + }, + null + ); +} + Spicetify.ContextMenuV2 = (() => { const registeredItems = new Map(); @@ -1409,26 +1434,6 @@ Spicetify.ContextMenuV2 = (() => { return [uris, uids, contextUri]; } - function parseIcon(icon) { - if (icon && Spicetify.SVGIcons[icon]) { - return `${Spicetify.SVGIcons[icon]}`; - } - return icon || ""; - } - - function createIconComponent(icon) { - return Spicetify.React.createElement( - Spicetify.ReactComponent.IconComponent, - { - iconSize: "16", - dangerouslySetInnerHTML: { - __html: parseIcon(icon) - } - }, - null - ); - } - // these classes bridge the gap between react and js, insuring reactivity class Item { constructor({ children, disabled = false, leadingIcon, trailingIcon, divider, onClick, shouldAdd = () => true }) { @@ -1753,47 +1758,27 @@ Spicetify.ContextMenu = (() => { return { Item, SubMenu }; })(); -Spicetify._cloneSidebarItem = (list, isLibX = false) => { - function findChild(parent, key, value) { - if (!parent.props) { - return null; - } - - if (value && parent.props[key]?.includes(value)) { - return parent; - } - if (!parent.props.children) { - return null; - } - if (Array.isArray(parent.props.children)) { - for (const child of parent.props.children) { - const ele = findChild(child, key, value); - if (ele) { - return ele; - } - } - } else if (parent.props.children) { - return findChild(parent.props.children, key, value); - } - return null; - } - - function conditionalAppend(baseClassname, activeClassname, location) { - if (Spicetify.Platform?.History?.location?.pathname.startsWith(location)) { - return `${baseClassname} ${activeClassname}`; - } +let navLinkFactoryCtx = null; +let refreshNavLinks = null; - return baseClassname; - } +Spicetify._renderNavLinks = (list, isTouchScreenUi) => { + const [refreshCount, refresh] = Spicetify.React.useReducer(x => x + 1, 0); + refreshNavLinks = refresh; - if (!Spicetify.React) { - setTimeout(Spicetify._cloneSidebarItem, 10, list, isLibX); + if ( + !Spicetify.ReactComponent.ButtonTertiary || + !Spicetify.ReactComponent.Navigation || + !Spicetify.ReactComponent.TooltipWrapper || + !Spicetify.Platform.History || + !Spicetify.Platform.LocalStorageAPI + ) { return; } - const React = Spicetify.React; - const reactObjs = []; - const sidebarIsCollapsed = Spicetify.Platform?.LocalStorageAPI?.getItem?.("ylx-sidebar-state") === 1; + const navLinkFactory = isTouchScreenUi ? NavLinkGlobal : NavLinkSidebar; + + if (!navLinkFactoryCtx) navLinkFactoryCtx = Spicetify.React.createContext(null); + const registered = []; for (const app of list) { let manifest; @@ -1815,90 +1800,69 @@ Spicetify._cloneSidebarItem = (list, isLibX = false) => { } const icon = manifest.icon || ""; const activeIcon = manifest["active-icon"] || icon; + const appRoutePath = `/${app}`; + registered.push({ appProper, appRoutePath, icon, activeIcon }); + } - const appLink = `/${app}`; - let obj; - let link; - - if (isLibX) { - link = findChild(Spicetify._sidebarXItemToClone, "className", "main-yourLibraryX-navLink"); - obj = React.cloneElement( - Spicetify._sidebarXItemToClone, - null, - React.cloneElement( - Spicetify._sidebarXItemToClone.props.children, - { - label: sidebarIsCollapsed ? appProper : "" - }, - React.cloneElement( - link, - { - to: appLink, - isActive: (e, { pathname: t }) => t.startsWith(appLink), - className: conditionalAppend("link-subtle main-yourLibraryX-navLink", "main-yourLibraryX-navLinkActive", appLink) - }, - React.createElement(Spicetify.ReactComponent.IconComponent, { - className: "home-icon", - iconSize: "24", - dangerouslySetInnerHTML: { - __html: icon - } - }), - React.createElement(Spicetify.ReactComponent.IconComponent, { - className: "home-active-icon", - iconSize: "24", - dangerouslySetInnerHTML: { - __html: activeIcon - } - }), - !sidebarIsCollapsed && - React.createElement( - Spicetify.ReactComponent.TextComponent, - { - variant: "balladBold" - }, - appProper - ) - ) - ) - ); - } else { - link = findChild(Spicetify._sidebarItemToClone, "className", "main-navBar-navBarLink"); - obj = React.cloneElement( - Spicetify._sidebarItemToClone, - null, - React.cloneElement( - link, - { - to: appLink, - isActive: (e, { pathname: t }) => t.startsWith(appLink), - className: conditionalAppend("link-subtle main-navBar-navBarLink", "main-navBar-navBarLinkActive", appLink) - }, - React.createElement("div", { - className: "icon collection-icon", - dangerouslySetInnerHTML: { - __html: icon - } - }), - React.createElement("div", { - className: "icon collection-active-icon", - dangerouslySetInnerHTML: { - __html: activeIcon - } - }), - React.createElement( - "span", - { - className: "ellipsis-one-line main-type-mestoBold" - }, - appProper - ) - ) - ); - } - reactObjs.push(obj); + return Spicetify.React.createElement( + navLinkFactoryCtx.Provider, + { value: navLinkFactory }, + registered.map(NavLinkElement => Spicetify.React.createElement(NavLink, NavLinkElement, null)) + ); +}; + +const NavLink = ({ appProper, appRoutePath, icon, activeIcon }) => { + const isActive = Spicetify.Platform.History.location.pathname?.startsWith(appRoutePath); + const createIcon = () => createIconComponent(isActive ? activeIcon : icon, 24); + + const NavLinkFactory = Spicetify.React.useContext(navLinkFactoryCtx); + if (!NavLinkFactory) { + return; } - return reactObjs; + + return Spicetify.React.createElement(NavLinkFactory, { appProper, appRoutePath, createIcon, isActive }, null); +}; + +const NavLinkSidebar = ({ appProper, appRoutePath, createIcon, isActive }) => { + const isSidebarCollapsed = Spicetify.Platform.LocalStorageAPI.getItem("ylx-sidebar-state") === 1; + + return Spicetify.React.createElement( + "li", + { className: "main-yourLibraryX-navItem InvalidDropTarget" }, + Spicetify.React.createElement( + Spicetify.ReactComponent.TooltipWrapper, + { label: isSidebarCollapsed ? appProper : null, disabled: !isSidebarCollapsed, placement: "right" }, + Spicetify.React.createElement( + Spicetify.ReactComponent.Navigation, + { + to: appRoutePath, + referrer: "other", + className: Spicetify.classnames("link-subtle", "main-yourLibraryX-navLink", { + "main-yourLibraryX-navLinkActive": isActive + }), + onClick: () => undefined, + "aria-label": appProper + }, + createIcon(), + !isSidebarCollapsed && Spicetify.React.createElement(Spicetify.ReactComponent.TextWrapper, { variant: "bodyMediumBold" }, appProper) + ) + ) + ); +}; + +const NavLinkGlobal = ({ appProper, appRoutePath, createIcon, isActive }) => { + return Spicetify.React.createElement( + Spicetify.ReactComponent.TooltipWrapper, + { label: appProper }, + Spicetify.React.createElement(Spicetify.ReactComponent.ButtonTertiary, { + iconOnly: createIcon, + className: Spicetify.classnames("bWBqSiXEceAj1SnzqusU", "main-globalNav-link-icon", "cUwQnQoE3OqXqSYLT0hv", { + voA9ZoTTlPFyLpckNw3S: isActive + }), + "aria-label": appProper, + onClick: () => Spicetify.Platform.History.push(appRoutePath) + }) + ); }; class _HTMLGenericModal extends HTMLElement { diff --git a/src/apply/apply.go b/src/apply/apply.go index 3daede5fd0..e7137199b5 100644 --- a/src/apply/apply.go +++ b/src/apply/apply.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "path/filepath" + "regexp" "strings" "github.com/spicetify/spicetify-cli/src/utils" @@ -288,19 +289,7 @@ func insertCustomApp(jsPath string, flags Flag) { return fmt.Sprintf("%s%s", appEleMap, submatches[0]) }) - utils.Replace( - &content, - `(?:\w+(?:\(\))?\.createElement|\([\w$\.,]+\))\("li",\{className:[\w$\.]+\}?,(?:children:)?[\w$\.,()]+\(\w+,\{uri:"spotify:user:@:collection",to:"/collection"`, - func(submatches ...string) string { - return fmt.Sprintf("Spicetify._sidebarItemToClone=%s", submatches[0]) - }) - - utils.Replace( - &content, - `(?:\w+(?:\(\))?\.createElement|\([\w$.,_]+\))\("li",{className:[-\w".${}()?!:, ]+,children:(?:\w+(?:\(\))?\.createElement|\([\w$.,_]+\))\([\w$._]+,{label:[-\w".${}()?!:, ]+,(\w+:[-\w".${}()?!&: ]+,)*children:(?:\w+(?:\(\))?\.createElement|\([\w$.,_]+\))\([\w$._]+,\{to:"/search"`, - func(submatches ...string) string { - return fmt.Sprintf("Spicetify._sidebarXItemToClone=%s", submatches[0]) - }) + content = insertNavLink(content, appNameArray) utils.ReplaceOnce( &content, @@ -309,36 +298,6 @@ func insertCustomApp(jsPath string, flags Flag) { return fmt.Sprintf("%s%s", submatches[0], cssEnableMap) }) - sidebarItemMatch := utils.SeekToCloseParen( - content, - `\("li",\{className:[\w$\.]+\}?,(?:children:)?[\w$\.,()]+\(\w+,\{uri:"spotify:user:@:collection",to:"/collection"`, - '(', ')') - - // Prevent breaking on future Spotify update - if sidebarItemMatch != "" { - content = strings.Replace( - content, - sidebarItemMatch, - sidebarItemMatch+",Spicetify._cloneSidebarItem(["+appNameArray+"])", - 1) - } - - sidebarXItemMatch := utils.SeekToCloseParen( - content, - `\("li",{className:[-\w".${}()?!:, ]+,children:(?:\w+(?:\(\))?\.createElement|\([\w$.,_]+\))\([\w$._]+,{label:[-\w".${}()?!:, ]+,(\w+:[-\w".${}()?!&: ]+,)*children:(?:\w+(?:\(\))?\.createElement|\([\w$.,_]+\))\([\w$._]+,\{to:"/search"`, - '(', ')') - - // Prevent breaking on future Spotify update - if sidebarXItemMatch != "" { - content = strings.Replace( - content, - sidebarXItemMatch, - sidebarXItemMatch+",Spicetify._cloneSidebarItem(["+appNameArray+"],true)", - 1) - } else { - utils.PrintWarning("Sidebar X item not found, ignoring") - } - if flags.SidebarConfig { utils.ReplaceOnce( &content, @@ -361,6 +320,41 @@ func insertCustomApp(jsPath string, flags Flag) { }) } +func findMatchingPos(str string, start int, direction int, pair []string, scopes int) int { + l := scopes + i := start + direction + + for l > 0 { + c := string(str[i]) + i += direction + if c == pair[0] { + l++ + } else if c == pair[1] { + l-- + } + } + + return i +} + +func insertNavLink(str string, appNameArray string) string { + // Library X + re := regexp.MustCompile(`\("li",\{[^\{]*\{[^\{]*\{to:"\/search`) + loc := re.FindStringIndex(str) + if loc == nil { + return str + } + index := findMatchingPos(str, loc[0], 1, []string{"(", ")"}, 1) + str = str[:index] + ",Spicetify._renderNavLinks([" + appNameArray + "], false)," + str[index:] + + // Global Navbar + utils.ReplaceOnce(&str, `(,[a-zA-Z_\$][\w\$]*===(?:[a-zA-Z_\$][\w\$]*\.){2}HOME_NEXT_TO_NAVIGATION&&.+?)\]`, func(submatches ...string) string { + return submatches[1] + ",Spicetify._renderNavLinks([" + appNameArray + "], true)]" + }) + + return str +} + func insertHomeConfig(jsPath string, flags Flag) { if !flags.HomeConfig { return diff --git a/src/utils/utils.go b/src/utils/utils.go index 2298b7385b..a4e18ba841 100644 --- a/src/utils/utils.go +++ b/src/utils/utils.go @@ -179,7 +179,9 @@ func ReplaceOnce(str *string, pattern string, repl func(submatches ...string) st if firstMatch { firstMatch = false submatches := re.FindStringSubmatch(match) - return repl(submatches...) + if submatches != nil { + return repl(submatches...) + } } return match }) From 3cf05686baf1beb76a4ab7b9962b3479809d4239 Mon Sep 17 00:00:00 2001 From: ririxi Date: Thu, 21 Mar 2024 16:52:31 +0100 Subject: [PATCH 12/54] fix(NavLinkSidebar): use `TextComponent`, not `TextWrapper` (#2912) --- jsHelper/spicetifyWrapper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsHelper/spicetifyWrapper.js b/jsHelper/spicetifyWrapper.js index 9cef546094..40cd0d9261 100644 --- a/jsHelper/spicetifyWrapper.js +++ b/jsHelper/spicetifyWrapper.js @@ -1844,7 +1844,7 @@ const NavLinkSidebar = ({ appProper, appRoutePath, createIcon, isActive }) => { "aria-label": appProper }, createIcon(), - !isSidebarCollapsed && Spicetify.React.createElement(Spicetify.ReactComponent.TextWrapper, { variant: "bodyMediumBold" }, appProper) + !isSidebarCollapsed && Spicetify.React.createElement(Spicetify.ReactComponent.TextComponent, { variant: "bodyMediumBold" }, appProper) ) ) ); From 9ef07f95f77f6012a2bf8e9e87045ed05af81d7c Mon Sep 17 00:00:00 2001 From: Brandon Chen <90290521+b-chen00@users.noreply.github.com> Date: Fri, 22 Mar 2024 20:25:43 -0400 Subject: [PATCH 13/54] docs: create `contributing.md` (#2915) Co-authored-by: ririxi --- CONTRIBUTING.md | 120 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..7468ea5e22 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,120 @@ +# Contributing to Spicetify-cli + +## Table of Contents + +- [I Have a Question](#i-have-a-question) +- [How to Contribute](#how-to-contribute) + - [Reporting Bugs](#reporting-bugs) + - [Suggesting Enhancements](#suggesting-enhancements) + - [Your First Code Contribution](#your-first-code-contribution) + - [Improving The Documentation](#improving-the-documentation) + - [Commit Message Format](#commit-message-format) + +## I Have a Question + +> If you want to ask a question, we assume that you have read the available [Documentation](https://spicetify.app/docs/getting-started/). + +Before you ask a question, it is best to search for existing [issues](https://github.com/spicetify/spicetify-cli/issues) that might help you. In case you have found a suitable issue and still need clarification, you can write your question in this issue. It is also advisable to search the internet for answers first. + +If you then still feel the need to ask a question and need clarification, we recommend the following: + +- Open an [issue](https://github.com/spicetify/spicetify-cli/issues/new). +- Provide both Spicetify and Spotify version. +- Explain what the problem is. + +We will then take care of the issue as soon as possible. + +## How to Contribute + +> ### Legal Notice +> When contributing to this project, you must agree that you have authored 100% of the content, that you have the necessary rights to the content and that the content you contribute may be provided under the project license. + +### Reporting Bugs + +#### Before Submitting a Bug Report + +A good bug report shouldn't leave others needing to chase you up for more information. Therefore, we ask you to investigate carefully, collect information and describe the issue in detail in your report. Please complete the following steps in advance to help us fix any potential bug as fast as possible. + +- Make sure that you are using the latest version. +- Determine if your bug is really a bug and not an error on your side e.g. using incompatible environment components/versions (Make sure that you have read the [documentation](https://spicetify.app/docs/getting-started/). If you are looking for support, you might want to check [this section](#i-have-a-question)). +- To see if other users have experienced (and potentially already solved) the same issue you are having, check if there is not already a bug report existing for your bug or error in the [bug tracker](https://github.com/spicetify/spicetify-cli/labels/%F0%9F%90%9B%20bug). + +#### How Do I Submit a Good Bug Report? + +We use GitHub issues to track bugs and errors. If you run into an issue with the project: + +- Open an [issue](https://github.com/spicetify/spicetify-cli/issues/new). (Since we can't be sure at this point whether it is a bug or not, we ask you not to talk about a bug yet and not to label the issue.) + - Use the provided [bug template](https://github.com/spicetify/spicetify-cli/issues/new?assignees=&labels=%F0%9F%90%9B+bug&projects=&template=bug_report.yml). +- Explain the behavior you would expect and the actual behavior. +- Please provide as much context as possible and describe the *reproduction steps* that someone else can follow to recreate the issue on their own. This usually includes your code. For good bug reports you should isolate the problem and create a reduced test case. +- Provide the information you collected in the previous section. + +### Suggesting Enhancements + +This section guides you through submitting an enhancement suggestion for spicetify, **including completely new features and minor improvements to existing functionality**. Following these guidelines will help maintainers and the community to understand your suggestion and find related suggestions. + +#### Before Submitting an Enhancement + +- Make sure that you are using the latest version. +- Read the [documentation](https://spicetify.app/docs/getting-started/) carefully and find out if the functionality is already covered, maybe by an individual configuration. +- Perform a [search](https://github.com/spicetify/spicetify-cli/issues) to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one. +- Find out whether your idea fits with the scope and aims of the project. It's up to you to make a strong case to convince the project's developers of the merits of this feature. Keep in mind that we want features that will be useful to the majority of our users and not just a small subset. If you're just targeting a minority of users, consider writing an add-on/plugin library. + +#### How Do I Submit a Good Enhancement Suggestion? + +Enhancement suggestions are tracked as [GitHub issues](https://github.com/spicetify/spicetify-cli/issues). Create an enhancement suggestion using the provided [feature request template](https://github.com/spicetify/spicetify-cli/issues/new?assignees=&labels=%E2%9C%A8+feature&projects=&template=feature_request.yml). + +- Use a **clear and descriptive title** for the issue to identify the suggestion. +- Provide a **step-by-step description of the suggested enhancement** in as many details as possible. +- **Describe the current behavior** and **explain which behavior you expected to see instead** and why. At this point you can also tell which alternatives do not work for you. +- For GUIs, you may want to **include screenshots** which help you demonstrate the steps or point out the part which the suggestion is related to. Animated GIFS and videos may be helpful but are not expected. Some tools available are the [built-in screen recorder](https://support.apple.com/en-us/102618) on macOS, [LICEcap](https://www.cockos.com/licecap/) on macOS and Windows, and [ShareX](https://getsharex.com/) on Linux. +- **Explain why this enhancement would be useful** to most spicetify users. You may also want to point out the other projects that solved it better and which could serve as inspiration. + +### Your First Code Contribution + +#### Requirements + +- [Go](https://go.dev/dl/) + +#### Environment Setup and Development + +Follow the steps outlined in the [documentation](https://spicetify.app/docs/development/compiling) or the steps below. +1. Clone the repository using `git clone https://github.com/spicetify/spicetify-cli`. +2. Enter the repository directory and build the project. + * Windows + ``` + cd spicetify-cli + go build -o spicetify.exe + ``` + * Linux and MacOS + ``` + cd spicetify-cli + go build -o spicetify + ``` +3. Execute the executable file generated by `go build` using `./spicetify` or `./spicetify.exe`. + +### Improving The Documentation + +To improve the [documentation](https://spicetify.app/docs/getting-started), navigate to the documentation [repository](https://github.com/spicetify/spicetify-docs). + +### Commit Message Format + + (): + + [optional] + +* **type:** feat | fix | docs | chore | revert + * **feat:** A new feature + * **fix:** A bug fix + * **docs:** Documentation only changes + * **chore:** Changes to build process, auxiliary tools, libraries, and other things + * **revert:** A reversion to a previous commit +* **scope:** Anything specifying place of the commit change +* **subject:** What changes you have done + * Use the imperative, present tense: "change" not "changed" nor "changes" + * Don't capitalize first letter + * No dot (.) at the end +* **body**: More details of your changes, you can mention the most important changes here + * Use the imperative, present tense: "change" not "changed" nor "changes" + +If you want to learn more, view the [Angular - Git Commit Guidelines](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines). From cac4af86b09fc29f6f7b03655216870048550ea6 Mon Sep 17 00:00:00 2001 From: ririxi Date: Mon, 25 Mar 2024 01:07:51 +0100 Subject: [PATCH 14/54] feat(config): add another folder to `potentialList` (#2916) --- CustomApps/lyrics-plus/TabBar.js | 2 +- CustomApps/new-releases/Card.js | 4 ++-- CustomApps/reddit/TabBar.js | 2 +- biome.json | 2 +- src/utils/config.go | 5 +++-- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CustomApps/lyrics-plus/TabBar.js b/CustomApps/lyrics-plus/TabBar.js index d82dfc6c8a..6bdf4f4c72 100644 --- a/CustomApps/lyrics-plus/TabBar.js +++ b/CustomApps/lyrics-plus/TabBar.js @@ -196,7 +196,7 @@ const TabBar = react.memo(({ links, activeLink, lockLink, switchCallback, lockCa items: droplistItem.map(i => options[i]).filter(Boolean), switchTo: switchCallback, lockIn: lockCallback - }) + }) : null ) ); diff --git a/CustomApps/new-releases/Card.js b/CustomApps/new-releases/Card.js index 4f661277cb..c731b8b7ca 100644 --- a/CustomApps/new-releases/Card.js +++ b/CustomApps/new-releases/Card.js @@ -4,7 +4,7 @@ function DraggableComponent({ uri, title, children }) { ? react.cloneElement(children, { onDragStart: dragHandler, draggable: "true" - }) + }) : children; } @@ -53,7 +53,7 @@ class Card extends react.Component { }) }) }) - }) + }) : Spicetify.showNotification(`Dismissed ${this.title} from
${this.artist.name}`); event.stopPropagation(); diff --git a/CustomApps/reddit/TabBar.js b/CustomApps/reddit/TabBar.js index 985d268e6a..f4aa20d942 100644 --- a/CustomApps/reddit/TabBar.js +++ b/CustomApps/reddit/TabBar.js @@ -166,7 +166,7 @@ const TabBar = react.memo(({ links, activeLink, switchCallback, windowSize = Num ? react.createElement(TabBarMore, { items: droplistItem.map(i => options[i]).filter(Boolean), switchTo: switchCallback - }) + }) : null ) ); diff --git a/biome.json b/biome.json index adc1776243..6a38d87d0d 100644 --- a/biome.json +++ b/biome.json @@ -1,5 +1,5 @@ { - "$schema": "https://biomejs.dev/schemas/1.6.0/schema.json", + "$schema": "https://biomejs.dev/schemas/1.6.2/schema.json", "organizeImports": { "enabled": true }, diff --git a/src/utils/config.go b/src/utils/config.go index bcdd499db7..324115b155 100644 --- a/src/utils/config.go +++ b/src/utils/config.go @@ -304,11 +304,12 @@ func linuxApp() string { "/usr/share/spotify/", "/usr/libexec/spotify/", "/var/lib/flatpak/app/com.spotify.Client/x86_64/stable/active/files/extra/share/spotify/", + "$HOME/.local/share/flatpak/app/com.spotify.Client/x86_64/stable/active/files/extra/share/spotify/", } for _, v := range potentialList { - _, err := os.Stat(filepath.Join(v, "Apps")) - _, err2 := os.Stat(filepath.Join(v, "spotify")) + _, err := os.Stat(filepath.Join(ReplaceEnvVarsInString(v), "Apps")) + _, err2 := os.Stat(filepath.Join(ReplaceEnvVarsInString(v), "spotify")) if err == nil && err2 == nil { return v } From 6f88fb6b8e2624176cde72d35e1c096cb9f44dbb Mon Sep 17 00:00:00 2001 From: ririxi Date: Mon, 25 Mar 2024 01:09:01 +0100 Subject: [PATCH 15/54] fix: make various changes to global navbar (#2913) Co-authored-by: Delusoire Co-authored-by: harbassan <84175605+harbassan@users.noreply.github.com> --- css-map.json | 5 +- jsHelper/spicetifyWrapper.js | 130 +++++++++++++++++++++++++++-------- src/apply/apply.go | 4 +- src/preprocess/preprocess.go | 8 ++- 4 files changed, 114 insertions(+), 33 deletions(-) diff --git a/css-map.json b/css-map.json index ed66e89b30..0f81360dec 100644 --- a/css-map.json +++ b/css-map.json @@ -1221,7 +1221,7 @@ "Gw7E7MkWci1ttQhb4EK0": "npv-exitFullScreenButton-button", "KAq2kDjXj2VS4eXrFL4i": "main-userWidget-box", "LKfKy7bXKmlkMEANVJMS": "main-avatar-avatar", - "nRSfonXHVr6utXYgk2Ui": "main-globalNav-mainNav", + "nRSfonXHVr6utXYgk2Ui": "Root__globalNav", "Z6t_8rA6LOBrX3huqRJG": "main-globalNav-historyButtonsContainer", "VizXsWMIuNfKGN5pMyox": "main-globalNav-historyButtons", "rBX1EWVZ2EaPwP4y1Gkd": "main-globalNav-icon", @@ -1231,6 +1231,9 @@ "PvsV2JgJRDME1vDn6IJL": "main-globalNav-searchInputSection", "fksI89zEXwqKWm1O6sJm": "main-globalNav-searchInputContainer", "OomFKn3bsxs5JfNUoWhz": "main-globalNav-buddyFeed", + "bWBqSiXEceAj1SnzqusU": "main-globalNav-navLink", + "voA9ZoTTlPFyLpckNw3S": "main-globalNav-navLinkActive", + "cUwQnQoE3OqXqSYLT0hv": "link-subtle", "rQ6LXqVlEOGZdGIG0LgP": "main-contextMenu-menuItem", "mWj8N7D_OlsbDgtQx5GW": "main-contextMenu-menuItemButton", "NbcaczStd8vD2rHWwaKv": "main-contextMenu-menu" diff --git a/jsHelper/spicetifyWrapper.js b/jsHelper/spicetifyWrapper.js index 40cd0d9261..ddd84620d4 100644 --- a/jsHelper/spicetifyWrapper.js +++ b/jsHelper/spicetifyWrapper.js @@ -90,9 +90,7 @@ window.Spicetify = { return await Spicetify.Player.origin.play({ uri: uri }, context, options); }, removeEventListener: (type, callback) => { - if (!(type in Spicetify.Player.eventListeners)) { - return; - } + if (!(type in Spicetify.Player.eventListeners)) return; const stack = Spicetify.Player.eventListeners[type]; for (let i = 0; i < stack.length; i++) { if (stack[i] === callback) { @@ -163,9 +161,6 @@ window.Spicetify = { "Topbar", "ReactComponent", "PopupModal", - "_cloneSidebarItem", - // Deprecated since Spotify 1.2.14 - // "_sidebarItemToClone", "SVGIcons", "colorExtractor", "test", @@ -182,7 +177,6 @@ window.Spicetify = { "_getStyledClassName", "GraphQL", "ReactHook", - "_sidebarXItemToClone", "AppTitle", "_reservedPanelIds", "ReactFlipToolkit", @@ -193,7 +187,8 @@ window.Spicetify = { "ReactDOMServer", "Snackbar", "ContextMenuV2", - "ReactJSX" + "ReactJSX", + "_renderNavLinks" ]) }, { @@ -428,8 +423,17 @@ window.Spicetify = { return Object.values(module); } catch {} }); + // polyfill for chromium <117 + const groupBy = (values, keyFinder) => { + if (typeof Object.groupBy === "function") return Object.groupBy(values, keyFinder); + return values.reduce((a, b) => { + const key = typeof keyFinder === "function" ? keyFinder(b) : b[keyFinder]; + a[key] = a[key] ? [...a[key], b] : [b]; + return a; + }, {}); + }; const functionModules = modules.filter(module => typeof module === "function"); - const exportedReactObjects = Object.groupBy(modules.filter(Boolean), x => x.$$typeof); + const exportedReactObjects = groupBy(modules.filter(Boolean), x => x.$$typeof); const exportedMemos = exportedReactObjects[Symbol.for("react.memo")]; const exportedMemoFRefs = exportedMemos.filter(m => m.type.$$typeof === Symbol.for("react.forward_ref")); @@ -483,6 +487,10 @@ window.Spicetify = { ReactJSX: cache.find(m => m?.jsx), ReactDOM: cache.find(m => m?.createPortal), ReactDOMServer: cache.find(m => m?.renderToString), + // classnames for 1.2.13 + classnames: cache + .filter(module => typeof module === "function") + .find(module => module.toString().includes('"string"') && module.toString().includes("[native code]")), Color: functionModules.find(m => m.toString().includes("static fromHex") || m.toString().includes("this.rgb")), Player: { ...Spicetify.Player, @@ -555,6 +563,7 @@ window.Spicetify = { Route: functionModules.find(m => m.toString().match(/^function [\w$]+\([\w$]+\)\{\(0,[\w$]+\.[\w$]+\)\(\!1\)\}$/)), StoreProvider: functionModules.find(m => m.toString().includes("notifyNestedSubs") && m.toString().includes("serverState")), Navigation: exportedMemoFRefs.find(m => m.type.render.toString().includes("navigationalRoot")), + ScrollableContainer: functionModules.find(m => m.toString().includes("scrollLeft") && m.toString().includes("showButtons")), ...Object.fromEntries(menus) }, ReactHook: { @@ -675,7 +684,7 @@ window.Spicetify = { // classnames // https://github.com/JedWatson/classnames/ const classnamesChunk = chunks.find(([_, value]) => value.toString().includes("[native code]") && !value.toString().includes("")); - if (classnamesChunk) { + if (classnamesChunk && !Spicetify.classnames) { Spicetify.classnames = Object.values(require(classnamesChunk[0])).find(m => typeof m === "function"); } @@ -719,6 +728,7 @@ window.Spicetify = { autoHideDuration: msTimeout }); }; + return; } @@ -994,7 +1004,7 @@ Spicetify._getStyledClassName = (args, component) => { } } - const excludedKeys = ["children", "className", "style", "dir", "key", "ref", "as", "$autoMirror", "$hasFocus", ""]; + const excludedKeys = ["children", "className", "style", "dir", "key", "ref", "as", "isUsingKeyboard", "$autoMirror", "$hasFocus", ""]; const excludedPrefix = ["aria-"]; const childrenProps = ["iconLeading", "iconTrailing", "iconOnly"]; @@ -1771,9 +1781,8 @@ Spicetify._renderNavLinks = (list, isTouchScreenUi) => { !Spicetify.ReactComponent.TooltipWrapper || !Spicetify.Platform.History || !Spicetify.Platform.LocalStorageAPI - ) { + ) return; - } const navLinkFactory = isTouchScreenUi ? NavLinkGlobal : NavLinkSidebar; @@ -1804,11 +1813,47 @@ Spicetify._renderNavLinks = (list, isTouchScreenUi) => { registered.push({ appProper, appRoutePath, icon, activeIcon }); } - return Spicetify.React.createElement( - navLinkFactoryCtx.Provider, - { value: navLinkFactory }, - registered.map(NavLinkElement => Spicetify.React.createElement(NavLink, NavLinkElement, null)) - ); + const style = document.createElement("style"); + style.innerHTML = ` +:root { + --max-custom-navlink-count: 4; +} + +.custom-navlinks-scrollable_container { + max-width: calc(48px * var(--max-custom-navlink-count) + 8px * (var(--max-custom-navlink-count) - 1)); + -webkit-app-region: no-drag; +} + +.custom-navlinks-scrollable_container div[role="presentation"] > *:not(:last-child) { + margin-inline-end: 8px; +} + +.custom-navlinks-scrollable_container div[role="presentation"] { + display: flex; + flex-direction: row; +} + +.custom-navlink { + -webkit-app-region: unset; +} + `; + document.head.appendChild(style); + + const wrapScrollableContainer = element => + Spicetify.React.createElement( + "div", + { className: "custom-navlinks-scrollable_container" }, + Spicetify.React.createElement(Spicetify.ReactComponent.ScrollableContainer, null, element) + ); + + const NavLinks = () => + Spicetify.React.createElement( + navLinkFactoryCtx.Provider, + { value: navLinkFactory }, + registered.map(NavLinkElement => Spicetify.React.createElement(NavLink, NavLinkElement, null)) + ); + + return isTouchScreenUi ? wrapScrollableContainer(NavLinks()) : NavLinks(); }; const NavLink = ({ appProper, appRoutePath, icon, activeIcon }) => { @@ -1816,11 +1861,8 @@ const NavLink = ({ appProper, appRoutePath, icon, activeIcon }) => { const createIcon = () => createIconComponent(isActive ? activeIcon : icon, 24); const NavLinkFactory = Spicetify.React.useContext(navLinkFactoryCtx); - if (!NavLinkFactory) { - return; - } - return Spicetify.React.createElement(NavLinkFactory, { appProper, appRoutePath, createIcon, isActive }, null); + return NavLinkFactory && Spicetify.React.createElement(NavLinkFactory, { appProper, appRoutePath, createIcon, isActive }, null); }; const NavLinkSidebar = ({ appProper, appRoutePath, createIcon, isActive }) => { @@ -1844,7 +1886,8 @@ const NavLinkSidebar = ({ appProper, appRoutePath, createIcon, isActive }) => { "aria-label": appProper }, createIcon(), - !isSidebarCollapsed && Spicetify.React.createElement(Spicetify.ReactComponent.TextComponent, { variant: "bodyMediumBold" }, appProper) + !isSidebarCollapsed && + Spicetify.React.createElement(Spicetify.ReactComponent.TextComponent, { variant: "bodyMediumBold", weight: "bold" }, appProper) ) ) ); @@ -1856,8 +1899,8 @@ const NavLinkGlobal = ({ appProper, appRoutePath, createIcon, isActive }) => { { label: appProper }, Spicetify.React.createElement(Spicetify.ReactComponent.ButtonTertiary, { iconOnly: createIcon, - className: Spicetify.classnames("bWBqSiXEceAj1SnzqusU", "main-globalNav-link-icon", "cUwQnQoE3OqXqSYLT0hv", { - voA9ZoTTlPFyLpckNw3S: isActive + className: Spicetify.classnames("link-subtle", "main-globalNav-navLink", "main-globalNav-link-icon", "custom-navlink", { + "main-globalNav-navLinkActive": isActive }), "aria-label": appProper, onClick: () => Spicetify.Platform.History.push(appRoutePath) @@ -1971,12 +2014,22 @@ Spicetify.Topbar = (() => { this.label = label; this.element.appendChild(this.button); + const globalHistoryButtons = document.querySelector(".main-globalNav-historyButtons"); if (isRight) { this.button.classList.add("encore-over-media-set", "main-topBar-buddyFeed"); + if (globalHistoryButtons) this.button.classList.add("main-globalNav-buddyFeed"); + rightButtonsStash.add(this.element); rightContainer?.prepend(this.element); } else { this.button.classList.add("main-topBar-button"); + if (globalHistoryButtons) { + this.button.classList.add( + "main-globalNav-icon", + "Button-medium-medium-buttonTertiary-iconOnly-condensed-disabled-useBrowserDefaultFocusStyle" + ); + } + leftButtonsStash.add(this.element); leftContainer?.append(this.element); } @@ -2019,18 +2072,38 @@ Spicetify.Topbar = (() => { } function waitForTopbarMounted() { - leftContainer = document.querySelector(".main-topBar-historyButtons"); + const globalHistoryButtons = document.querySelector(".main-globalNav-historyButtons"); + leftContainer = document.querySelector(".main-topBar-historyButtons") ?? globalHistoryButtons; rightContainer = document.querySelector(".main-actionButtons"); if (!leftContainer || !rightContainer) { setTimeout(waitForTopbarMounted, 100); return; } + + if (globalHistoryButtons) globalHistoryButtons.style = "gap: 4px; padding-inline: 4px 4px"; for (const button of leftButtonsStash) { if (button.parentNode) button.parentNode.removeChild(button); + + const buttonElement = button.querySelector("button"); + if (globalHistoryButtons) { + buttonElement.classList.add( + "main-globalNav-icon", + "Button-medium-medium-buttonTertiary-iconOnly-condensed-disabled-useBrowserDefaultFocusStyle" + ); + } else { + buttonElement.classList.remove( + "main-globalNav-icon", + "Button-medium-medium-buttonTertiary-iconOnly-condensed-disabled-useBrowserDefaultFocusStyle" + ); + } } leftContainer.append(...leftButtonsStash); for (const button of rightButtonsStash) { if (button.parentNode) button.parentNode.removeChild(button); + + const buttonElement = button.querySelector("button"); + if (globalHistoryButtons) buttonElement.classList.add("main-globalNav-buddyFeed"); + else buttonElement.classList.remove("main-globalNav-buddyFeed"); } rightContainer.prepend(...rightButtonsStash); } @@ -2041,6 +2114,7 @@ Spicetify.Topbar = (() => { setTimeout(waitForPlatform, 100); return; } + Spicetify.Platform.History.listen(() => waitForTopbarMounted()); })(); @@ -2254,9 +2328,7 @@ Spicetify.Playbar = (() => { } const { check_spicetify_update, version } = Spicetify.Config; // Skip checking if upgrade check is disabled, or version is Dev/version is not set - if (!check_spicetify_update || !version || version === "Dev") { - return; - } + if (!check_spicetify_update || !version || version === "Dev") return; // Fetch latest version from GitHub try { const res = await fetch("https://api.github.com/repos/spicetify/spicetify-cli/releases/latest"); diff --git a/src/apply/apply.go b/src/apply/apply.go index e7137199b5..b73fa4042b 100644 --- a/src/apply/apply.go +++ b/src/apply/apply.go @@ -345,11 +345,11 @@ func insertNavLink(str string, appNameArray string) string { return str } index := findMatchingPos(str, loc[0], 1, []string{"(", ")"}, 1) - str = str[:index] + ",Spicetify._renderNavLinks([" + appNameArray + "], false)," + str[index:] + str = fmt.Sprintf("%s,Spicetify._renderNavLinks([%s], false),%s", str[:index], appNameArray, str[index:]) // Global Navbar utils.ReplaceOnce(&str, `(,[a-zA-Z_\$][\w\$]*===(?:[a-zA-Z_\$][\w\$]*\.){2}HOME_NEXT_TO_NAVIGATION&&.+?)\]`, func(submatches ...string) string { - return submatches[1] + ",Spicetify._renderNavLinks([" + appNameArray + "], true)]" + return fmt.Sprintf("%s,Spicetify._renderNavLinks([%s], true)]", submatches[1], appNameArray) }) return str diff --git a/src/preprocess/preprocess.go b/src/preprocess/preprocess.go index c239d07491..3047e5b10c 100644 --- a/src/preprocess/preprocess.go +++ b/src/preprocess/preprocess.go @@ -145,7 +145,7 @@ func Start(version string, extractedAppsPath string, flags Flag) { tags += "\n" } - utils.Replace(&content, ``, func(submatches ...string) string { + utils.Replace(&content, ``, func(submatches ...string) string { return fmt.Sprintf("%s\n%s", submatches[0], tags) }) @@ -359,6 +359,9 @@ func disableLogging(input string) string { utils.Replace(&input, `key:"createLoggingParams",value:function\([^)]*\)\s*\{`, func(submatches ...string) string { return fmt.Sprintf("%sreturn {interactionIds:null,pageInstanceIds:null};", submatches[0]) }) + utils.Replace(&input, `key:"addEventsToESSData",value:function\([^)]*\)\s*\{`, func(submatches ...string) string { + return fmt.Sprintf("%sreturn;", submatches[0]) + }) utils.Replace(&input, `registerEventListeners\([^)]*\)\s*\{`, func(submatches ...string) string { return fmt.Sprintf("%sreturn;", submatches[0]) @@ -393,6 +396,9 @@ func disableLogging(input string) string { utils.Replace(&input, `createLoggingParams\([^)]*\)\s*\{`, func(submatches ...string) string { return fmt.Sprintf("%sreturn {interactionIds:null,pageInstanceIds:null};", submatches[0]) }) + utils.Replace(&input, `addEventsToESSData\([^)]*\)\s*\{`, func(submatches ...string) string { + return fmt.Sprintf("%sreturn;", submatches[0]) + }) return input } From 4950982b567c6968696eed13ff94afd71170dadd Mon Sep 17 00:00:00 2001 From: ririxi Date: Tue, 26 Mar 2024 22:05:12 +0100 Subject: [PATCH 16/54] feat(shuffle+): add an option to shuffle queue (#2923) --- Extensions/shuffle+.js | 44 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/Extensions/shuffle+.js b/Extensions/shuffle+.js index 413db2dba2..d8f41fadc9 100755 --- a/Extensions/shuffle+.js +++ b/Extensions/shuffle+.js @@ -12,6 +12,7 @@ const { React } = Spicetify; const { useState } = React; + let playbarButton = null; function getConfig() { try { @@ -22,7 +23,7 @@ throw ""; } catch { Spicetify.LocalStorage.set("shufflePlus:settings", "{}"); - return { artistMode: "all", artistNameMust: false }; + return { artistMode: "all", artistNameMust: false, enableQueueButton: false }; } } @@ -180,12 +181,18 @@ React.createElement(checkBoxItem, { name: "Chosen artist must be included", field: "artistNameMust" + }), + React.createElement(checkBoxItem, { + name: "Enable Shuffle+ Queue Tracks button in Playbar", + field: "enableQueueButton", + onclickFun: () => renderQueuePlaybarButton() }) ); Spicetify.PopupModal.display({ title: "Shuffle+", - content: settingsDOMContent + content: settingsDOMContent, + isLarge: true }); } @@ -265,6 +272,24 @@ "playlist-folder" ).register(); + renderQueuePlaybarButton(); + function renderQueuePlaybarButton() { + if (!playbarButton) { + playbarButton = new Spicetify.Playbar.Button( + "Shuffle+ Queue Tracks", + "enhance", + async () => { + await fetchAndPlay("queue"); + }, + false, + false + ); + } + + if (CONFIG.enableQueueButton) playbarButton.register(); + else playbarButton.deregister(); + } + async function fetchPlaylistTracks(uri) { const res = await Spicetify.CosmosAsync.get(`sp://core-playlist/v1/playlist/spotify:playlist:${uri}/rows`, { policy: { link: true, playable: true } @@ -407,6 +432,16 @@ return res.map(track => track.uri); } + function fetchQueue() { + const { _queueState } = Spicetify.Platform.PlayerAPI._queue; + const nextUp = _queueState.nextUp.map(track => track.uri); + const queued = _queueState.queued.map(track => track.uri); + const array = [...new Set([...nextUp, ...queued])]; + const current = _queueState.current?.uri; + if (current) array.push(current); + return array; + } + async function fetchCollection(uriObj) { const { category, type } = uriObj; const { pathname } = Spicetify.Platform.History.location; @@ -528,7 +563,10 @@ let uri; try { - if (typeof rawUri === "object") { + if (rawUri === "queue") { + list = fetchQueue(); + context = null; + } else if (typeof rawUri === "object") { list = rawUri; context = null; } else { From 03770a9083515d2ce1771c58cb5d0b91343776dd Mon Sep 17 00:00:00 2001 From: ririxi Date: Tue, 26 Mar 2024 22:05:25 +0100 Subject: [PATCH 17/54] feat: add support for pre-Library X UI again (#2922) --- CustomApps/lyrics-plus/TabBar.js | 3 ++- CustomApps/reddit/TabBar.js | 3 ++- CustomApps/reddit/index.js | 2 +- jsHelper/spicetifyWrapper.js | 29 +++++++++++++++++++++++++++-- src/apply/apply.go | 14 ++++++++++++++ 5 files changed, 46 insertions(+), 5 deletions(-) diff --git a/CustomApps/lyrics-plus/TabBar.js b/CustomApps/lyrics-plus/TabBar.js index 6bdf4f4c72..4a0b6d55ac 100644 --- a/CustomApps/lyrics-plus/TabBar.js +++ b/CustomApps/lyrics-plus/TabBar.js @@ -63,7 +63,8 @@ const TabBarMore = react.memo(({ items, switchTo, lockIn }) => { }); const TopBarContent = ({ links, activeLink, lockLink, switchCallback, lockCallback }) => { - const resizeHost = document.querySelector(".Root__main-view .os-resize-observer-host"); + const resizeHost = + document.querySelector(".Root__main-view .os-resize-observer-host") ?? document.querySelector(".Root__main-view .os-size-observer"); const [windowSize, setWindowSize] = useState(resizeHost.clientWidth); const resizeHandler = () => setWindowSize(resizeHost.clientWidth); diff --git a/CustomApps/reddit/TabBar.js b/CustomApps/reddit/TabBar.js index f4aa20d942..37731c896a 100644 --- a/CustomApps/reddit/TabBar.js +++ b/CustomApps/reddit/TabBar.js @@ -48,7 +48,8 @@ const TabBarMore = react.memo(({ items, switchTo }) => { }); const TopBarContent = ({ links, activeLink, switchCallback }) => { - const resizeHost = document.querySelector(".Root__main-view .os-resize-observer-host"); + const resizeHost = + document.querySelector(".Root__main-view .os-resize-observer-host") ?? document.querySelector(".Root__main-view .os-size-observer"); const [windowSize, setWindowSize] = useState(resizeHost.clientWidth); const resizeHandler = () => setWindowSize(resizeHost.clientWidth); diff --git a/CustomApps/reddit/index.js b/CustomApps/reddit/index.js index e6633ad946..8af0cdc4f4 100644 --- a/CustomApps/reddit/index.js +++ b/CustomApps/reddit/index.js @@ -62,7 +62,7 @@ const typesLocale = { }; class Grid extends react.Component { - viewportSelector = "#main .os-viewport"; + viewportSelector = document.querySelector("#main .os-viewport") ? "#main .os-viewport" : "#main .main-view-container__scroll-node"; constructor(props) { super(props); diff --git a/jsHelper/spicetifyWrapper.js b/jsHelper/spicetifyWrapper.js index ddd84620d4..28565554b9 100644 --- a/jsHelper/spicetifyWrapper.js +++ b/jsHelper/spicetifyWrapper.js @@ -1771,7 +1771,7 @@ Spicetify.ContextMenu = (() => { let navLinkFactoryCtx = null; let refreshNavLinks = null; -Spicetify._renderNavLinks = (list, isTouchScreenUi) => { +Spicetify._renderNavLinks = (list, isTouchScreenUi, isPreLibX = false) => { const [refreshCount, refresh] = Spicetify.React.useReducer(x => x + 1, 0); refreshNavLinks = refresh; @@ -1784,7 +1784,7 @@ Spicetify._renderNavLinks = (list, isTouchScreenUi) => { ) return; - const navLinkFactory = isTouchScreenUi ? NavLinkGlobal : NavLinkSidebar; + const navLinkFactory = isTouchScreenUi ? NavLinkGlobal : isPreLibX ? NavLinkSidebarLegacy : NavLinkSidebar; if (!navLinkFactoryCtx) navLinkFactoryCtx = Spicetify.React.createContext(null); const registered = []; @@ -1865,6 +1865,31 @@ const NavLink = ({ appProper, appRoutePath, icon, activeIcon }) => { return NavLinkFactory && Spicetify.React.createElement(NavLinkFactory, { appProper, appRoutePath, createIcon, isActive }, null); }; +const NavLinkSidebarLegacy = ({ appProper, appRoutePath, createIcon, isActive }) => { + return Spicetify.React.createElement( + "li", + { className: "main-navBar-navBarItem InvalidDropTarget" }, + Spicetify.React.createElement( + Spicetify.ReactComponent.TooltipWrapper, + { label: appProper, placement: "right" }, + Spicetify.React.createElement( + Spicetify.ReactComponent.Navigation, + { + to: appRoutePath, + referrer: "other", + className: Spicetify.classnames("link-subtle", "main-navBar-navBarLink", { + "main-navBar-navBarLinkActive active": isActive + }), + onClick: () => undefined, + "aria-label": appProper + }, + createIcon(), + Spicetify.React.createElement(Spicetify.ReactComponent.TextComponent, { variant: "bodyMediumBold", weight: "bold" }, appProper) + ) + ) + ); +}; + const NavLinkSidebar = ({ appProper, appRoutePath, createIcon, isActive }) => { const isSidebarCollapsed = Spicetify.Platform.LocalStorageAPI.getItem("ylx-sidebar-state") === 1; diff --git a/src/apply/apply.go b/src/apply/apply.go index b73fa4042b..fbb5dd8d69 100644 --- a/src/apply/apply.go +++ b/src/apply/apply.go @@ -347,6 +347,20 @@ func insertNavLink(str string, appNameArray string) string { index := findMatchingPos(str, loc[0], 1, []string{"(", ")"}, 1) str = fmt.Sprintf("%s,Spicetify._renderNavLinks([%s], false),%s", str[:index], appNameArray, str[index:]) + // pre-Library X + sidebarItemMatch := utils.SeekToCloseParen( + str, + `\("li",\{className:[\w$\.]+\}?,(?:children:)?[\w$\.,()]+\(\w+,\{uri:"spotify:user:@:collection",to:"/collection"`, + '(', ')') + + if sidebarItemMatch != "" { + str = strings.Replace( + str, + sidebarItemMatch, + fmt.Sprintf("%s,Spicetify._renderNavLinks([%s], false, true)", sidebarItemMatch, appNameArray), + 1) + } + // Global Navbar utils.ReplaceOnce(&str, `(,[a-zA-Z_\$][\w\$]*===(?:[a-zA-Z_\$][\w\$]*\.){2}HOME_NEXT_TO_NAVIGATION&&.+?)\]`, func(submatches ...string) string { return fmt.Sprintf("%s,Spicetify._renderNavLinks([%s], true)]", submatches[1], appNameArray) From 80437c94a58a3a342cb36d7fa035563546c77f25 Mon Sep 17 00:00:00 2001 From: ririxi Date: Thu, 28 Mar 2024 03:56:40 +0100 Subject: [PATCH 18/54] fix(wrapper): adapt `checkForUpdate` to new changelog (#2926) --- jsHelper/spicetifyWrapper.js | 37 +++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/jsHelper/spicetifyWrapper.js b/jsHelper/spicetifyWrapper.js index 28565554b9..80d890e3eb 100644 --- a/jsHelper/spicetifyWrapper.js +++ b/jsHelper/spicetifyWrapper.js @@ -2356,18 +2356,37 @@ Spicetify.Playbar = (() => { if (!check_spicetify_update || !version || version === "Dev") return; // Fetch latest version from GitHub try { + let changelog; const res = await fetch("https://api.github.com/repos/spicetify/spicetify-cli/releases/latest"); const { tag_name, html_url, body } = await res.json(); const semver = tag_name.slice(1); - const changelogRawData = body.match(/## What's Changed([\s\S]*?)\r\n\r/)[1]; - const changelog = [...changelogRawData.matchAll(/\r\n\*\s(.+?)\sin\shttps/g)] - .map(match => { - const featureData = match[1].split("@"); - const feature = featureData[0]; - const committerID = featureData[1]; - return `
  • ${feature}${committerID}
  • `; - }) - .join("\n"); + const changelogRawDataOld = body.match(/## What's Changed([\s\S]*?)\r\n\r/)?.[1]; + if (changelogRawDataOld) { + changelog = [...changelogRawDataOld.matchAll(/\r\n\*\s(.+?)\sin\shttps/g)] + .map(match => { + const featureData = match[1].split("@"); + const feature = featureData[0]; + const committerID = featureData[1]; + return `
  • ${feature}${committerID}
  • `; + }) + .join("\n"); + } else { + const sections = body.split("\n## "); + const filteredSections = sections.filter(section => !section.startsWith("Compatibility")); + const filteredText = filteredSections.join("\n## "); + changelog = [...filteredText.matchAll(/- (?:\*\*(.+?)\*\*:? )?(.+?) \(\[(.+?)\]\((.+?)\)\)/g)] + .map(match => { + const feature = match[1]; + const description = match[2]; + const prNumber = match[3]; + const prLink = match[4]; + let text = "
  • "; + if (feature) text += `${feature}: `; + text += `${description} (${prNumber})
  • `; + return text; + }) + .join("\n"); + } if (semver !== version) { const content = document.createElement("div"); From 8bc619f884bec3390c1dee7be381dc02bad12769 Mon Sep 17 00:00:00 2001 From: ririxi Date: Fri, 29 Mar 2024 15:52:43 +0100 Subject: [PATCH 19/54] feat(navlink): match spotify style & use `SeekToCloseParen` (#2927) --- jsHelper/spicetifyWrapper.js | 5 ++--- src/apply/apply.go | 35 +++++++++++------------------------ 2 files changed, 13 insertions(+), 27 deletions(-) diff --git a/jsHelper/spicetifyWrapper.js b/jsHelper/spicetifyWrapper.js index 80d890e3eb..561a7a039d 100644 --- a/jsHelper/spicetifyWrapper.js +++ b/jsHelper/spicetifyWrapper.js @@ -1884,7 +1884,7 @@ const NavLinkSidebarLegacy = ({ appProper, appRoutePath, createIcon, isActive }) "aria-label": appProper }, createIcon(), - Spicetify.React.createElement(Spicetify.ReactComponent.TextComponent, { variant: "bodyMediumBold", weight: "bold" }, appProper) + Spicetify.React.createElement(Spicetify.ReactComponent.TextComponent, { variant: "mestoBold" }, appProper) ) ) ); @@ -1911,8 +1911,7 @@ const NavLinkSidebar = ({ appProper, appRoutePath, createIcon, isActive }) => { "aria-label": appProper }, createIcon(), - !isSidebarCollapsed && - Spicetify.React.createElement(Spicetify.ReactComponent.TextComponent, { variant: "bodyMediumBold", weight: "bold" }, appProper) + !isSidebarCollapsed && Spicetify.React.createElement(Spicetify.ReactComponent.TextComponent, { variant: "balladBold" }, appProper) ) ) ); diff --git a/src/apply/apply.go b/src/apply/apply.go index fbb5dd8d69..5b3bd26af3 100644 --- a/src/apply/apply.go +++ b/src/apply/apply.go @@ -4,7 +4,6 @@ import ( "fmt" "os" "path/filepath" - "regexp" "strings" "github.com/spicetify/spicetify-cli/src/utils" @@ -320,32 +319,20 @@ func insertCustomApp(jsPath string, flags Flag) { }) } -func findMatchingPos(str string, start int, direction int, pair []string, scopes int) int { - l := scopes - i := start + direction - - for l > 0 { - c := string(str[i]) - i += direction - if c == pair[0] { - l++ - } else if c == pair[1] { - l-- - } - } - - return i -} - func insertNavLink(str string, appNameArray string) string { // Library X - re := regexp.MustCompile(`\("li",\{[^\{]*\{[^\{]*\{to:"\/search`) - loc := re.FindStringIndex(str) - if loc == nil { - return str + libraryXItemMatch := utils.SeekToCloseParen( + str, + `\("li",\{[^\{]*\{[^\{]*\{to:"\/search`, + '(', ')') + + if libraryXItemMatch != "" { + str = strings.Replace( + str, + libraryXItemMatch, + fmt.Sprintf("%s,Spicetify._renderNavLinks([%s], false)", libraryXItemMatch, appNameArray), + 1) } - index := findMatchingPos(str, loc[0], 1, []string{"(", ")"}, 1) - str = fmt.Sprintf("%s,Spicetify._renderNavLinks([%s], false),%s", str[:index], appNameArray, str[index:]) // pre-Library X sidebarItemMatch := utils.SeekToCloseParen( From ccb023b054f326599339f8b1414b3a266cd13adc Mon Sep 17 00:00:00 2001 From: ririxi Date: Mon, 1 Apr 2024 11:34:56 +0200 Subject: [PATCH 20/54] ci(release): add support for windows `arm64` (#2928) --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2394cd1332..a41a91c326 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -45,7 +45,7 @@ jobs: run: echo "IS_UNIX=${{ matrix.os != 'windows' && matrix.arch != '386' }}" >> $GITHUB_ENV - name: Is Windows Platform - run: echo "IS_WIN=${{ matrix.os == 'windows' && matrix.arch != 'arm64' }}" >> $GITHUB_ENV + run: echo "IS_WIN=${{ matrix.os == 'windows' }}" >> $GITHUB_ENV - name: Setup Go uses: actions/setup-go@v5 From 29fc298f6875151e323e7ba726e1f0b0a0c77be7 Mon Sep 17 00:00:00 2001 From: ririxi Date: Mon, 1 Apr 2024 13:40:41 +0200 Subject: [PATCH 21/54] feat(windows/install): add support for `arm64` (#2933) --- install.ps1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/install.ps1 b/install.ps1 index 87ded9b1b0..d0553af1e3 100644 --- a/install.ps1 +++ b/install.ps1 @@ -67,6 +67,9 @@ function Get-Spicetify { if ($env:PROCESSOR_ARCHITECTURE -eq 'AMD64') { $architecture = 'x64' } + elseif ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64') { + $architecture = 'arm64' + } else { $architecture = 'x32' } From 6dbc53c595d459bd2b27b1e6760c2412a572d480 Mon Sep 17 00:00:00 2001 From: ririxi Date: Tue, 2 Apr 2024 12:30:15 +0200 Subject: [PATCH 22/54] fix(ci/build): add arm64 to 7z checks (#2934) --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a41a91c326..36b2719d87 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -78,7 +78,7 @@ jobs: if: env.IS_WIN == 'true' uses: edgarrc/action-7z@v1 with: - args: 7z a -bb0 -mx9 "spicetify-${{ env.TAG }}-${{ matrix.os }}-${{ matrix.arch == 'amd64' && 'x64' || 'x32' }}.zip" "./spicetify.exe" "./CustomApps" "./Extensions" "./Themes" "./jsHelper" "globals.d.ts" "css-map.json" + args: 7z a -bb0 -mx9 "spicetify-${{ env.TAG }}-${{ matrix.os }}-${{ (matrix.arch == 'amd64' && 'x64') || (matrix.arch == 'arm64' && 'arm64') || 'x32' }}.zip" "./spicetify.exe" "./CustomApps" "./Extensions" "./Themes" "./jsHelper" "globals.d.ts" "css-map.json" - name: Release if: env.IS_UNIX == 'true' || env.IS_WIN == 'true' From 1d9de3a13f4fcafb88df88e3b42cd64857a86a78 Mon Sep 17 00:00:00 2001 From: ririxi Date: Sat, 6 Apr 2024 17:10:09 +0200 Subject: [PATCH 23/54] fix(install/linux): properly parse `--root` flag and tag option (#2932) --- install.sh | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/install.sh b/install.sh index 05e678c506..9d45f59830 100755 --- a/install.sh +++ b/install.sh @@ -5,10 +5,17 @@ set -e -while getopts ":r" arg; do - case "${arg}" in - "r") override_root=1 ;; - *) echo "Invalid option -${OPTARG}" >&2; exit 1 ;; +for arg in "$@"; do + shift + case "$arg" in + "--root") override_root=1 ;; + *) + if echo "$arg" | grep -qv "^-"; then + tag="$arg" + else + echo "Invalid option $arg" >&2 + exit 1 + fi esac done @@ -19,7 +26,7 @@ is_root() { if ! is_root && [ "${override_root:-0}" -eq 0 ]; then echo "The script was ran as root. Script will now exit" echo "If you did not intend to do this, please run the script without root permissions to avoid issues with Spicetify" - echo "You can override this behavior by passing '-r' or '--root' flag to this script" + echo "You can override this behavior by passing '--root' flag to this script" exit fi @@ -46,9 +53,7 @@ command -v grep >/dev/null || { log "grep isn't installed!" >&2; exit 1; } # download uri releases_uri=https://github.com/spicetify/spicetify-cli/releases -if [ $# -gt 0 ]; then - tag=$1 -else +if [ -z "$tag" ]; then tag=$(curl -LsH 'Accept: application/json' $releases_uri/latest) tag=${tag%\,\"update_url*} tag=${tag##*tag_name\":\"} From 9ee62026d86904972c88bf1494a4a10715ad1261 Mon Sep 17 00:00:00 2001 From: ririxi Date: Sun, 7 Apr 2024 04:57:28 +0200 Subject: [PATCH 24/54] fix: do not replace color variables in mini player css (#2948) --- src/preprocess/preprocess.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/preprocess/preprocess.go b/src/preprocess/preprocess.go index 3047e5b10c..5e87fcd79f 100644 --- a/src/preprocess/preprocess.go +++ b/src/preprocess/preprocess.go @@ -161,6 +161,11 @@ func Start(version string, extractedAppsPath string, flags Flag) { func StartCSS(extractedAppsPath string) { appPath := filepath.Join(extractedAppsPath, "xpui") filepath.Walk(appPath, func(path string, info os.FileInfo, err error) error { + // temp so text won't be black ._. + if info.Name() == "pip-mini-player.css" { + return nil + } + if filepath.Ext(info.Name()) == ".css" { utils.ModifyFile(path, colorVariableReplace) } From cb3e8f89114ffbbc2468414738f9aadd5c5618b6 Mon Sep 17 00:00:00 2001 From: ririxi Date: Sun, 7 Apr 2024 04:58:23 +0200 Subject: [PATCH 25/54] fix(new-releases): update `viewportSelector` for `1.2.34` and higher (#2940) --- CustomApps/new-releases/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CustomApps/new-releases/index.js b/CustomApps/new-releases/index.js index 5bbd639e9e..f336911372 100644 --- a/CustomApps/new-releases/index.js +++ b/CustomApps/new-releases/index.js @@ -70,7 +70,7 @@ let separatedByDate = {}; let dateList = []; class Grid extends react.Component { - viewportSelector = "#main .os-viewport"; + viewportSelector = document.querySelector("#main .os-viewport") ? "#main .os-viewport" : "#main .main-view-container__scroll-node"; constructor() { super(); From b82f6e22813fcd09b6e9a54cb173e095ba59a437 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 7 Apr 2024 03:58:53 +0100 Subject: [PATCH 26/54] chore(deps): bump golang.org/x/net from 0.22.0 to 0.24.0 (#2945) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 63991291dc..91522e4af1 100644 --- a/go.mod +++ b/go.mod @@ -5,11 +5,11 @@ go 1.21 require ( github.com/go-ini/ini v1.67.0 github.com/mattn/go-colorable v0.1.13 - golang.org/x/net v0.22.0 + golang.org/x/net v0.24.0 ) require ( github.com/mattn/go-isatty v0.0.16 // indirect github.com/stretchr/testify v1.7.1 // indirect - golang.org/x/sys v0.18.0 // indirect + golang.org/x/sys v0.19.0 // indirect ) diff --git a/go.sum b/go.sum index aadbe09461..264fa7d3b3 100644 --- a/go.sum +++ b/go.sum @@ -11,11 +11,11 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= From 32c700614f039765d42da886b6f2400ee47186fb Mon Sep 17 00:00:00 2001 From: harbassan <84175605+harbassan@users.noreply.github.com> Date: Sun, 7 Apr 2024 14:59:56 +1200 Subject: [PATCH 27/54] fix(wrapper/cards): change hook for `Default` card component (#2942) Co-authored-by: ririxi --- jsHelper/spicetifyWrapper.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jsHelper/spicetifyWrapper.js b/jsHelper/spicetifyWrapper.js index 561a7a039d..ef88576f7d 100644 --- a/jsHelper/spicetifyWrapper.js +++ b/jsHelper/spicetifyWrapper.js @@ -553,7 +553,9 @@ window.Spicetify = { Chip: modules.find(m => m?.render?.toString().includes("invertedDark") && m?.render?.toString().includes("isUsingKeyboard")), Toggle: functionModules.find(m => m.toString().includes("onSelected") && m.toString().includes('type:"checkbox"')), Cards: { - Default: functionModules.find(m => m?.toString().includes('"card-click-handler"')), + Default: functionModules.find( + m => m.toString().includes("?highlight") && m.toString().includes("headerText") && m.toString().includes("imageContainer") + ), Hero: functionModules.find(m => m?.toString().includes('"herocard-click-handler"')), CardImage: functionModules.find(m => m.toString().includes("isHero") && m.toString().includes("withWaves")), ...Object.fromEntries(cards) From 1e4f0690dce769ca7f5ac4154a5a0065bd44c2dd Mon Sep 17 00:00:00 2001 From: ririxi Date: Mon, 8 Apr 2024 04:32:15 +0200 Subject: [PATCH 28/54] feat(cmd/update): add support for `arm64` (#2952) --- src/cmd/update.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cmd/update.go b/src/cmd/update.go index 0090ff29b7..64e07fcadf 100644 --- a/src/cmd/update.go +++ b/src/cmd/update.go @@ -34,6 +34,8 @@ func Update(currentVersion string) bool { case "windows": if runtime.GOARCH == "386" { assetURL += "-windows-x32.zip" + } else if runtime.GOARCH == "arm64" { + assetURL += "-windows-arm64.zip" } else { assetURL += "-windows-x64.zip" } From 445868eeb380b94ea976d39ac8b37c848a23e58d Mon Sep 17 00:00:00 2001 From: ririxi Date: Mon, 8 Apr 2024 04:33:14 +0200 Subject: [PATCH 29/54] fix(manifest): remove borked extensions on marketplace (#2953) --- manifest.json | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/manifest.json b/manifest.json index 493d1901b4..9b6276dc56 100644 --- a/manifest.json +++ b/manifest.json @@ -17,12 +17,6 @@ "preview": "https://i.imgur.com/5reGrBb.png", "main": "Extensions/autoSkipExplicit.js" }, - { - "name": "Full App Display", - "description": "Minimal album cover art display with beautiful blur effect background. Activating button locates in top bar. While in display mode, double click anywhere to exit. Right click anywhere to open setting menu.", - "preview": "https://i.imgur.com/S7CPQ2s.png", - "main": "Extensions/fullAppDisplay.js" - }, { "name": "Keyboard Shortcut", "description": "Register some useful keybinds to support keyboard-driven navigation in Spotify client. Less time touching the mouse.", @@ -35,12 +29,6 @@ "preview": "https://i.imgur.com/YEkbjLC.png", "main": "Extensions/loopyLoop.js" }, - { - "name": "Pop-up Lyrics", - "description": "Have easy access to a pop-up window with the current song's lyrics. Click at microphone icon on top bar to open lyrics windows. Right click at the same icon to open config menu to customize looks and lyrics providers priorities.", - "preview": "https://i.imgur.com/Nx9Lx7D.png", - "main": "Extensions/popupLyrics.js" - }, { "name": "Shuffle+", "description": "Shuffles using Fisher–Yates algorithm with zero bias. After installing extensions, right click album/playlist/artist item, there will be an option \"Play with Shuffle+\". You can also multiple select tracks and choose to \"Play with Shuffle+\". Moreover, enable option \"Auto Shuffle+\" in Profile menu to inject Shuffle+ into every play buttons, no need to right click anymore.", @@ -52,11 +40,5 @@ "description": "Throw songs/artists to trash bin and never hear them again (automatically skip). This extension will append a Throw to Trashbin option in tracks and artists link right click menu.", "preview": "https://i.imgur.com/ZFTy5Rm.png", "main": "Extensions/trashbin.js" - }, - { - "name": "Web Now Playing", - "description": "For Rainmeter users, establish connection with WebNowPlaying plugin to send track metadata and control players.", - "preview": null, - "main": "Extensions/webnowplaying.js" } ] From 6591a1a98d00126f8fa805f17c2b5779331c7bfc Mon Sep 17 00:00:00 2001 From: Bergbok <66174189+Bergbok@users.noreply.github.com> Date: Mon, 8 Apr 2024 23:19:57 +0200 Subject: [PATCH 30/54] feat(windows/install): add help text for `?` choices (#2957) --- install.ps1 | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/install.ps1 b/install.ps1 index d0553af1e3..373aa2a742 100644 --- a/install.ps1 +++ b/install.ps1 @@ -167,7 +167,11 @@ if (-not (Test-Admin)) { Write-Unsuccess Write-Warning -Message "The script was ran as Administrator which isn't recommended" $Host.UI.RawUI.Flushinputbuffer() - $choice = $Host.UI.PromptForChoice('', 'Do you want to abort the installation process to avoid any issues?', ('&Yes', '&No'), 0) + $choices = [System.Management.Automation.Host.ChoiceDescription[]] @( + (New-Object System.Management.Automation.Host.ChoiceDescription '&Yes', 'Abort installation.'), + (New-Object System.Management.Automation.Host.ChoiceDescription '&No', 'Resume installation.') + ) + $choice = $Host.UI.PromptForChoice('', 'Do you want to abort the installation process to avoid any issues?', $choices, 0) if ($choice -eq 0) { Write-Host -Object 'spicetify installation aborted' -ForegroundColor 'Yellow' Pause @@ -189,7 +193,11 @@ Write-Host -Object 'to get started' #region Marketplace $Host.UI.RawUI.Flushinputbuffer() -$choice = $Host.UI.PromptForChoice('', "`nDo you want to install Spicetify Marketplace?", ('&Yes', '&No'), 0) +$choices = [System.Management.Automation.Host.ChoiceDescription[]] @( + (New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Install Spicetify Marketplace."), + (New-Object System.Management.Automation.Host.ChoiceDescription "&No", "Do not install Spicetify Marketplace.") +) +$choice = $Host.UI.PromptForChoice('', "`nDo you want to install Spicetify Marketplace?", $choices, 0) if ($choice -eq 1) { Write-Host -Object 'spicetify Marketplace installation aborted' -ForegroundColor 'Yellow' } From c77623b34d7166bbd2049f9e7b67b6ed7591ed80 Mon Sep 17 00:00:00 2001 From: ririxi Date: Tue, 9 Apr 2024 01:14:09 +0200 Subject: [PATCH 31/54] fix: adapt regexes for `1.2.35` (#2958) Co-authored-by: surfbryce <80861823+surfbryce@users.noreply.github.com> --- jsHelper/spicetifyWrapper.js | 13 ++++++++++--- src/apply/apply.go | 2 +- src/preprocess/preprocess.go | 2 +- src/utils/utils.go | 2 +- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/jsHelper/spicetifyWrapper.js b/jsHelper/spicetifyWrapper.js index ef88576f7d..f6af0c766c 100644 --- a/jsHelper/spicetifyWrapper.js +++ b/jsHelper/spicetifyWrapper.js @@ -265,7 +265,9 @@ window.Spicetify = { "StoreProvider", "PlatformProvider", "Dropdown", - "MenuSubMenuItem" + "MenuSubMenuItem", + "Navigation", + "ScrollableContainer" ]) }, { @@ -557,7 +559,12 @@ window.Spicetify = { m => m.toString().includes("?highlight") && m.toString().includes("headerText") && m.toString().includes("imageContainer") ), Hero: functionModules.find(m => m?.toString().includes('"herocard-click-handler"')), - CardImage: functionModules.find(m => m.toString().includes("isHero") && m.toString().includes("withWaves")), + CardImage: functionModules.find( + m => + m.toString().includes("isHero") && + (m.toString().includes("withWaves") || m.toString().includes("isCircular")) && + m.toString().includes("imageWrapper") + ), ...Object.fromEntries(cards) }, Router: functionModules.find(m => m.toString().includes("navigationType") && m.toString().includes("static")), @@ -1038,7 +1045,7 @@ Spicetify._getStyledClassName = (args, component) => { Spicetify.getFontStyle = font => { if (!font || !Spicetify._fontStyle) return; - let rawStyle = Spicetify._fontStyle({ variant: font }) + let rawStyle = Spicetify._fontStyle({ variant: font, $variant: font }) .filter(style => typeof style === "string") .join(""); // Clean up empty rulesets diff --git a/src/apply/apply.go b/src/apply/apply.go index 5b3bd26af3..fc95687c6a 100644 --- a/src/apply/apply.go +++ b/src/apply/apply.go @@ -219,7 +219,7 @@ func getColorCSS(scheme map[string]string) string { func insertCustomApp(jsPath string, flags Flag) { utils.ModifyFile(jsPath, func(content string) string { const REACT_REGEX = `([\w_\$][\w_\$\d]*(?:\(\))?)\.lazy\(\((?:\(\)=>|function\(\)\{return )(\w+)\.(\w+)\(\d+\)\.then\(\w+\.bind\(\w+,\d+\)\)\}?\)\)` - const REACT_ELEMENT_REGEX = `(\[\w_\$][\w_\$\d]*(?:\(\))?\.createElement|\([\w$\.,]+\))\(([\w\.]+),\{path:"\/collection"(?:,(element|children)?[:.\w,{}()/*"]+)?\}` + const REACT_ELEMENT_REGEX = `(\[\w_\$][\w_\$\d]*(?:\(\))?\.createElement|\([\w$\.,]+\))\(([\w\.]+),\{path:"\/collection"(?:,(element|children)?[:.\w,{}()$/*"]+)?\}` reactSymbs := utils.FindSymbol( "Custom app React symbols", content, diff --git a/src/preprocess/preprocess.go b/src/preprocess/preprocess.go index 5e87fcd79f..b4ce206bd6 100644 --- a/src/preprocess/preprocess.go +++ b/src/preprocess/preprocess.go @@ -611,7 +611,7 @@ func exposeAPIs_vendor(input string) string { utils.ReplaceOnce( &input, - `\(function\(\w+\)\{return \w+\.variant\?function\(\w+\)\{`, + `\(function\(\w+\)\{return \w+\.\$?variant\?function\(\w+\)\{`, func(submatches ...string) string { return fmt.Sprintf("Spicetify._fontStyle=%s", submatches[0]) }) diff --git a/src/utils/utils.go b/src/utils/utils.go index a4e18ba841..c2658e2cf1 100644 --- a/src/utils/utils.go +++ b/src/utils/utils.go @@ -278,7 +278,7 @@ func FindSymbol(debugInfo, content string, clues []string) []string { } if len(debugInfo) > 0 { - PrintError("cannot find symbol for " + debugInfo) + PrintError("Cannot find symbol for " + debugInfo) } return nil From 84273d1e1666613c6f3fc410d70194c7d9f06a6f Mon Sep 17 00:00:00 2001 From: ririxi Date: Wed, 10 Apr 2024 21:05:36 +0200 Subject: [PATCH 32/54] fix(getStyledClassName): add `$semanticColor` to included keys (#2962) --- jsHelper/spicetifyWrapper.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jsHelper/spicetifyWrapper.js b/jsHelper/spicetifyWrapper.js index f6af0c766c..52fcd79be4 100644 --- a/jsHelper/spicetifyWrapper.js +++ b/jsHelper/spicetifyWrapper.js @@ -990,7 +990,8 @@ Spicetify._getStyledClassName = (args, component) => { "data-encore-id", "$size", "$iconColor", - "$variant" + "$variant", + "$semanticColor" ]; const customKeys = ["padding", "blocksize"]; From d31784fe27de247d612e93194ecf12aa631a58f4 Mon Sep 17 00:00:00 2001 From: ririxi Date: Fri, 12 Apr 2024 13:27:15 +0200 Subject: [PATCH 33/54] fix(lyrics-plus): add second selector for viewport (#2961) --- CustomApps/lyrics-plus/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CustomApps/lyrics-plus/index.js b/CustomApps/lyrics-plus/index.js index 584d59cf67..596d35920a 100644 --- a/CustomApps/lyrics-plus/index.js +++ b/CustomApps/lyrics-plus/index.js @@ -559,7 +559,8 @@ class LyricsContainer extends react.Component { this.forceUpdate(); }; - this.viewPort = document.querySelector(".Root__main-view .os-viewport"); + this.viewPort = + document.querySelector(".Root__main-view .os-viewport") ?? document.querySelector(".Root__main-view .main-view-container__scroll-node"); this.configButton = new Spicetify.Menu.Item("Lyrics Plus config", false, openConfig, "lyrics"); this.configButton.register(); From 1ba6ef0cbac52bf15617ec01f6b3be39b42a9fc2 Mon Sep 17 00:00:00 2001 From: ririxi Date: Mon, 15 Apr 2024 18:54:06 +0200 Subject: [PATCH 34/54] fix(config): check for duplicates when adding multiple values (#2963) --- jsHelper/spicetifyWrapper.js | 2 +- src/apply/apply.go | 1 + src/cmd/config.go | 74 ++++++++++++++++++++++++------------ 3 files changed, 51 insertions(+), 26 deletions(-) diff --git a/jsHelper/spicetifyWrapper.js b/jsHelper/spicetifyWrapper.js index 52fcd79be4..95cc955977 100644 --- a/jsHelper/spicetifyWrapper.js +++ b/jsHelper/spicetifyWrapper.js @@ -2390,7 +2390,7 @@ Spicetify.Playbar = (() => { const prNumber = match[3]; const prLink = match[4]; let text = "
  • "; - if (feature) text += `${feature}: `; + if (feature) text += `${feature}${!feature.endsWith(":") ? ": " : " "}`; text += `${description} (${prNumber})
  • `; return text; }) diff --git a/src/apply/apply.go b/src/apply/apply.go index fc95687c6a..af174ec13a 100644 --- a/src/apply/apply.go +++ b/src/apply/apply.go @@ -233,6 +233,7 @@ func insertCustomApp(jsPath string, flags Flag) { if (len(reactSymbs) < 2) || (len(eleSymbs) == 0) { utils.PrintError("Spotify version mismatch with Spicetify. Please report it on our github repository.") + utils.PrintInfo("Spicetify might have been updated for this version already. Please run `spicetify update` to check for a new version. If one isn't available yet, please wait for the update to be released.") return content } diff --git a/src/cmd/config.go b/src/cmd/config.go index 6dcc4913ff..fd920a8f4c 100644 --- a/src/cmd/config.go +++ b/src/cmd/config.go @@ -1,6 +1,7 @@ package cmd import ( + "fmt" "log" "os" "strings" @@ -121,41 +122,64 @@ func arrayType(section *ini.Section, field, value string) { utils.Fatal(err) } - allExts := key.Strings("|") + allExts := make(map[string]bool) + for _, v := range key.Strings("|") { + allExts[v] = true + } - isSubstract := value[len(value)-1] == '-' - if isSubstract { - value = value[0 : len(value)-1] - found := false - newList := []string{} - for _, v := range allExts { - if value == v { - found = true - } else { - newList = append(newList, v) - } - } + values := strings.Split(value, "|") + duplicates := []string{} + inputValues := make(map[string]bool) + modifiedValues := 0 - if !found { - unchangeWarning(field, value+" is not on the list.") - return + for _, value := range values { + isSubstract := strings.HasSuffix(value, "-") + if isSubstract { + value = value[:len(value)-1] } - allExts = newList - } else { - for _, ext := range allExts { - if value == ext { - unchangeWarning(field, value+" is already in the list.") + if isSubstract { + if _, found := allExts[value]; !found { + unchangeWarning(field, fmt.Sprintf("%s is not on the list.", value)) return } + + modifiedValues++ + delete(allExts, value) + } else { + if _, found := allExts[value]; found && !inputValues[value] { + duplicates = append(duplicates, value) + } else if _, found := allExts[value]; !found { + allExts[value] = true + modifiedValues++ + } + + inputValues[value] = true } + } - allExts = append(allExts, value) + if len(duplicates) > 0 { + unchangeWarning(field, fmt.Sprintf("%s %s already in the list.", strings.Join(duplicates, ", "), pluralize(len(duplicates), "is", "are"))) } - newList := strings.Join(allExts, "|") - key.SetValue(newList) - changeSuccess(field, newList) + if modifiedValues == 0 { + return + } + + newList := make([]string, 0, len(allExts)) + for k := range allExts { + newList = append(newList, k) + } + + key.SetValue(strings.Join(newList, "|")) + changeSuccess(field, strings.Join(newList, "|")) +} + +func pluralize(count int, singular, plural string) string { + if count == 1 { + return singular + } + return plural } func stringType(section *ini.Section, field, value string) { From 83c3ad8d602f171d5bdad63f6f39e13e634da2f2 Mon Sep 17 00:00:00 2001 From: ririxi Date: Mon, 22 Apr 2024 16:21:13 +0200 Subject: [PATCH 35/54] fix: make changes for `1.2.36` (#2973) --- css-map.json | 1941 +++++++++++++++++----------------- jsHelper/spicetifyWrapper.js | 62 +- spicetify.go | 10 +- src/cmd/config.go | 6 + src/preprocess/preprocess.go | 15 +- 5 files changed, 1035 insertions(+), 999 deletions(-) diff --git a/css-map.json b/css-map.json index 0f81360dec..7dbde34802 100644 --- a/css-map.json +++ b/css-map.json @@ -1,54 +1,373 @@ { - "bFQ9NOIn1bDs8tTH0ebQ": "main-collectionLinkButton-icon", - "vCaNVEuqazhZFQNcVHZj": "main-yourEpisodesButton-yourEpisodesIcon", - "q3ABXYJT9JZIzXOOtVuO": "main-createPlaylistButton-createPlaylistIcon", - "OEFWODerafYHGp09iLlA": "queue-tabBar-headerItem", - "Em2LrSSfvrgXQoajs6cm": "x-categoryCard-CategoryCard", - "ZtY42R4YSo_W7VMeAg9m": "x-searchInput-searchInputClearButton", - "QO9loc33XC50mMRUCIvf": "x-searchInput-searchInputInput", - "H6jh9Xd7DNOq3NsLDmCB": "x-searchInput-searchInputSearchIcon", + "n8Bz0c0v17whD3KfMdOk": "album-albumPage-sectionWrapper", + "HPNSn7d7aZf4nfre61sk": "artist-artistAbout-about", + "xaeunxBdlShScWay5mQR": "artist-artistAbout-artistGridContainer", + "RHlPX8sl9gW1cmKdm1E9": "artist-artistAbout-artistOverviewContainer", + "TPcD_1UTh6DS32DfZxhA": "artist-artistAbout-artistOverviewContent", + "Ev5jVfYlqmjaZh6ziail": "artist-artistAbout-artistShelfSpacer", + "N3mpQyWevHz7lrgLkOBM": "artist-artistAbout-artistSides", + "TxASgfgEtA4JmUkhkNUN": "artist-artistAbout-artistSidesBlock", + "PAlX44btlstKkPJfe2uU": "artist-artistAbout-avatar", + "k4MNlyGrhsL0qgnENxqh": "artist-artistAbout-backgroundImage", + "CjnwbSTpODW56Gerg7X6": "artist-artistAbout-bio", + "Fzu8dfizHyYedxyDjaQ2": "artist-artistAbout-bioContainer", + "Q_OUHp7iDNLBcO2ZYI2x": "artist-artistAbout-cityBlock", + "MHIOvvlSYRmF7VAJDLWy": "artist-artistAbout-close", + "ml8qANY77Ah3fx5VTjoe": "artist-artistAbout-columnContainer", + "uhDzVbFHyCQDH6WrWZaC": "artist-artistAbout-container", + "ejNsts52hRq0uZcc_NXi": "artist-artistAbout-content", + "H3lKAypjVfPoxoQkkCJQ": "artist-artistAbout-events", + "XbP5GUst__JF8uVtbozd": "artist-artistAbout-heading", + "oMsgQk2LPTIE4yinSHOQ": "artist-artistAbout-image", + "e2S7FcJ1QgVLlcUbl2Kn": "artist-artistAbout-merch", + "Er5rIejLMh22M0OiF8wH": "artist-artistAbout-merchShelfContent", + "iZ_BsoftrZBB78FRQ3Yq": "artist-artistAbout-merchSmall", + "pSn5vOGhTHswAWTC_3tE": "artist-artistAbout-modal", + "KUUFCMOavSKiLbBMXu0f": "artist-artistAbout-modalAfterOpen", + "hIhnD0UMvYHG6TnluwnX": "artist-artistAbout-modalBase", + "Xr7SnQlqJFl6FSMeiSsw": "artist-artistAbout-modalBeforeClose", + "yzXX2lW3wGayC_cdup_m": "artist-artistAbout-overview", + "fPw1FkQQDEJvxJwTalo5": "artist-artistAbout-popularTracks", + "Apg1EshcUJs6y4ITDWwV": "artist-artistAbout-popularTracksBlock", + "hdS8jsvbJhsJXHAZlWwz": "artist-artistAbout-postedBy", + "mM_me6VjRfHLPkqAMqEI": "artist-artistAbout-postedByAvatar", + "tQp8UOu8jGduQXUTcv0c": "artist-artistAbout-rank", + "pHrwZOFBdT8FNXnmcPPI": "artist-artistAbout-scrollbars", + "y72RJ2LhCkAyAfZ8tzUt": "artist-artistAbout-sideBlock", + "upZIQtiBy1Tr0ZbvhnSL": "artist-artistAbout-stats", + "ndIZG_atdpv_tBZtqQhk": "artist-artistAbout-statsContainer", + "GB_nwkJosBf_NLdZAgAx": "artist-artistDiscography-active", + "cFKW94askf6sbyOYlRqe": "artist-artistDiscography-artistName", + "Ihlsi5QU3AnIfSgnhorS": "artist-artistDiscography-button", + "h8z21OhjsxoY1IvpR1QP": "artist-artistDiscography-cardGrid", + "Rz6JI4bCxJVeSWe6LtEX": "artist-artistDiscography-firstAlbum", + "O61y0bIacmTFxhhbL1Bl": "artist-artistDiscography-headerButtons", + "fEvxx8vl3zTNWsuC8lpx": "artist-artistDiscography-headerContainer", + "n1EzbHQahSKztskTUAm3": "artist-artistDiscography-headerImage", + "hyHkMMynp3uUsmEtOkSN": "artist-artistDiscography-headerMetadata", + "kRb29P1Fo5blFMPRDSdq": "artist-artistDiscography-headerTitle", + "P7nfAtcLXgPiUCJrlUjA": "artist-artistDiscography-topBar", + "EvQHNTBhaU3rGCRRlAWj": "artist-artistDiscography-topBar", + "QplCuuGSoV4updqTSLq9": "artist-artistDiscography-topBarScrolled", + "oxpxKtAxG4E2DCK0AJo9": "artist-artistDiscography-tracklist", + "QQasfrfLlxtbcdiJP40s": "artist-artistOffers-description", + "F6RR_jytWUwdg_jiv0Ss": "artist-artistOffers-icon", + "TXVCwyY2iLFPRMSav251": "artist-artistOffers-info", + "RmO04klyCgpCtMspkDMH": "artist-artistOffers-item", + "crweb403jWwGSZngXpHU": "artist-artistOffers-name", + "nMgXBztFcmHCjT0dRQDx": "artist-artistOffers-pic", + "N5_bW94EwvHFbWWoRucu": "artist-artistOnTour-condensed", + "gyHBzoYLUrTsDmijyGQ7": "artist-artistOnTour-date", + "J8F7vs26LDSof1E_qwmN": "artist-artistOnTour-dateDay", + "VbaPExA4ISCqk6SuSe2H": "artist-artistOnTour-dateMonth", + "P5l28MUwDXvStz4OF0IE": "artist-artistOnTour-elevated", + "rTTxX5loXbtazDI0NLAj": "artist-artistOnTour-eventName", + "j1MetdstqbpfRVFl1W01": "artist-artistOnTour-info", + "viRsT27AlJDd4bZyiH_k": "artist-artistOnTour-item", + "h3FvLvcLCaK12strxe2F": "artist-artistOnTour-location", + "ERcmpF077M1XT1X0fIxB": "artist-artistOnTour-metadata", + "Oq3xjFrLaBAabx847xea": "artist-artistOnTour-onTourShelfGrid", + "n46Gs0Xh2zys0a2KwSRS": "artist-artistOnTour-time", + "IUF5ct6RQtva_f_DQqg0": "artist-artistOnTour-timeAndVenue", + "dvPKZDevT0Llia4bmaJX": "artist-artistOnTour-timeAndVenueText", + "RpOhZK9h4ccL8wsEgdwQ": "artist-artistOnTour-title", + "kgR8s9v7IzY4G17ZtLbw": "artist-artistOverview-about", + "Sl7tzXKh5stpn_y5prU5": "artist-artistOverview-artistOverviewContainer", + "BL__GuO2JsHMR6RgNfwY": "artist-artistOverview-artistOverviewContent", + "_7rRmILTMMuCiW77ERpvL": "artist-artistOverview-artistShelfRelatedVideos", + "jJ1PYBjdJy5plPbVprT1": "artist-artistOverview-artistShelfSpacer", + "EsgR8WWJIEa9L2wBAKxg": "artist-artistOverview-artistSides", + "_yUo81yeoON6wNqCV_ud": "artist-artistOverview-artistSidesBlock", + "qsfp4wSDOv6LBCbFApI1": "artist-artistOverview-events", + "hLkn_NwPkY5VIAETCqCK": "artist-artistOverview-heading", + "_7MwXzTGa7JMhVlJCeDJ9": "artist-artistOverview-merch", + "NOFtFAj4dIAsXQgVHJcA": "artist-artistOverview-merchShelfContent", + "ODvt8oN68o6Iy8nxwOuY": "artist-artistOverview-merchSmall", + "NLaDALU71zxOtBUbsrfH": "artist-artistOverview-overview", + "q9GR66ZTM4HH42Z_qroQ": "artist-artistOverview-popularTracks", + "yTBLU_z7yk9Xp_oN48Q2": "artist-artistOverview-popularTracksBlock", + "uVh80THccLWIzZYwgUaQ": "artist-artistOverview-sideBlock", + "b0NcxAbHvRbqgs2S8QDg": "artist-artistVerifiedBadge-badge", + "bn2UNQDs5GLY5rjp5Ljh": "artist-artistVerifiedBadge-fillColor", + "CmR9tHJ5ta6oWJlKBm3k": "artist-artistVerifiedBadge-wrapper", + "idI9vydtCzXVhU1BaKLw": "artist-followButton-button", + "Qq16641w1flRfBavPaAn": "artist-followButton-disabled", + "fEbcweEiUPPy2eaIaD3F": "artist-followButton-followed", + "wi2HeHXOI471ZOh8ncCG": "artist-popularTrackList-seeMore", + "YV8aNrRwNwFaMozM_Bfo": "collection-collection-adBarEnabled", + "Hbwta1_s02edtdkgJ7qZ": "collection-collection-AddToPlaylistIcon", + "nHGnfkVXCk9YYVitV6eu": "collection-collection-emptyStateContainer", + "fLqEiE5HwKr9eFCbJgeu": "collection-collection-header", + "tUg9tRrSVbtjHJ4WHnxw": "collection-collection-tabBar", + "ZzUvBwE6uj5CAU2pjlQX": "collection-collectionEntityHeroCard-container", + "xhPzQCyks9pfizJj_PVK": "collection-collectionEntityHeroCard-descriptionContainer", + "DY2YrJ5MH3ddIhZGORBq": "collection-collectionEntityHeroCard-headerContainer", + "NGSgqDuaOH2VDApkzoxN": "collection-collectionEntityHeroCard-likedSongs", + "QoUF6etsDFiL979QR7aC": "collection-collectionEntityHeroCard-moreText", + "d8ifuAZX8mK644AwlRZK": "collection-collectionEntityHeroCard-opacityText", + "lBs1v3T3HAPrOxfyWemr": "collection-collectionEntityHeroCard-skeletonRow", + "ZXOyJPokUIObMnvTOJvc": "collection-collectionEntityHeroCard-tracksContainer", + "kST1INfbHSxzydJffBq_": "collection-collectionEntityHeroCard-yourEpisodes", + "VuUpAVlUW_OfMfOcDEID": "collection-searchBar-searchBar", + "H0HbpIM3UrcupWIAjLWu": "cover-art", + "W0TACB7OY0iXtKVOtEhY": "cover-art-auto-height", + "zmOtW0vqqn1qpZrtQ_w9": "cover-art-icon", + "FqmFsMhuF4D0s35Z62Js": "cover-art-image", + "GSFvITwD84dS2JA62Mtj": "desktopmodals-aboutSpotifyModal-closeButton", + "UnLGG6p932k7WyjkB9Vo": "desktopmodals-aboutSpotifyModal-container", + "KlzblASEYfUfaykBFZgM": "desktopmodals-aboutSpotifyModal-content", + "XF1XXenkrbdAK2rRoxoU": "desktopmodals-aboutSpotifyModal-copyright", + "Ifnz1lh1jjvqPqJ4KPo8": "desktopmodals-aboutSpotifyModal-licensing", + "qsKpcFrhrA8KtuTVIN_y": "desktopmodals-licensesModal-buttonContainer", + "uYKs_kQMPOziaeDj877B": "desktopmodals-licensesModal-container", + "i8qeSJJVx4PXb7fsvOTd": "desktopmodals-licensesModal-content", + "WhIzm3S3R6Ker3XvpYW6": "desktopmodals-licensesModal-licensesFrame", + "qi0hX8uXrbQyS6tvdDBt": "desktopmodals-versionStatus-container", + "WomzHWnDO_yFyjnkd49P": "desktopmodals-versionStatus-content", + "R83hOohwVshnd6bEkDO4": "desktopmodals-versionStatus-copyButton", + "YJMECPbMHWgMUs8RFdcV": "folder-folderPage-sectionWrapper", + "cUwQnQoE3OqXqSYLT0hv": "link-subtle", + "VUXMMFKWudUWE1kIXZoS": "link-subtle", + "iKgf4UDhbRTHxmZSuAEc": "lyrics-lyrics-adLeaderboardIsEnabled", + "L9xhJOJnV2OL5Chm3Jew": "lyrics-lyrics-background", + "tr8V5eHsUaIkOYVw7eSG": "lyrics-lyrics-container", + "Q2RPoHcoxygOoPLXLMww": "lyrics-lyrics-contentContainer", + "esRByMgBY3TiENAsbDHA": "lyrics-lyrics-contentWrapper", + "iPBJpp5EVkRE24N6vmGA": "lyrics-lyrics-coverTopBar", + "SaEkeiyzAoXnWVSDiTR7": "lyrics-lyrics-vocalRemoval", + "arY01KDGhWNgzlAHlhpd": "lyrics-lyricsContent-active", + "iq4cgi0YEKr6DGaTtzUj": "lyrics-lyricsContent-description", + "MEjuIn9iTBQbnCqHpkoQ": "lyrics-lyricsContent-highlight", + "_LKG3z7SnerR0eigPCoK": "lyrics-lyricsContent-isInteractive", + "NiCdLCpp3o2z6nBrayOn": "lyrics-lyricsContent-lyric", + "kGR_hu4tdj9PnUlSPaRL": "lyrics-lyricsContent-provider", + "A3ohAQNHsDIMv2EM3Ytp": "lyrics-lyricsContent-text", + "HxblHEsl2WX2yhubfVIc": "lyrics-lyricsContent-unsynced", + "E4q8ogfdWtye7YgotBlN": "main-actionBar-ActionBar", + "eSg4ntPU2KQLfpLGXAww": "main-actionBar-ActionBarRow", + "CoLO4pdSl8LGWyVZA00t": "main-actionBarBackground-background", + "GTAFfOA_w5vh_bDaGJAG": "main-actionButtons", + "NPvLJSRWfv1Joo8dF0D8": "main-actionButtons", + "WIGgdAaAzrXm7f_loaXi": "main-actionButtons-button", "rRF_r7EyCHjZv058JACi": "main-addButton-active", + "SPC4uzYXJmknkCGKpxHw": "main-addButton-active", "Fm7C3gdh5Lsc9qSXrQwO": "main-addButton-button", + "RbsCNNM9a0WkFCM2UzBA": "main-addButton-button", + "nzUMgk_XBD4uFFgA_LOI": "main-addButton-disabled", + "GolAZOzxNIKbfZdIApC_": "main-addButton-helmet", + "LuK6ZGXdwxSW92X3FodG": "main-addButton-zoomInAnimation", "uKyQmBSHiTyLvZlrFHLE": "main-appShell-card", "fGX1fnzBkGAAMfMxDXDe": "main-appShell-cards", "uMdsIJ2RlIvMQObefThj": "main-appShell-cardsHeader", "ucE6L4XRyB9F_RXDPVuR": "main-appShell-cardsWrapper", + "FKzolQvIeUcXEOsjtw8l": "main-appShell-container", "vIGYXwggXAn1Xc_qD5LA": "main-appShell-logo", "HMyLin1O_6Ae2odnit1u": "main-appShell-mainContent", "qqVgbIIvqVxAT7KPTjM6": "main-appShell-navItems", "D1z00v8mUgOxx_my43Yq": "main-appShell-playbackBar", "rLrSnwagmkEsLoI1InYT": "main-appShell-sideBar", "Fe4_ZnxnNSMxu7vzbntV": "main-appShell-topBar", - "w9Tpa4Y111UM5u1WMkEl": "main-card-DownloadStatusIndicator", - "woJQ5t2YiaJhjTv_KE7p": "main-card-PlayButtonContainer", - "zuKTW9yEI9rToECOcWG3": "main-card-PlayButtonContainerVisible", + "tp8rO9vtqBGPLOhwcdYv": "main-avatar-avatar", + "LKfKy7bXKmlkMEANVJMS": "main-avatar-avatar", + "Xz3tlahv16UpqKBW5HdK": "main-avatar-image", + "yzLEMgdzXgAnIZZwMHO1": "main-avatar-piled", + "ENopS3htmKy15q_QCR2j": "main-avatar-piledIcon", + "m95Ymx847hCaxHjmyXKX": "main-avatar-placeholderTransparent", + "KdxlBanhDJjzmHfqhP0X": "main-avatar-placeholderWrapper", + "BzunmwrVMyWGpopPJRt2": "main-avatar-withBadge", + "YEaaNScT6lyJCVBeQoxd": "main-buddyFeed-actions", + "_Xe25F2aC59Kljgqyw3G": "main-buddyFeed-activityMetadata", + "j7K7_Zly3G1HS9MlKoao": "main-buddyFeed-addFriendPlaceholder", + "gY0qK1gmEdhq5idwQc8C": "main-buddyFeed-addFriendPlaceholderBtn", + "cBPbfBWIIPDzhIT6i3ih": "main-buddyFeed-addFriendPlaceholderText", + "mthrc5U9wb8F4zMBqlPy": "main-buddyFeed-artistAndTrackName", + "dLg5WMgjh1kfYtZ_MnZz": "main-buddyFeed-avatarContainer", + "ythYrlFSBm1P_ltHc8e1": "main-buddyFeed-buddyFeed", + "t345U9kQY1pF704d79oY": "main-buddyFeed-closeButton", + "eZCD3dqbvZaABVAhIniT": "main-buddyFeed-closeContainer", + "AzO2ondhaHJntbGy_3_S": "main-buddyFeed-container", + "zuwPpHAEtIqahnB2u9NR": "main-buddyFeed-content", + "MObmOrMxbQpO10ebAtZA": "main-buddyFeed-emptyBuddyFeed", + "gj9SOnCIzruGWAM5m3XO": "main-buddyFeed-friendActivity", + "oWQvtc5QZlmB60A9ejJx": "main-buddyFeed-friendsFeedContainer", + "nGInMrf62TCFD9MBnEzz": "main-buddyFeed-friendsList", + "NdQkQZhcYIEcJnRdAYcQ": "main-buddyFeed-header", + "BeABJha8PrxMcJmlBzcH": "main-buddyFeed-headerTitle", + "tli6RLZf7DdPtClCKK6_": "main-buddyFeed-link", + "n6rSk6R7nfmSGSgTRR5_": "main-buddyFeed-loadingFriends", + "VBQoaks4ZkfIknTKmxXZ": "main-buddyFeed-overlay", + "ylTErJiI2Ir_LqmrsaXV": "main-buddyFeed-panelTransition", + "kE5DI3BkNlo9zuO7K3aO": "main-buddyFeed-playbackContext", + "dvb9y9hcP8sUfMhUASKO": "main-buddyFeed-playbackContextIcon", + "hnEmEncF7kB2TnE_Uyja": "main-buddyFeed-playbackContextLink", + "Irsd58UNEmDPxdhXKXCs": "main-buddyFeed-playIcon", + "AWUxW13rbpNdQkvJJg13": "main-buddyFeed-scrollableArea", + "v_YrAYQP6fHG_z0hyg7C": "main-buddyFeed-scrollBarContainer", + "gWUxbU2cIHAajHxsVLMZ": "main-buddyFeed-section", + "WjW1oRtpaNrY37daDP6Y": "main-buddyFeed-sectionFadeEnter", + "C3bqciZSM7rPG_L3ohdC": "main-buddyFeed-sectionFadeEnterActive", + "T27BYdtZ9ugE_X_JpP1A": "main-buddyFeed-sectionFadeExit", + "RLdiPAZ3grZgi7lfHjXA": "main-buddyFeed-sectionFadeExitActive", + "LywlKLgNaEtHZzLM3EX5": "main-buddyFeed-timestamp", + "Lcc_yFPFIr7HSbt6aQbQ": "main-buddyFeed-title", + "cwcgvNz4amFDKqakIqxc": "main-buddyFeed-titleContainer", + "ktMuChpoidaEvECE7y8f": "main-buddyFeed-username", + "P7j2kCLc27vLybuzy5XB": "main-buddyFeed-usernameAndTimestamp", "LunqxlFIupJw_Dkx6mNx": "main-card-card", + "aAYpzGljXQv1_zfopxaH": "main-card-cardContainer", "tsv7E_RBBw6v0XTQlcRo": "main-card-cardLink", "E1N1ByPFWo4AJLHovIBQ": "main-card-cardMetadata", + "xHz124sSHSCYHecLCTfi": "main-card-cardTitle", + "w9Tpa4Y111UM5u1WMkEl": "main-card-DownloadStatusIndicator", "XiVwj5uoqqSFpS4cYOC6": "main-card-draggable", "kpO5z7v_Nr22lge440TY": "main-card-hero", "xBV4XgMq0gC5lQICFWY_": "main-card-imageContainer", + "NH6UaoYYe47eIHA2Rmal": "main-card-imageContainerOld", + "AYwATC_zEPwCkmO1yc8R": "main-card-imageContainerSkeleton", + "UB3cP9wsqoAMAHaeBGDt": "main-card-imagePlaceholder", + "r9Oj1LabijReMkOyeUxw": "main-card-newEpisodeIndicator", + "woJQ5t2YiaJhjTv_KE7p": "main-card-PlayButtonContainer", + "zuKTW9yEI9rToECOcWG3": "main-card-PlayButtonContainerVisible", "iwsv8i7rNxA2c_VvC4CO": "main-card-type", "c6FJaCManaNcchyUwvoL": "main-card-withWaves", "MxnDSnm9KnJu4xcsinKh": "main-card-withWavesWrapper", + "QO_OHdGt6X6luPH6_Lfg": "main-cardHeader-hasNewEpisodeIndicator", "Nqa6Cw3RkDMV8QnYreTr": "main-cardHeader-link", "nk6UgB4GUYNoAcPtAQaG": "main-cardHeader-text", "yYflTYbufy7rATGQiZfq": "main-cardImage-circular", "SKJSok3LfyedjZjujmFt": "main-cardImage-image", "g4PZpjkqEh5g7xDpCr2K": "main-cardImage-imageWrapper", + "qucSNjx66ofSGZDzCuEk": "main-cardSubHeader-isHero", "Za_uNH8nTZ0qCuIqbPLZ": "main-cardSubHeader-root", + "RArlOXg8S6l3NgRKrGsO": "main-cardSubHeader-text", + "r9YzlaAPnM2LGK97GSfa": "main-collectionLinkButton-collectionLinkButton", + "ot6VAZq1Xfbw2Vh8Qt_A": "main-collectionLinkButton-collectionLinkText", + "v1Gs5xaHy8aBhUMEobSn": "main-collectionLinkButton-dragEnter", + "bFQ9NOIn1bDs8tTH0ebQ": "main-collectionLinkButton-icon", + "GGx57b6ZwGgzUeTpynUw": "main-collectionLinkButton-iconWrapper", + "zDK1f3nL_R49a1mOvaO1": "main-collectionLinkButton-selected", + "MIsUJlamzLYuAlvPbmZz": "main-confirmDialog-button", + "X05XDhpQJ7THPHfgbUk1": "main-confirmDialog-buttonContainer", + "RVgHI2ejYct8LjT1AO7m": "main-confirmDialog-container", + "m0yIuS1Q6XRA5R4PNEhl": "main-confirmDialog-overlay", + "gQoa8JTSpjSmYyABcag2": "main-connectBar-connectBar", + "T3hkVxXuSbCYOD2GIeQd": "main-connectBar-connected", + "GcHojieewpdN1c8vbtwk": "main-connectBar-connecting", + "Cm3jbLBimhqdYEcNTVPj": "main-contextMenu-addToPlaylistSubtitle", + "OVv1uDz67TLurN8o6LtQ": "main-contextMenu-addToPlaylistTitle", + "EyDGMdJOp8ktTzmRFcQM": "main-contextMenu-clearButton", "pzkhLqffqF_4hucrVVQA": "main-contextMenu-disabled", + "jJzb9peSGYsUDKbc5QBy": "main-contextMenu-disabled", "NmbeQabkSLXf0mTAhSLl": "main-contextMenu-dividerAfter", + "pXsnH0sMlWUGBffe24cr": "main-contextMenu-dividerAfter", "QgtQw2NJz7giDZxap2BB": "main-contextMenu-dividerBefore", + "hYwu7ZpcbQIP6iM5fzAu": "main-contextMenu-dividerBefore", + "pc7Mq0FHh8Nlho4sOJH7": "main-contextMenu-expandButton", + "IErtLy9qyhR17riTrzYh": "main-contextMenu-expanded", + "qCnh1KNFmroitPazoXOc": "main-contextMenu-expandRight", + "ycGdaksV3Z5Y7eav3ZyQ": "main-contextMenu-filterInput", + "dJzYRtCWK2U6k08EtqAg": "main-contextMenu-filterInputContainer", + "zfZEbT8RJbcAg13pTMDl": "main-contextMenu-filterInputFullWidth", + "eG930DCaQXDFqjhxRGIs": "main-contextMenu-filterPlaylistSearch", + "i8EjndRQjYlli0aLGYEm": "main-contextMenu-filterPlaylistSearchContainer", + "M0E2Al6URHV3iyoDbvi_": "main-contextMenu-highlightedText", + "uEPiT_llP0oFNDYu_QZR": "main-contextMenu-loadingContainer", + "ibA08TpSVrM0wThmotVd": "main-contextMenu-loadingContainer", "SboKmDrCTZng7t4EgNoM": "main-contextMenu-menu", - "DuEPSADpSwCcO880xjUG": "main-contextMenu-menuItem", - "wC9sIed7pfp47wZbmU6m": "main-contextMenu-menuItemButton", + "k4sYYpEpX2f7RMAPHv3F": "main-contextMenu-menu", + "NbcaczStd8vD2rHWwaKv": "main-contextMenu-menu", + "re2d5HDzt6T4XBgqcBhi": "main-contextMenu-menuHeading", + "qUeWph4VP9DwR4xOfabh": "main-contextMenu-menuHeading", + "DuEPSADpSwCcO880xjUG": "main-contextMenu-menuItem", + "GqvHlGax1jo6vO9D0wHH": "main-contextMenu-menuItem", + "rQ6LXqVlEOGZdGIG0LgP": "main-contextMenu-menuItem", + "wC9sIed7pfp47wZbmU6m": "main-contextMenu-menuItemButton", + "SN9k988q2Seb_joCaEny": "main-contextMenu-menuItemButton", + "mWj8N7D_OlsbDgtQx5GW": "main-contextMenu-menuItemButton", + "PDPsYDh4ntfQE3B4duUI": "main-contextMenu-menuItemLabel", + "ctAknuakI8idqf_S9tvT": "main-contextMenu-menuItemLabel", + "llTZj1tjDr5ZnIOkKdHv": "main-contextMenu-menuItemStatic", + "Cjga8q3TFvtKCu9qfm27": "main-contextMenu-menuItemStatic", + "T2BaFHODss7KUUqG8Ryq": "main-contextMenu-overlay", + "_PqnQJddudWUtaIxOzo7": "main-contextMenu-searchIcon", + "dgc81JRAlkNQTsZae3Bz": "main-contextMenu-searchIconContainer", "iGw72tLfCJI5bdpgf7JQ": "main-contextMenu-subMenuIcon", + "IJYRnAk_0OE4UPQABQcl": "main-contextMenu-subMenuIcon", + "abJqsjKClbniwiTCZ7bC": "main-contextMenu-subMenuLeading", + "wtEUrk4Sxa5e3QZhvbrs": "main-contextMenu-subMenuLeading", + "X8yW2lJbFCQfV5GjoRwL": "main-contextMenu-tippy", + "nYdM55iHFByRTzJUmx9X": "main-contextMenu-tippy", + "mph1R_QkS44EPi4lrhxd": "main-contextMenu-tippyEnter", + "sNOxi993vqYCWYgo_N3H": "main-contextMenu-tippyEnter", + "v5IUMJNPJgol0273zQXD": "main-contextMenu-tippyEnterActive", + "z_29i58eLFLK50jAs_4a": "main-contextMenu-tippyEnterActive", + "bkFQH4uasL3pXqN9eDSi": "main-contextMenu-tippyWrapper", + "ExGt4YQfmcwvVFGM7tpN": "main-contextMenu-trigger", + "rVxzkDirgkuRPv5V1HYF": "main-coverSlotCollapsed-container", + "GQ5_gIWzIqAfBdmQm8yJ": "main-coverSlotCollapsed-container", + "qWcH8e2laY9sYOuCsOAx": "main-coverSlotCollapsed-expandButton", + "_9sCL61nGvQFXv2u02jXw": "main-coverSlotCollapsed-expandButton", + "IcyWfMS5VkeOhaI7OWIx": "main-coverSlotCollapsed-navAltContainer", + "jtRqaoDIpIR6fEATUTyY": "main-coverSlotExpanded-container", + "LROBF2WtGaVryVpVbSOu": "main-coverSlotExpanded-containerExpanding", + "FegbnTtU6poHbemMzmBP": "main-coverSlotExpanded-enter", + "i1SMAJ9KRyK_muq63Pmg": "main-coverSlotExpanded-enterActive", + "Q4cc5RktWgz2H8_vDrIS": "main-coverSlotExpanded-exitActive", + "Fih6l1HD6F3NRrdCEMFE": "main-coverSlotExpanded-expanding", + "g6ZgzRfiHjsTLskeyI0J": "main-coverSlotExpandedCollapseButton-collapseButton", + "IPVjkkhh06nan7aZK7Bx": "main-createPlaylistButton-button", + "q3ABXYJT9JZIzXOOtVuO": "main-createPlaylistButton-createPlaylistIcon", + "Bwc9jlVb7HWs8JJupnBB": "main-createPlaylistButton-icon", + "J4xXuqyaJnnwS6s2p3ZB": "main-createPlaylistButton-text", + "PrhIVExjBkmjHt6Ea4XE": "main-devicePicker-button", + "tyZF5iwaJ6J5raHWkxwu": "main-devicePicker-connectBarVisible", + "IbmaxRtjqCjqTBpFwCgw": "main-devicePicker-connected", + "l79vgNZqvs1q9nw6Q8A2": "main-devicePicker-connecting", + "E3EJEgTSJdjF1NrDf9GB": "main-devicePicker-connectingIcon", + "INitzTSjokOMEJOc6P2H": "main-devicePicker-controlButton", + "hwP4Oum2PB765sb8jigI": "main-devicePicker-devices", + "h3qSlLeqACMUaASiKDHa": "main-devicePicker-devicesHeading", + "zFqMGX3h5z2CO3f2uEiL": "main-devicePicker-devicesList", + "MMjN8VsyKsAlLjFw4RMa": "main-devicePicker-devicesOtherNetworksHeading", + "AXkwHpGa_BG7Dy4v7o2V": "main-devicePicker-header", + "tm3lCLoFzk25Q_df5g5K": "main-devicePicker-heading", + "pXrRjiuo3ZpGwIvDAGzJ": "main-devicePicker-headingAction", + "gz7xPnsQVKVMnQY2KjJs": "main-devicePicker-headingConnected", + "SzZayhxQEuTPMFgNrLOG": "main-devicePicker-headingContent", + "TJ5Bjp6vgnWVbh6mGN0n": "main-devicePicker-headingSubtitle", + "YY5a3DPS6akIYNqJdwn3": "main-devicePicker-headingTechIcon", + "E9qsFEgJZJnARk6hOCsj": "main-devicePicker-headingTitle", + "WFRr38dFOxh75JyzSTj5": "main-devicePicker-indicator", + "ntdp2T_przGKYzhwYSGz": "main-devicePicker-menuOpen", + "LVp1auH4vtD3hvb1s4gl": "main-devicePicker-moreButton", + "uWvwXlS0Da1bWsRX6KOw": "main-devicePicker-nowPlayingActiveIcon", + "pUkuSEO5HGdvTiujyI6H": "main-devicePicker-section", + "IdxmFS96lyE7c5uiTnLM": "main-devicePicker-sectionHeading", + "HVCCFeUiHVwZVv74p34a": "main-devicePicker-sectionWrapper", + "bk509U3ZhZc9YBJAmoPB": "main-devicePicker-tooltip", + "b46WEWO1Sc_P4WK5RTg0": "main-devicePicker-tooltipArrow", + "ItaYxdM8MiuHsa2VXuGQ": "main-devicePicker-tooltipContent", + "YUyFyiI58gL8VuLdbOD6": "main-devicePicker-troubleshooting", + "QClIatTm05fvjVzODr8X": "main-devicePicker-troubleshootingItemIcon", + "OTuSSciCS3NJqFG8OKX2": "main-devicePicker-troubleshootingItemSubtitle", + "AN2rvWrkrs7UsnY12hL8": "main-devicePicker-troubleshootingList", + "Fyc_tPyPKyRIT_59VZ2B": "main-downloadClient-actionContainer", + "Foyk_HJx16yh22JYmQ56": "main-downloadClient-container", + "UalNRoO1omHtEEniypS5": "main-downloadClient-container", + "_w3sHVCUhYgvQar5WNHw": "main-dragAndDrop-dndImage", + "vb8kSzIiZbfkwqWZROkW": "main-dragAndDrop-dndImageShelter", "zrvvPyoxE6wQNqnu0yWA": "main-dropDown-dropDown", + "jmu6DFPvhxRl0wSfmv2O": "main-dropDown-isSafari", + "T596E9OFZtarwLZV_Opk": "main-duplicateTrackModal-buttonContainer", + "AdF5F5BxQXGeWkfceg9A": "main-duplicateTrackModal-container", + "XBJ5gUPLDUdlCFkWV7PZ": "main-duplicateTrackModal-description", + "YDfNb_CMrwg2Z6FeLyNu": "main-duplicateTrackModal-title", + "MF2rLXp4d_JPNs2t0bbj": "main-editImage-buttonContainer", "jN7ZUHc7IxpwvWsjb4jo": "main-editImageButton-copy", "w3w0DS8atwcgOQJAKAV2": "main-editImageButton-icon", "xfQXUkj6ThzTYbfF8ilt": "main-editImageButton-image", "Usk1cPR7qbn7RudRN3td": "main-editImageButton-overlay", + "CdHBSRh3RhPwBNIBQtkD": "main-editImageButton-rounded", "PvesGiAqdV7dazP6Qulv": "main-embedWidgetGenerator-active", "oBoIIlKrwQjxXpvOiOa0": "main-embedWidgetGenerator-closeBtn", "U_nX_1rJoqQSWPJRE6zb": "main-embedWidgetGenerator-code", @@ -83,44 +402,92 @@ "H0vWBc23fJOetym6NudG": "main-entityHeader-bold", "ta4ePOlmGXjBYPTd90lh": "main-entityHeader-circle", "NXiYChVp4Oydfxd7rT5r": "main-entityHeader-container", + "kuSGKO1BuKZ3fgas7_T7": "main-entityHeader-creatorButton", "NO_VO3MRVl9z3z56d8Lg": "main-entityHeader-creatorWrapper", "Ydwa1P5GkCggtLlSvphs": "main-entityHeader-detailsText", - "RANLXG3qKB61Bh33I0r2": "main-entityHeader-metaDataText", + "n4hTP7ZeAOT_UQEkRUR7": "main-entityHeader-divider", "k2I8B0MzXkAJ6_s8okM7": "main-entityHeader-gradient", "PUIUCdIR_h05BC2EDgIP": "main-entityHeader-gray", "RP2rRchy4i8TIp1CTmb7": "main-entityHeader-headerText", + "CmkY1Ag0tJDfnFXbGgju": "main-entityHeader-image", "_gLjHpwOxHFwo5nLM8hb": "main-entityHeader-imageContainer", - "UB3cP9wsqoAMAHaeBGDt": "main-card-imagePlaceholder", + "GoU8CT9Vm_TP_LyYJTsf": "main-entityHeader-imageContainerClickable", + "_osiFNXU9Cy1X0CYaU9Z": "main-entityHeader-imageContainerNew", + "MclJZ2TMkhjdlqqQfmQd": "main-entityHeader-imagePlaceholder", "C7eyib8lynZrycU2Eh_A": "main-entityHeader-large", + "k9LEjzjnGgVaEm3BvhAb": "main-entityHeader-largeHeader", "Jnt9_XezZCMkZmtgBtlL": "main-entityHeader-medium", + "bQy_F9QVENlCAL8Qan9_": "main-entityHeader-mermaidGradientOverlay", "Fb61sprjhh75aOITDnsJ": "main-entityHeader-metaData", + "Yc6ftz7mCqbsTN4ha_ke": "main-entityHeader-metaDataAuthor", + "RANLXG3qKB61Bh33I0r2": "main-entityHeader-metaDataText", + "lD5bMttyrRNzsKch6ysa": "main-entityHeader-newEntityHeaders", "ByDYHUfzUKVgFwT5bTxp": "main-entityHeader-newEntriesIndicator", "RMDSGDMFrx8eXHpFphqG": "main-entityHeader-nonWrapped", "xYgjMpAjE5XT05aRIezb": "main-entityHeader-overlay", + "YW4dYEf5ZuLzMfSjsqZk": "main-entityHeader-piled", + "lp9Tfm4rsM9_pfbIE0zd": "main-entityHeader-pretitle", + "YbDIZ84mS7tzHr1tgWE9": "main-entityHeader-roundedCorners", "_EShSNaBK1wUIaZQFJJQ": "main-entityHeader-shadow", "D5X2O0j5dhTZJIkgH8mz": "main-entityHeader-small", "U1ypKorrS1qiWD1uQpAD": "main-entityHeader-smallHeader", + "zjsGbrMpvbdA1HJ4rpfi": "main-entityHeader-smallMadeForIcon", "gSx70PISJg6PSRafbOXd": "main-entityHeader-subtitle", "YxJ3zwH0R8K8njVQgMcw": "main-entityHeader-subtitleButton", + "RmWKJG2G0fTrx11zKv_j": "main-entityHeader-theyFollowUs", "rEN7ncpaUeSGL9z0NGQR": "main-entityHeader-title", "wCkmVGEQh3je1hrbsFBY": "main-entityHeader-titleButton", + "o4KVKZmeHsoRZ2Ltl078": "main-entityHeader-titleInner", "HcA9WjbLc4x02X8Ty0uO": "main-entityHeader-topbarContent", "lro6AjUrZFH6zxjmOGg0": "main-entityHeader-topbarContentFadeIn", "G7zO58ORUHxcUw0sXktM": "main-entityHeader-topbarTitle", "E0MlERsQ_zvY3BX7ZzPp": "main-entityHeader-uppercase", "L29j6que7xOiNSH_EOvQ": "main-entityHeader-wavesBackground", "XPjEhsPyuOvMZ9NsDrxT": "main-entityHeader-withBackgroundImage", + "KAZD28usA1vPz5GVpm63": "main-genericButton-button", + "RK45o6dbvO1mb0wQtSwq": "main-genericButton-buttonActive", + "EHxL6K_6WWDlTCZP6x5w": "main-genericButton-buttonActiveDot", + "OomFKn3bsxs5JfNUoWhz": "main-globalNav-buddyFeed", + "VizXsWMIuNfKGN5pMyox": "main-globalNav-historyButtons", + "Z6t_8rA6LOBrX3huqRJG": "main-globalNav-historyButtonsContainer", + "pIM9jg__39NIpOvXG89b": "main-globalNav-historyButtonsContainer", + "rBX1EWVZ2EaPwP4y1Gkd": "main-globalNav-icon", + "jdlOKroADlFeZZQeTdp8": "main-globalNav-link-icon", + "dIfr5oVr5kotAi0HsIsW": "main-globalNav-link-icon", + "bWBqSiXEceAj1SnzqusU": "main-globalNav-navLink", + "voA9ZoTTlPFyLpckNw3S": "main-globalNav-navLinkActive", + "ETjtwGvAB4lRVqSzm8nA": "main-globalNav-navLinkActive", + "QrpHSphgBSqzODEHqr_t": "main-globalNav-searchContainer", + "lj0eGI6WEtfxFX7irC03": "main-globalNav-searchContainer", + "fksI89zEXwqKWm1O6sJm": "main-globalNav-searchInputContainer", + "W9VXOkC43GP_7ULClgxQ": "main-globalNav-searchInputContainer", + "PvsV2JgJRDME1vDn6IJL": "main-globalNav-searchInputSection", + "tDFP1X98EgqQIPaumxRt": "main-globalNav-searchInputSection", + "W02pQCvfy5Bin7z4EAzo": "main-globalNav-searchSection", + "gj5VcIUC9oD2p4BsxzGE": "main-globalNav-searchSection", "soGhxDX6VjS7dBxX9Hbd": "main-gridContainer-fixedWidth", "iKwGKEfAfW7Rkx2_Ba4E": "main-gridContainer-gridContainer", - "pgwIORyBdf4nbb4G5_Jx": "main-heroCard-PlayButtonContainer", + "PmW2UCL9vlTcNPD7J0KJ": "main-gridContainer-uniformRowHeight", "HkbHLcqgUfXruL5xVi28": "main-heroCard-card", "_gB1lxCfXeR8_Wze5Cx9": "main-heroCard-cardLink", "sm7ZnbOO1Zfg9cupYgPN": "main-heroCard-cardMetadata", "kVHQenQh3yKEk2n7Ere4": "main-heroCard-draggable", + "NkDkQMd75JY5xes9xFVe": "main-heroCard-isDownloadable", + "liYe8rZ0FEQBy8j8XGJH": "main-heroCard-isPlaying", + "pgwIORyBdf4nbb4G5_Jx": "main-heroCard-PlayButtonContainer", + "I3EivnXTjYMpSbPUiYEg": "main-home-content", + "uIJTvxFOg2izOY7aRRiU": "main-home-home", + "HsbczDqu9qjcYr7EIdHR": "main-home-homeHeader", + "DQRst2WAECYq2xsrsPRA": "main-home-isOffline", + "QbD9zl7z3AhEQu_TGmo8": "main-home-subfeedSection", + "_kVOt2H6WxXzURx2FRLM": "main-home-withAds", "mMx2LUixlnN_Fu45JpFB": "main-image-image", + "Yn2Ei5QZn19gria6LjZj": "main-image-loaded", + "yOKoknIYYzAE90pe7_SE": "main-image-loading", "wcftliF4QjZKB1CYgEON": "main-imagePicker-fileInput", "IuU_JLhFTfKPXfDkmAaF": "main-keyboardShortcutsHelpModal-closeBtn", "YyxAoeTuu0BHU1OcahFK": "main-keyboardShortcutsHelpModal-container", + "EhyK_jJzB2PcWXd5lg24": "main-keyboardShortcutsHelpModal-container", "e4ETsc5zxjzyF9nyb4LI": "main-keyboardShortcutsHelpModal-header", "hykQHtPI6EeFREwqRrOR": "main-keyboardShortcutsHelpModal-key", "ARw2f2PkF29n9Ek_eWu3": "main-keyboardShortcutsHelpModal-sectionHeading", @@ -129,17 +496,32 @@ "KDlcc1SFTcA90eMUcn5P": "main-keyboardShortcutsHelpModal-sections", "cyXplMovoowBozEe4r2x": "main-keyboardShortcutsHelpModal-sectionsContainer", "X871RxPwx9V0MqpQdMom": "main-leaderboardComponent-container", + "Nd_DeCpszONzyaLe5Wd1": "main-likedSongsButton-likedSongsIcon", + "BuzoTjBZd1UqCn6DmFJr": "main-loadingIndicator-circle", + "HKamyJi9H31s99erfVyG": "main-loadingIndicator-loadingIcon", "K7fGF95OD9aI3zdYnFXg": "main-loadingPage-container", + "y7xcnM6yyOOrMwI77d5t": "main-lyricsCinema-container", + "TITRkcJffQbL60GWevgh": "main-lyricsCinema-content", + "xnPS9Fa6efctzBjM05O4": "main-lyricsCinema-controls", + "AptbKyUcObu7QQ1sxqgb": "main-lyricsCinema-lyricsCinemaVisible", + "YtsqA6txqmCqkKq0G2Ta": "main-lyricsCinema-nonDisplayedArea", "T0anrkk_QA4IAQL29get": "main-moreButton-button", + "NyIynkmMpZXSoaE3XGhA": "main-navBar-banner", + "WvLkmOVB2R2vzI2ibR_r": "main-navBar-downloadItem", "RSg3qFREWrqWCuUvDpJR": "main-navBar-entryPoints", + "WJsKJXEbycxxq8OcGHM1": "main-navBar-logo", + "sqKERfoKl4KwrtHqcKOd": "main-navBar-mainNav", + "lYpiKR_qEjl1jGGyEvsA": "main-navBar-mainNav", "tUwyjggD2n5KvEtP5z1B": "main-navBar-navBar", "eNs6P3JYpf2LScgTDHc6": "main-navBar-navBarItem", + "b2KVTiBUcXV1kT0OjL2p": "main-navBar-navBarItemDropTarget", "ATUzFKub89lzvkmvhpyE": "main-navBar-navBarLink", "moDRd9td0KtitPDzR7OJ": "main-navBar-navBarLinkActive", - "GTAFfOA_w5vh_bDaGJAG": "main-actionButtons", - "NPvLJSRWfv1Joo8dF0D8": "main-actionButtons", - "WIGgdAaAzrXm7f_loaXi": "main-actionButtons-button", - "vQNZsbpzoUFSW5fsFOAw": "main-notificationBubble-NotificationBubble", + "GKnnhbExo0U9l7Jz2rdc": "main-navBar-premiumLink", + "uhxXhw9alI7KR1YTc904": "main-navBar-premiumNavItem", + "IebnAuNOhIG5mDVNJQ5M": "main-noConnection-isError", + "N3juGUCH1EhEzmffNHAp": "main-noConnection-isNotice", + "w3PliL6VjTaj2VfscF_k": "main-notificationBubble-closeIcon", "ZKFK00olAYy6LtYMjEIa": "main-notificationBubble-enter", "QlivAoYbLCn5nS3zU331": "main-notificationBubble-enterActive", "o_GEOPl4MEZXycGnTN69": "main-notificationBubble-exit", @@ -149,13 +531,99 @@ "_cDysv1Z9Ihw848shb92": "main-notificationBubble-isCloseable", "sgWxJyCSuqvdP5VZhqts": "main-notificationBubble-isError", "hmqCvVdVEXlW52i3efqa": "main-notificationBubble-isNotice", + "vQNZsbpzoUFSW5fsFOAw": "main-notificationBubble-NotificationBubble", "mtmSGKkBYNwbd49V_8fS": "main-notificationBubble-withPointer", "zrZgCe7tURBRdKkFGc7S": "main-notificationBubble-withSidePointer", "a3nLBllaudGWnYzNTND_": "main-notificationBubble-withTopLeftPointer", "_XeODCkWznZi5csbdPAe": "main-notificationBubble-withTopRightPointer", "AOaoydTb5lrGytHbTAAy": "main-notificationBubbleContainer-NotificationBubbleContainer", + "wh7q2LxxjhyXLJvxRQGG": "main-nowPlayingBar-buddyFeedIcon", + "P4eSEARM2h24PZxMHz1T": "main-nowPlayingBar-center", + "sVv2OQORCQ4kf6iKfUTF": "main-nowPlayingBar-center", + "GD2gbRtcs5dOjMGAM_Y4": "main-nowPlayingBar-container", + "yglmI5m3fCc8baD1Kwdw": "main-nowPlayingBar-container", + "RtrMo_s0acvzbSRLovVW": "main-nowPlayingBar-enter", + "D4el1GTrNd7l_TFyRGO8": "main-nowPlayingBar-enterActive", + "HOZJyu9UCJodOQSVvduV": "main-nowPlayingBar-enterDone", + "mwpJrmCgLlVkJVtWjlI1": "main-nowPlayingBar-extraControls", + "tT6x7wFZmjldiCeh6HzO": "main-nowPlayingBar-isAnonymous", + "OgkbKIVYE_mrNpYESylB": "main-nowPlayingBar-left", + "snFK6_ei0caqvFI6As9Q": "main-nowPlayingBar-left", + "Xmv2oAnTB85QE4sqbK00": "main-nowPlayingBar-lyricsButton", + "OCY4jHBlCVZEyGvtSv0J": "main-nowPlayingBar-nowPlayingBar", + "udArIAqnfUQPQew2VAns": "main-nowPlayingBar-nowPlayingBar", + "jOKLc29vP0Bz1K0TsDtX": "main-nowPlayingBar-right", + "pLifNBuHRY8cZkZyEqwL": "main-nowPlayingBar-right", + "uVRRxsH6RKj3Dzhl40Ok": "main-nowPlayingBar-topButton", + "ExuDUBJ7bk8vT6INnm9F": "main-nowPlayingBar-volumeBar", + "U3kNTAyv7lhF9nBuwgB6": "main-nowPlayingView-aboutArtist", + "muTn937T_T9l0xqjlN8A": "main-nowPlayingView-aboutArtistBio", + "Tk7SUvI_ULiUuC5gZsIx": "main-nowPlayingView-aboutArtistButton", + "ldx08BCI74rTPhgD3vbj": "main-nowPlayingView-aboutArtistContent", + "HISuyqmMLx0amzWHxgN1": "main-nowPlayingView-aboutArtistHasImage", + "RJvcrFChbhxGRIi8mBXJ": "main-nowPlayingView-aboutArtistPlaceholderWrapper", + "DjnRJuC2FcNrQ6Q6DerZ": "main-nowPlayingView-aboutArtistTextContent", + "vbsB4OQJkFHLU8SbSGzS": "main-nowPlayingView-aboutArtistV2", + "jLPxNlznfpZHUtITCFnb": "main-nowPlayingView-aboutArtistV2Avatar", + "r9m6lHy7RyIPDzW1Youe": "main-nowPlayingView-aboutArtistV2Bio", + "hd6a3g_3QyF8MFL0wWs1": "main-nowPlayingView-aboutArtistV2Button", + "kVP43jHrJeS7afn8mOgX": "main-nowPlayingView-aboutArtistV2FollowButton", + "z9CDQr2gnyXDtcc1uF05": "main-nowPlayingView-aboutArtistV2HasImage", + "ouorHKa6NI5cm666H3tp": "main-nowPlayingView-aboutArtistV2Image", + "GTmlByXpJj7V6AwVq0Vk": "main-nowPlayingView-aboutArtistV2ImageContainer", + "iWpZp7Ab_9h7s_U1SsLN": "main-nowPlayingView-aboutArtistV2Listeners", + "zhQX2DOI2muMo8EKsZ6h": "main-nowPlayingView-aboutArtistV2ListenersCount", + "COJ84QbXPrd4jkO1HU2N": "main-nowPlayingView-aboutArtistV2Name", + "yIPdY6L6pcwR4L5Xf0vY": "main-nowPlayingView-aboutArtistV2PlaceholderWrapper", + "QkOkUShDYWFx5Cz40Bcn": "main-nowPlayingView-aboutArtistV2TextContent", + "vkS_Ks0svKls4w2s2ppT": "main-nowPlayingView-aboutArtistV2Title", + "IgTMXVbZtqtZwu3GZASd": "main-nowPlayingView-artistOnTour", + "uvIvZ4XqfEFs88BAPaI8": "main-nowPlayingView-artistOnTourItem", + "svHFeMC3Ef_TpSdRyvsM": "main-nowPlayingView-artistOnTourShowAll", + "QIuMX9iPlMiflBPUkrEQ": "main-nowPlayingView-container", + "jtqtOeRP46XAlHWx4C0D": "main-nowPlayingView-content", + "aaFQbW0j0N40v_siz0kX": "main-nowPlayingView-contextItemInfo", + "j9I5h3Z4o0fKNgI1fIjb": "main-nowPlayingView-coverArt", + "zL6hQR4mukVUUQaa_7K1": "main-nowPlayingView-coverArtContainer", + "l2PpoXJouAgqFCuNT3iB": "main-nowPlayingView-credits", + "g5zF2gHZOarew6ApvZB6": "main-nowPlayingView-creditsGroup", + "kUyRPckYBgHDaJp8bmXi": "main-nowPlayingView-creditsHeader", + "bBldZtWu4QtzmrTfHOKm": "main-nowPlayingView-creditsShowAll", + "PqjIyA05rhDaDg2S1qIQ": "main-nowPlayingView-creditsSource", + "MPBLLykSgRJIlLSbQVgy": "main-nowPlayingView-gradient", + "SfAYznqZyNk_AvvxIkUx": "main-nowPlayingView-header", + "hzUuLPdH48AzgQun5NYQ": "main-nowPlayingView-lyricsContent", + "KzMnBC9eFK8cAfcFTg9b": "main-nowPlayingView-lyricsControls", + "I2WIloMMjsBeMaIS8H3v": "main-nowPlayingView-lyricsGradient", + "N9Xjnxz8vGgWwbEBE5g7": "main-nowPlayingView-lyricsTitle", + "wpJvLvrrnyP0_C7hLkqg": "main-nowPlayingView-merch", + "n4_WcnoVeg2SeDJPWnKK": "main-nowPlayingView-nextInQueue", + "cIUedsmg_cTnTxvOYTKR": "main-nowPlayingView-nowPlayingGrid", + "fIpDXK7M3W0Bn3FgLSRe": "main-nowPlayingView-nowPlayingWidget", + "PqL625rkFi7CBiMggYTP": "main-nowPlayingView-openQueue", + "wkl1CJw1cTKpqlKDAiln": "main-nowPlayingView-panelOpenDiv", + "byIN5OSjNcJHipcI9kuf": "main-nowPlayingView-playNext", + "LT6lpp3S4Tx8VsbnPzuA": "main-nowPlayingView-playNextButton", + "A4e013b7hUST0QPHFqKr": "main-nowPlayingView-playNextButtonIcon", + "V6Fgup3wwQdhZVYVntrH": "main-nowPlayingView-playNextIcon", + "qbOrWcMUhSri1nPkZLQA": "main-nowPlayingView-queue", + "Mj718TwbPAUi_iNAcsmz": "main-nowPlayingView-queueItem", + "Nyxk_izrYbGecpgmtp91": "main-nowPlayingView-queueItemEntityImage", + "Ai_McRq9wJEYK21w8nX_": "main-nowPlayingView-section", + "EVqc6HChiM9pEqBYAiUE": "main-nowPlayingView-sectionHeader", + "gpDSOimnzH4zTJmE7UR5": "main-nowPlayingView-sectionHeaderSpacing", + "zZdI03asKaUCNlbhjDAv": "main-nowPlayingView-sectionHeaderText", + "hfdkySA4kiUldFsPj9lD": "main-nowPlayingView-trackInfo", + "BFR9Zt3zpL8BATBMiwQB": "main-nowPlayingWidget-coverArt", + "bYHWD_eQ1jAh3sAKTHtr": "main-nowPlayingWidget-coverExpanded", + "deomraqfhIAoSB3SgXpu": "main-nowPlayingWidget-nowPlaying", + "j96cpCtZAIdqxcDrYHPI": "main-nowPlayingWidget-trackInfo", "fFv7yCuLuIO1dAGZHcVf": "main-pageErrorTemplate-errorBody", + "npFSJSO1wsu3mEEGb5bh": "main-playbackBarRemainingTime-container", + "kQqIrFPM5PjMWb5qUS56": "main-playbackBarRemainingTime-container", + "f4XfIkH9v3tBTnI8AEDj": "main-playButton-lockIcon", "IeLnf2wUHVKqxhzBcBoM": "main-playButton-PlayButton", + "PFgcCoJSWC3KjhZxHDYH": "main-playButton-PlayButton", "KOoUMuC7IxI_1Pi4r4m5": "main-playButton-primary", "VgweZbpfbMSfOcTeGNj_": "main-playButton-secondary", "D7HQ50jRBGU8qaAGHRTw": "main-playButton-transparent", @@ -185,31 +653,111 @@ "qOBo9jzgJoMkt2Ad8fur": "main-playlistEditDetailsModal-titleCharacterCounter", "JaGLdeBa2UaUMBT44vqI": "main-playlistEditDetailsModal-titleInput", "SuHDp5IvWoCq1P8yJQmo": "main-playlistEditDetailsModal-titleInputWithPadding", + "AytCc2WKUld6N212Pcpu": "main-playlistRemoveMultipleModal-buttonContainer", + "J0xJcBaKhwl9EIuzvhLg": "main-playlistRemoveMultipleModal-container", + "tlBLfMv0fCxd31jPTQhL": "main-playlistRemoveMultipleModal-description", + "ce3qMCnc2kDVSi7k74fh": "main-playlistRemoveMultipleModal-title", + "vnCew8qzJq3cVGlYFXRI": "main-playPauseButton-button", + "QavgDs_52SpJ2rw0LNYz": "main-popper-arrow", + "aCtCKL9BxAoHeVZS0uRs": "main-popper-container", "kMVnZekiwoVgg0Vjd418": "main-progressRing-circleColor", "PcjBXoPwLAnvPiTQx79g": "main-progressRing-circleShadow", - "q8AZzDc_1BumBHZg0tZb": "main-shelf-header", - "HOgue4Eg4UdBR58M0633": "main-shelf-seeAll", - "QyANtc_r7ff_tqrf5Bvc": "main-shelf-shelf", - "Z4InHgCs2uhk0MU93y_a": "main-shelf-shelfGrid", - "BtbiwMynlB4flsYu_hA2": "main-shelf-showAll", - "onVWL7MW4PW9FyVajBAc": "main-shelf-titleWrapper", - "OMuRYOdpUbGif12_lRJl": "main-shelf-topRow", - "r4Qmv_YM7IHogP2i1tmJ": "main-shelf-browseGridSection", - "kpGMQq1KFz620g_BD_dS": "main-tag-container", - "Upqw01TOXETOmR5Td7Dj": "main-topBar-UpgradeButton", - "pfMoD1MbelMuF1m8QeMc": "main-topBar-forward", - "T1xI1RTSFU7Wu94UuvE6": "main-topBar-background", - "ql0zZd7giPXSnPg75NR0": "main-topBar-button", - "facDIsOQo9q7kiWc4jSg": "main-topBar-container", - "MIX_wd0K1tVHme_pwV2F": "main-topBar-contentArea", + "tP0mccyU1WAa7I9PevC1": "main-repeatButton-active", + "Vz6yjzttS0YlLcwrkoUR": "main-repeatButton-button", + "qnYVzttodnzg9WdrVQ1p": "main-rootlist-bottomSentinel", + "xkHiFJhykpOWcVMMPufq": "main-rootlist-dropIndicator", + "I_aApN9pSlbGcpLtFQWw": "main-rootlist-expandArrow", + "NTJM_mh36C5kJ5oO8eac": "main-rootlist-expandArrowActive", + "LKgm9fCDTO7wqig_5U1q": "main-rootlist-rootlist", + "EY6S7vlkxB7SF_OjjF_Y": "main-rootlist-rootlistContent", + "FBPrcmuqo3yv5UfWSRl5": "main-rootlist-rootlistDivider", + "McwcCfBLSuXa5UDU1IMw": "main-rootlist-rootlistDividerContainer", + "Y8edH1Yjo4xrW_58czQj": "main-rootlist-rootlistDividerGradient", + "whXv9jYuEgS1DPTmPCe_": "main-rootlist-rootlistItem", + "utSR0FVkHnII_aL8TOcu": "main-rootlist-rootlistItemLink", + "K8Rs3qAYirS8wJ1hR8gn": "main-rootlist-rootlistItemLinkActive", + "AINMAUImkAYJd4ertQxy": "main-rootlist-rootlistItemOverlay", + "tojGvx6tcIBmKlICMJAZ": "main-rootlist-rootlistPlaylistsScrollNode", + "g_jOSq3pLY5p4tldskrw": "main-rootlist-statusIcons", + "gtuJjD43VjwtP8ii3H3P": "main-rootlist-statusIcons", + "VjIb8SfYTkc4wMpqqj3f": "main-rootlist-textWrapper", + "lyVkg68L7ycnwyOcO3vj": "main-rootlist-topSentinel", + "JUa6JJNj7R_Y3i4P8YUX": "main-rootlist-wrapper", + "rKdWluhLAGpdUFBWN8sK": "main-seeAll-link", + "MRfNcNMd_djj3KOg_VOB": "main-seekBackButton-button", + "XGCdw_LcXQHrxmvpxjwi": "main-seekForwardButton-button", + "r4Qmv_YM7IHogP2i1tmJ": "main-shelf-browseGridSection", + "q8AZzDc_1BumBHZg0tZb": "main-shelf-header", + "HOgue4Eg4UdBR58M0633": "main-shelf-seeAll", + "QyANtc_r7ff_tqrf5Bvc": "main-shelf-shelf", + "Z4InHgCs2uhk0MU93y_a": "main-shelf-shelfGrid", + "Sdmk6QLCvk5EuAP54IN5": "main-shelf-shelfGridResponsive", + "PodseQtNc4pWHyOfGkgA": "main-shelf-shelfGridResponsiveMultiRows", + "BtbiwMynlB4flsYu_hA2": "main-shelf-showAll", + "WkSW1U6jr3HDz3vApM56": "main-shelf-skeletonShelf", + "hWGxHSAKACFWXowXPDTP": "main-shelf-subHeader", + "MfVrtIzQJ7iZXfRWg6eM": "main-shelf-title", + "onVWL7MW4PW9FyVajBAc": "main-shelf-titleWrapper", + "OMuRYOdpUbGif12_lRJl": "main-shelf-topRow", + "OF_3F0SQCsBtL1jSTlTA": "main-shuffleButton-active", + "KVKoQ3u4JpKTvSSFtd6J": "main-shuffleButton-button", + "fn72ari9aEmKo4JcwteT": "main-skipBackButton-button", + "mnipjT4SLDMgwiDCEnRC": "main-skipForwardButton-button", + "d89qxCxbCRj4y1Woft8j": "main-smartShuffleButton-active", + "kpGMQq1KFz620g_BD_dS": "main-tag-container", + "T1xI1RTSFU7Wu94UuvE6": "main-topBar-background", + "IAyWaeDamLJLjxuPeVKw": "main-topBar-buddyFeed", + "WtC1lGbmQRplD6JBhNFU": "main-topBar-buddyFeed", + "W0bXxvPV_DhyzwdJWRuU": "main-topBar-buddyFeedActive", + "CE17OcVsW2svuK7ebBcx": "main-topBar-buddyFeedIcon", + "ql0zZd7giPXSnPg75NR0": "main-topBar-button", + "J6VTd7VdGN2PM_oXCAyH": "main-topBar-button", + "qvXMfQh1CjESoKKX49Bl": "main-topBar-buttonActive", + "facDIsOQo9q7kiWc4jSg": "main-topBar-container", + "MIX_wd0K1tVHme_pwV2F": "main-topBar-contentArea", + "BkpKedcdaMGbvgXMlmcg": "main-topBar-contentArea", + "OOsg_GCQDERDXc1d0EmC": "main-topBar-entryPoints", + "pfMoD1MbelMuF1m8QeMc": "main-topBar-forward", + "Oq5wiHCwgjjMg_VYy068": "main-topBar-fullscreenHistoryButtons", "VgSbatGBB9XwTH2_dsxg": "main-topBar-historyButtons", + "fWwn9sakqBBjgiNti7LD": "main-topBar-historyButtons", "IYDlXmBmmUKHveMzIPCF": "main-topBar-icon", + "ou0osOf3R1ZRWQ1xzFd9": "main-topBar-icon", + "cqO5c3gPyN6tXIddpWfr": "main-topBar-left", "qxbaGYC8rgMLfyOuYRCM": "main-topBar-loggedOut", + "LKFFk88SIRC9QKKUWR5u": "main-topBar-loginButtons", + "zuf9gCpkf86KkzzCtkJN": "main-topBar-navLink", "EvIR4O7jOSbNmxtMdIQ0": "main-topBar-overlay", + "CWFTCu03cdDALodezHmA": "main-topBar-responsiveForward", + "fl1Ov5aB9YCKnMkJYpEu": "main-topBar-right", + "VGKBvschhennrwdTibUE": "main-topBar-rightSidebarVisible", + "g3Xinb8x23n81ejvS9Uj": "main-topBar-searchBar", + "btOYheZlYlaVEyO9iEBk": "main-topBar-sectionWrapper", + "sibxBMlr_oxWTfBrEz2G": "main-topBar-signupButton", + "eBrbJuUWgMoCkOgWs5uw": "main-topBar-topBarContainer", "qHWqOt_TYlFxiF0Dm2fD": "main-topBar-topbarContent", + "rwdnt1SmeRC_lhLVfIzg": "main-topBar-topbarContentRight", "rovbQsmAS_mwvpKHaVhQ": "main-topBar-topbarContentWrapper", - "Y22srYwXssaWnfD1MXis": "main-topBarStatusIndicator-TopBarStatusIndicatorContainer", + "sNde2kloCY28V4GB9AvP": "main-topBar-topNavBarLinks", + "k0vXhOdr0XE83lAQaJ1O": "main-topBar-topNavBarSeparator", + "Upqw01TOXETOmR5Td7Dj": "main-topBar-UpgradeButton", + "rqZoelG5u2vHb3kedEph": "main-topBar-UpgradeButton", + "I4p8r1UNjIGk9yv3H2Ms": "main-topBar-whatsNewFeed", + "t794tYAiOJib_IAmmdqq": "main-topBar-whatsNewFeedActive", + "t93PZphItuM19kPhX7tC": "main-topBar-whatsNewFeedIcon", + "RJGA3d0jzObTXwoMUH4p": "main-topBar-whatsNewFeedNotification", + "kwTbLplLLsW6T_LrtR7_": "main-topBar-whatsNewFeedNotificationDot", + "dmF7or26BvPJs5kQtYVH": "main-topBar-whatsNewFeedNotificationTitle", + "coBkWVskipFo8KxLKief": "main-topBar-withBackgroundBlur", + "g_OLJCea3ISA_OEZXMld": "main-topBarStatusIndicator-enter", + "eUtkhxZmvSKe4G9vJbvG": "main-topBarStatusIndicator-enterActive", + "y0CwI5JkA0h0OyLFf53Q": "main-topBarStatusIndicator-exitActive", "uObDRTsYYQmLhK7QzuFF": "main-topBarStatusIndicator-hasTooltip", + "JbIx9RVHwxVXRbXAJaeN": "main-topBarStatusIndicator-notMinimized", + "FannkPV_e2vWawF9QgVA": "main-topBarStatusIndicator-tooltipEnter", + "CtNz_OQHOZ5Z0mJMHjzw": "main-topBarStatusIndicator-tooltipEnterActive", + "rSvmoStBWe2Cft5bw9ya": "main-topBarStatusIndicator-tooltipIsError", + "Y22srYwXssaWnfD1MXis": "main-topBarStatusIndicator-TopBarStatusIndicatorContainer", "mqZLFQb6fadgKQww5AFV": "main-trackCreditsModal-additionalCredits", "xd9f6OsPqmyb6CefhTRR": "main-trackCreditsModal-clickableCreditsEntry", "VKCcyYujazVPj6VkksPM": "main-trackCreditsModal-closeBtn", @@ -221,11 +769,25 @@ "iGT1RlMPCwUlIiRPbOqg": "main-trackCreditsModal-originalCredits", "bpaf11XBuMN_hd95L9ol": "main-trackCreditsModal-sectionTitle", "DAIH23Yj6NeioZ6jooQ6": "main-trackCreditsModal-sourceNames", + "gpNta6i8q3KYJC6WBZQC": "main-trackInfo-artists", + "ZcNcu7WZgOAz_Mkcoff3": "main-trackInfo-container", + "W5cB_o0XkkU7Q8tlTGxq": "main-trackInfo-contentContainer", + "PGSe59fD1Hwc9yUM2d3U": "main-trackInfo-contentWrapper", + "s1jyNJBxq16eqkqCf6Ax": "main-trackInfo-enhanced", + "y6bXimbi8JAcblOFxTap": "main-trackInfo-equalGradientWidth", + "Q_174taY6n64ZGC3GsKj": "main-trackInfo-name", + "eSMjmiD29Ox35O95waw6": "main-trackInfo-overlay", + "aMhBfOqJxn4jKzFN07Lg": "main-trackInfo-rightToLeft", + "Ty1q4GZz5EJ7Yl2jHs5I": "main-trackInfo-xsmallBadges", "Ry7zokVNFKXaDxKp1Qf1": "main-trackList-actionsHeader", "iSbqnFdjb1SuyJ3uWydl": "main-trackList-active", "eWNJl03RSvGa9VsxkJ_7": "main-trackList-addedBy", "zxSdNpIMNoVh8g3F9fqt": "main-trackList-arrow", + "wE9dp6W8uInhrlbWPMsR": "main-trackList-chartTrackList", "ASYv4mEu1lXEHVa04HqY": "main-trackList-column", + "r53kBgGOdrCYj2Jux0iN": "main-trackList-columnResizing", + "Wn5NpEuR1Qw99DelnfxX": "main-trackList-concertTrackList", + "KJeaWI3jCZemsmu4eYL3": "main-trackList-curationButton", "SzsIJoBzlexhelPsHXnn": "main-trackList-delayedVisibility", "Ar1CZ7qjPHuIJY0cI56W": "main-trackList-disabled", "UuAaE00MS64uibJyxXxK": "main-trackList-discRow", @@ -233,14 +795,22 @@ "WTbn2dLWM9fMMb3O4uKZ": "main-trackList-dropTargetAfter", "xhgesf8qPsbyZY2NaYdH": "main-trackList-dropTargetBefore", "AgiCqnZUliKs_dafpdyi": "main-trackList-durationHeader", + "m6Bvw7PNXw2WXqruLOLE": "main-trackList-enhanced", "vr04lRmH66LzICUXnwCq": "main-trackList-eventDate", "OINF2mTM4cu2JjtkmPiz": "main-trackList-eventTicketIcon", + "vL_PgycspyjCBwfFg9j9": "main-trackList-eventVenue", + "dZiDwJihz32GwQunXhnB": "main-trackList-facepile", + "uWYVhrrTnV2V_VYhThDl": "main-trackList-facepileAvatar", "FCzIz5e0Lpt4xa5zz2F1": "main-trackList-icon", + "vBFTtFW3Co9F_yJ_HjF4": "main-trackList-icon", "Ss6hr6HYpN4wjHJ9GHmi": "main-trackList-indexable", "Kb365Ykr7fUEvnvOH0vl": "main-trackList-isNextRowSelected", "dXWJ1DecZeg_dpXZUbHL": "main-trackList-isPreviousRowSelected", + "vDk3w0iWhhczk8PS_K3B": "main-trackList-isRecommendedTrackListRow", "HOP1JqKm27djuzPVbaRl": "main-trackList-nineteen", + "w304euOUWkI5A8qAqFj8": "main-trackList-notificationDot", "VrRwdIZO0sRX1lsWxJBe": "main-trackList-number", + "nEZjuVeUuGSmYaQWgXTd": "main-trackList-ownedBySelf", "Iy7vi9cVsy6pS6wF8Dud": "main-trackList-placeholder", "Dj9_CzXA7IbUFIz4wOsA": "main-trackList-placeholderEnd", "cF8vKdBGYRZs_SpaG0Yz": "main-trackList-placeholderIndex", @@ -249,8 +819,12 @@ "noANc1fQSmaQNKYVDEDQ": "main-trackList-placeholderVariable", "n5XwsUqagSoVk8oMiw1x": "main-trackList-playingIcon", "TYVy_QqiFWgzw0WkUiHb": "main-trackList-playsHeader", + "B2Dwok3Y07k2ttjGDssH": "main-trackList-queuePanelTracklist", + "Bob5Qz4qd2ApsH6o1loA": "main-trackList-resizeHandle", "sQcIERaiZKFhOM1LrSmX": "main-trackList-rowBadges", + "UeRAfdSphrPaohh2HWmB": "main-trackList-rowCompactMode", "Btg2qHSuepFGBG6X0yEN": "main-trackList-rowDuration", + "bnolo3jJ8KBxI6jyN7bD": "main-trackList-rowFeedback", "U_mTGq4vzVyOrPrB3mx4": "main-trackList-rowFeedbackButton", "tGKwoPuvNBNK3TzCS5OH": "main-trackList-rowHeartButton", "rkw8BWQi3miXqtlJhKg0": "main-trackList-rowImage", @@ -261,6 +835,7 @@ "cxYjUh_DjUkRijOXGrOT": "main-trackList-rowImageVideo", "byLkljnIRd_DJeSMD3LM": "main-trackList-rowImageWithPlay", "iCQtmPqY0QvkumAOuCjr": "main-trackList-rowMainContent", + "gQnx5tArze5q1wfG6AWJ": "main-trackList-rowMainContentCompact", "VpYFchIiPg3tPhBGyynT": "main-trackList-rowMarker", "JxZLQbpnH3fFGJHB4XQG": "main-trackList-rowMarkerChartStatus", "mYN_ST1TsDdC6q1k1_xs": "main-trackList-rowMoreButton", @@ -273,968 +848,428 @@ "rq2VQ5mb9SDAFWbBIUIn": "main-trackList-rowSubTitle", "t_yrXoUO3qGsJS4Y6iXX": "main-trackList-rowTitle", "eRuZMo_HNLjb1IalIeRb": "main-trackList-selected", + "FCqh1RprhBCx2nZeC2Xi": "main-trackList-showDisabledAsEnabled", "ZdBognHQ3X610bLWE3e3": "main-trackList-sortable", "vY_4na7XFQWMFH8phXCQ": "main-trackList-statusChangeDown", "YAINlTb90ZejTPv7k1dH": "main-trackList-statusChangeNew", "zbBdn49lgTKVccLVZBqE": "main-trackList-statusChangeUp", "_3IwXr7oR_KZlfPfwMh7": "main-trackList-talkIcon", "y8YIxGr73OXUGacKKsWb": "main-trackList-talkSegmentDuration", + "jsV182e49Puwz9SIYt2J": "main-trackList-text", "ShMHCGsT93epRGdxJp2w": "main-trackList-trackList", + "ixZyJJ3SHxsSb3NHkhWn": "main-trackList-trackListCompactMode", "koyeY6AgGRPmyPITi7yO": "main-trackList-trackListHeader", "dZPmmYYhskhqHJCAruvI": "main-trackList-trackListHeaderRow", "qJOhHoRcFhHJpEQ2CwFT": "main-trackList-trackListHeaderStuck", "h4HgbO_Uu1JYg5UGANeQ": "main-trackList-trackListRow", "wTUruPetkKdWAR1dd6w4": "main-trackList-trackListRowGrid", - "wE9dp6W8uInhrlbWPMsR": "main-trackList-chartTrackList", + "vOp2HlcPkxOHebo3If32": "main-useDropTarget-album", + "O0AN8Ty_Cxd4iLwyKATB": "main-useDropTarget-album", + "VNdHKKznHkpJ0VHoDmai": "main-useDropTarget-artist", + "wQnUXn1m6Gy4PH8jhslb": "main-useDropTarget-artist", + "zWWLnqWslTLHwq3wBgGB": "main-useDropTarget-audiobook", + "ufICQKJq0XJE5iiIsZfj": "main-useDropTarget-base", + "NxEINIJHGytq4gF1r2N1": "main-useDropTarget-base", + "ETclQEbcAcQdGdSioHaJ": "main-useDropTarget-episode", + "XNjgtSbyhshr7YQcVvry": "main-useDropTarget-episode", + "cuH8l_VHkTiz_NYVslQe": "main-useDropTarget-folder", + "mhuhir0ikRqXAPHU8ZZ1": "main-useDropTarget-folder", + "aRyoyQFJkzhoSOnf2ERM": "main-useDropTarget-local", + "odS2IW9wfNVHhkhc0l_X": "main-useDropTarget-local", + "kXEKypZEUzxx9rNJy09C": "main-useDropTarget-playlist", + "D8wJ9TPfJzLeLJYxnad2": "main-useDropTarget-playlist", + "eZnAGhYcXE4Bt0a7958z": "main-useDropTarget-playlistV2", + "pTvxY5yAQklZgb7VZFGS": "main-useDropTarget-pseudoPlaylist", + "ratGUXdpLCkyXZNaJryg": "main-useDropTarget-show", + "oE8LAmRhbeQqsZrQo4lb": "main-useDropTarget-show", + "caTDfb6Oj7a5_8jBLUSo": "main-useDropTarget-track", + "or84FBarW2zQhXfB9VFb": "main-useDropTarget-track", "atsRVFhRDxRbOyXyFZjS": "main-userWidget-active", "odcjv30UQnjaTv4sylc0": "main-userWidget-box", + "KAq2kDjXj2VS4eXrFL4i": "main-userWidget-box", + "Fxnb0xe6bL7I7W8V0p6C": "main-userWidget-boxCondensed", + "SFgYidQmrqrFEVh65Zrg": "main-userWidget-boxCondensed", "eAXFT6yvz37fvS1lmt6k": "main-userWidget-chevron", "EeWTFG_vxLI5QJc1TH4F": "main-userWidget-displayName", "ERyo7m5f00o7ToFdGMCD": "main-userWidget-dropDownMenu", + "pEG0W4wkbkrOYURhz82H": "main-userWidget-hasAvatar", "PrOCaGCRoGw7XaycfkTl": "main-userWidget-notificationDot", "EIrPk5CxH5DyLgcOY_yx": "main-userWidget-notificationIndicator", "y5mR1se0HqD3uewF5Eb6": "main-userWidget-screenReaderOnly", + "YqPjzOfhtzbCf_QD3P1f": "main-userWidget-setupPlan", + "RfdRTSGwulyQdDepLUTT": "main-userWidget-showDisplayName", + "VdLuku6YQT4tNLT6ojlD": "main-userWidget-unableToUpdate", + "kzlksKUC9aLBM62Bckxo": "main-whatsNewFeed-actions", + "bcU463yG4LHEtlBCOa8Q": "main-whatsNewFeed-buttonAlwaysVisible", + "n5y3jDsz8siC0JsxtS83": "main-whatsNewFeed-buttonVisibleOnHover", + "h8Dik_naJfcSoNM_4FKX": "main-whatsNewFeed-content", + "lgo_zhUnwxG2Qan4WLBY": "main-whatsNewFeed-dateAndTime", + "CONFZNJkrMwpneVuYWXC": "main-whatsNewFeed-description", + "eyWbmr17oov600GluVsy": "main-whatsNewFeed-divider", + "Z1qkHjt67N3DaWqnEM0w": "main-whatsNewFeed-imageContainer", + "j45TgktnaHqgEqeO3eXI": "main-whatsNewFeed-largeImage", + "pNM_LHG1Yp9WV_mBN6du": "main-whatsNewFeed-list", + "nQTI7556vneVslJT_fJv": "main-whatsNewFeed-listContent", + "BQD_pE0Nva_z6z7CvZww": "main-whatsNewFeed-listEpisodeBody", + "ymzFgL9iToSvtRvCWY3b": "main-whatsNewFeed-listExplicitIcon", + "TTFwcgaxN1VxbkjC80_Z": "main-whatsNewFeed-listFallbackIcon", + "nHEYUQKiBurmQ7SD4uzF": "main-whatsNewFeed-listFooter", + "LLxSqFbzfI5SPTK_22ZU": "main-whatsNewFeed-listHeader", + "GBycF4NUOkA5ZUHneLYa": "main-whatsNewFeed-listImageWrapper", + "LXfpmhx6aZ9YVV8x4PEI": "main-whatsNewFeed-listPlayButton", + "MCctbQkmLVbJyz3NSbq2": "main-whatsNewFeed-listRow", + "_MBf1tVqzfo2AefcuHwv": "main-whatsNewFeed-listRow", + "ThG4UqWk7ASXCMm69Opn": "main-whatsNewFeed-listSubtitleLink", + "zKLP_l7gmiomI7kW3BMw": "main-whatsNewFeed-listTimeAgo", + "uuqowKOQLu0zbk4zguPM": "main-whatsNewFeed-medium", + "Z3LszrbA1M2fpLsEhlQT": "main-whatsNewFeed-progressBar", + "uSj66OUSURBfFwFhD7Ed": "main-whatsNewFeed-separator", + "sQnWbTOGnPZBNn3lZTtI": "main-whatsNewFeed-separatorAlbum", + "nzZgeVfx1Y6nZe7Z9DsA": "main-whatsNewFeed-showImage", + "oezNMICqWdJHdR3QV9La": "main-yourEpisodes-coverContainer", + "ioDnN5QkrvTdd8oOrl2h": "main-yourEpisodes-coverIcon", + "U_iGRN8gxm_rKG_w2EzR": "main-yourEpisodes-yourEpisodesCard", + "vCaNVEuqazhZFQNcVHZj": "main-yourEpisodesButton-yourEpisodesIcon", + "OMCDc2F7g_AufJAtaKfL": "main-yourLibraryX-button", + "cljOO1tpzixzXctKJucK": "main-yourLibraryX-button", + "prGqQr33U0mG14TJ5V8a": "main-yourLibraryX-collapseButton", + "FTiXRW7kAldHmLaxVQ2N": "main-yourLibraryX-collapseButton", + "BhKGkKPprp2wm9bvfRKG": "main-yourLibraryX-collapseButtonIsCollapsed", + "RAWO6AczuDMOTI0qAc0a": "main-yourLibraryX-collapseButtonWrapper", + "i_FRcsaqNCEJmoyObIP0": "main-yourLibraryX-collapseButtonWrapper", + "ksmcxhImUuj3_s1lcIm0": "main-yourLibraryX-createButton", + "EZFyDnuQnx5hw78phLqP": "main-yourLibraryX-entryPoints", + "lHJd4oSttKLxkxuoZ0Lr": "main-yourLibraryX-entryPoints", + "wBsWS202aGdsul2kEGUf": "main-yourLibraryX-filterArea", + "paiZmlAHHhmZonuGJRAr": "main-yourLibraryX-filterArea", + "MLbFLVC33caOj3FgSQMC": "main-yourLibraryX-filters", + "msaOP0MYt3paJGpbdeJs": "main-yourLibraryX-filters", + "UvXqRORKQr_N3jlgGTcS": "main-yourLibraryX-header", + "HjPqU_UW2egr14mRSom9": "main-yourLibraryX-header", + "j8iKBDzqTDtnDv4XbmrK": "main-yourLibraryX-headerContent", + "tAfozCQs48q1JYdphYXi": "main-yourLibraryX-headerContent", + "O2Vp_sNHMLHUcgMPVnOA": "main-yourLibraryX-headerIsCollapsed", + "TxO7Ee8iwqBpkgznKHsd": "main-yourLibraryX-iconOnly", + "TiJahFhH6KZaibhRtEOA": "main-yourLibraryX-isFlattened", + "y2UicQnlTq148rL8Y0jp": "main-yourLibraryX-isScrolled", + "hjb8tUL3rpUa0ez4ZtAj": "main-yourLibraryX-library", + "wM72343CksOCaL3bZvKK": "main-yourLibraryX-library", + "g581mszC8syz99uMMWsr": "main-yourLibraryX-libraryAfterDrop", + "tXkgloQ88DHF_inQE69J": "main-yourLibraryX-libraryBeforeDrop", + "PpUTJL2NIYDUnmfzVIbE": "main-yourLibraryX-libraryContainer", + "hgJel0bLlS_1Uf0EIfSA": "main-yourLibraryX-libraryContainer", + "_0FuodatXU4_fToYAuYtY": "main-yourLibraryX-libraryFilter", + "uBqliBvyhxGsiql8_OJv": "main-yourLibraryX-libraryFilter", + "dNphEfQzPRaQufS04jUm": "main-yourLibraryX-libraryIsCollapsed", + "kJ_Q4aphh_uCJCZdzPpD": "main-yourLibraryX-libraryIsExpanded", + "_XBlEstA77PgWTJzWbe1": "main-yourLibraryX-libraryItem", + "_K79lE9KrIAkl_bUSSUM": "main-yourLibraryX-libraryItemContainer", + "WxM1eb7qnneSkMiT4dvw": "main-yourLibraryX-libraryItemContainer", + "oLOECYtBhVmBtyisKwew": "main-yourLibraryX-libraryOnDrop", + "ifVI2CEdOZGgMWIUN2Cw": "main-yourLibraryX-libraryRootlist", + "_W_0W9Uld1vxrRfsgdQR": "main-yourLibraryX-libraryRootlist", + "RGofdOZulhL2p9MRA5hg": "main-yourLibraryX-librarySort", + "XZRX_ea9eNn4rOLpNGLp": "main-yourLibraryX-librarySortWrapper", + "GG5skerNjHXAO6tXyyY0": "main-yourLibraryX-librarySortWrapper", + "qEiVyQ28VnOKb0LeijqL": "main-yourLibraryX-listItem", + "ojrThQm1wxR2gZ6GntJB": "main-yourLibraryX-listItemGroup", + "Dtr130mQSR0j8k7bu5KS": "main-yourLibraryX-listItemGroupCompact", + "nZSNG58XEPTX69mkNi9n": "main-yourLibraryX-listRowEntityImage", + "G7aCptcOZswI1fN6dGkO": "main-yourLibraryX-listRowIcon", + "o_wMyH9_LbAmIwlVqsF0": "main-yourLibraryX-listRowIconWrapper", + "d33vqKRxohS9RxzCic1D": "main-yourLibraryX-listRowLink", + "LSrBzBljgLeDhcm3Soye": "main-yourLibraryX-listRowSubtitle", + "HdTF8gsRm5MgWvEYlokG": "main-yourLibraryX-listRowSubtitleLeadingWrapper", + "gj1L_SVM_H8GteWMdEF_": "main-yourLibraryX-listRowTitleLink", + "LU0q0itTx2613uiATSig": "main-yourLibraryX-navItem", + "AlqlOMBoMUPbFmLmkhhg": "main-yourLibraryX-navItemOffline", + "QuHe04rU4bj0Z5U9E2Tk": "main-yourLibraryX-navItems", + "UYeKN11KAw61rZoyjcgZ": "main-yourLibraryX-navLink", + "DzWw3g4E_66wu9ktqn36": "main-yourLibraryX-navLinkActive", + "ep0_ry7CLwf91E1rN6Cv": "main-yourLibraryX-pulse", + "B_HdWVSEWPHaOf9LQAtC": "main-yourLibraryX-rowCover", + "Gw7E7MkWci1ttQhb4EK0": "npv-exitFullScreenButton-button", + "gIobRDHAxkAvUaF4_OOL": "npv-nowPlayingBar-center", + "tr1hDrJgoPSbMXlXU_sl": "npv-nowPlayingBar-container", + "mbUrqWP55sK6zhspiR72": "npv-nowPlayingBar-controls", + "N5cWYDvyLrfnyMZuqQHo": "npv-nowPlayingBar-left", + "FTi9QEhetf4Q4__5sb4S": "npv-nowPlayingBar-right", + "SVGHXIQcH9HYU7uGITw5": "npv-nowPlayingBar-section", "p1ULRzPc4bD8eQ4T_wyp": "playback-progressbar", - "TywOcKZEqNynWecCiATc": "progress-bar", - "Vis45PPawTyED7Lt2_LI": "progress-bar__slider", - "DuvrswZugGajIFNXObAr": "progress-bar--isDragging", - "NoOAOv6U6vtqj_ybS1Cd": "x-progressBar-progressBarBg", - "es9mguuOfkp6pBe1Bjlw": "x-toggle-indicator", - "Js64TOfWtHksI6TQ6knT": "x-toggle-indicatorWrapper", - "n8tsDTs8wDH73kejYfXs": "x-toggle-input", - "JWYoNAyrIIdW30u4PSGE": "x-toggle-wrapper", - "OgkbKIVYE_mrNpYESylB": "main-nowPlayingBar-left", - "P4eSEARM2h24PZxMHz1T": "main-nowPlayingBar-center", - "jOKLc29vP0Bz1K0TsDtX": "main-nowPlayingBar-right", - "ZcNcu7WZgOAz_Mkcoff3": "main-trackInfo-container", - "Q_174taY6n64ZGC3GsKj": "main-trackInfo-name", - "gpNta6i8q3KYJC6WBZQC": "main-trackInfo-artists", - "vnCew8qzJq3cVGlYFXRI": "main-playPauseButton-button", - "fn72ari9aEmKo4JcwteT": "main-skipBackButton-button", - "mnipjT4SLDMgwiDCEnRC": "main-skipForwardButton-button", - "Vz6yjzttS0YlLcwrkoUR": "main-repeatButton-button", - "Nd_DeCpszONzyaLe5Wd1": "main-likedSongsButton-likedSongsIcon", - "ythYrlFSBm1P_ltHc8e1": "main-buddyFeed-buddyFeed", - "FBPrcmuqo3yv5UfWSRl5": "main-rootlist-rootlistDivider", - "McwcCfBLSuXa5UDU1IMw": "main-rootlist-rootlistDividerContainer", - "Y8edH1Yjo4xrW_58czQj": "main-rootlist-rootlistDividerGradient", - "IPVjkkhh06nan7aZK7Bx": "main-createPlaylistButton-button", - "Bwc9jlVb7HWs8JJupnBB": "main-createPlaylistButton-icon", - "J4xXuqyaJnnwS6s2p3ZB": "main-createPlaylistButton-text", - "LKgm9fCDTO7wqig_5U1q": "main-rootlist-rootlist", - "EY6S7vlkxB7SF_OjjF_Y": "main-rootlist-rootlistContent", - "rVxzkDirgkuRPv5V1HYF": "main-coverSlotCollapsed-container", - "GD2gbRtcs5dOjMGAM_Y4": "main-nowPlayingBar-container", - "OCY4jHBlCVZEyGvtSv0J": "main-nowPlayingBar-nowPlayingBar", - "bYHWD_eQ1jAh3sAKTHtr": "main-nowPlayingWidget-coverExpanded", - "deomraqfhIAoSB3SgXpu": "main-nowPlayingWidget-nowPlaying", - "KVKoQ3u4JpKTvSSFtd6J": "main-shuffleButton-button", - "xkHiFJhykpOWcVMMPufq": "main-rootlist-dropIndicator", - "whXv9jYuEgS1DPTmPCe_": "main-rootlist-rootlistItem", - "utSR0FVkHnII_aL8TOcu": "main-rootlist-rootlistItemLink", - "VjIb8SfYTkc4wMpqqj3f": "main-rootlist-textWrapper", - "g_jOSq3pLY5p4tldskrw": "main-rootlist-statusIcons", - "K8Rs3qAYirS8wJ1hR8gn": "main-rootlist-rootlistItemLinkActive", - "I_aApN9pSlbGcpLtFQWw": "main-rootlist-expandArrow", - "r9YzlaAPnM2LGK97GSfa": "main-collectionLinkButton-collectionLinkButton", - "npFSJSO1wsu3mEEGb5bh": "main-playbackBarRemainingTime-container", - "zDK1f3nL_R49a1mOvaO1": "main-collectionLinkButton-selected", - "ot6VAZq1Xfbw2Vh8Qt_A": "main-collectionLinkButton-collectionLinkText", - "AINMAUImkAYJd4ertQxy": "main-rootlist-rootlistItemOverlay", - "qnYVzttodnzg9WdrVQ1p": "main-rootlist-bottomSentinel", - "lyVkg68L7ycnwyOcO3vj": "main-rootlist-topSentinel", - "JUa6JJNj7R_Y3i4P8YUX": "main-rootlist-wrapper", - "CoLO4pdSl8LGWyVZA00t": "main-actionBarBackground-background", - "E4q8ogfdWtye7YgotBlN": "main-actionBar-ActionBar", - "eSg4ntPU2KQLfpLGXAww": "main-actionBar-ActionBarRow", - "tp8rO9vtqBGPLOhwcdYv": "main-avatar-avatar", - "tojGvx6tcIBmKlICMJAZ": "main-rootlist-rootlistPlaylistsScrollNode", - "oWQvtc5QZlmB60A9ejJx": "main-buddyFeed-friendsFeedContainer", - "BeABJha8PrxMcJmlBzcH": "main-buddyFeed-headerTitle", - "AWUxW13rbpNdQkvJJg13": "main-buddyFeed-scrollableArea", - "j7K7_Zly3G1HS9MlKoao": "main-buddyFeed-addFriendPlaceholder", - "gY0qK1gmEdhq5idwQc8C": "main-buddyFeed-addFriendPlaceholderBtn", - "gj9SOnCIzruGWAM5m3XO": "main-buddyFeed-friendActivity", - "dLg5WMgjh1kfYtZ_MnZz": "main-buddyFeed-avatarContainer", - "VBQoaks4ZkfIknTKmxXZ": "main-buddyFeed-overlay", - "_Xe25F2aC59Kljgqyw3G": "main-buddyFeed-activityMetadata", - "P7j2kCLc27vLybuzy5XB": "main-buddyFeed-usernameAndTimestamp", - "ktMuChpoidaEvECE7y8f": "main-buddyFeed-username", - "LywlKLgNaEtHZzLM3EX5": "main-buddyFeed-timestamp", - "mthrc5U9wb8F4zMBqlPy": "main-buddyFeed-artistAndTrackName", - "kE5DI3BkNlo9zuO7K3aO": "main-buddyFeed-playbackContext", - "hnEmEncF7kB2TnE_Uyja": "main-buddyFeed-playbackContextLink", - "dvb9y9hcP8sUfMhUASKO": "main-buddyFeed-playbackContextIcon", - "jtRqaoDIpIR6fEATUTyY": "main-coverSlotExpanded-container", - "g6ZgzRfiHjsTLskeyI0J": "main-coverSlotExpandedCollapseButton-collapseButton", - "qWcH8e2laY9sYOuCsOAx": "main-coverSlotCollapsed-expandButton", - "BFR9Zt3zpL8BATBMiwQB": "main-nowPlayingWidget-coverArt", - "Xz3tlahv16UpqKBW5HdK": "main-avatar-image", - "MF2rLXp4d_JPNs2t0bbj": "main-editImage-buttonContainer", - "CmkY1Ag0tJDfnFXbGgju": "main-entityHeader-image", - "MclJZ2TMkhjdlqqQfmQd": "main-entityHeader-imagePlaceholder", - "MfVrtIzQJ7iZXfRWg6eM": "main-shelf-title", - "PFgcCoJSWC3KjhZxHDYH": "main-playButton-PlayButton", + "DFtdzavKSbEhwKYkPTa6": "playback-progressbar-isInteractive", + "JzyZE2R09wq7xtjECDeR": "playlist-inlineSearchBox-clearButton", + "FeWwGSRANj36qpOBoxdx": "playlist-inlineSearchBox-filterInput", + "YAYCVnYpPvmYV4JyTmn5": "playlist-inlineSearchBox-filterInputContainer", + "_h5mio6VqcL_fmiXAb1S": "playlist-inlineSearchBox-overlay", + "sgZ_MgcS1NlccH19fYsa": "playlist-inlineSearchBox-searchIcon", + "Hfgj4Zbb2ijt8g54MlCA": "playlist-inlineSearchBox-searchIconContainer", + "rARdlCShKVQsvuXamFOX": "playlist-playlist-artistResultListTitle", + "a4FkPOXWBc0nK4yzsJCf": "playlist-playlist-concertsFooter", + "IWWS0F3oiajJG7nlrjXj": "playlist-playlist-ctaLink", + "mWbx87vgssexrOs2tx4I": "playlist-playlist-disclaimerContainer", + "_Z2TnFjt8GB5ryOtvyti": "playlist-playlist-emptySearchTermContainer", + "Bl_kg24BjWgcXPokgEKy": "playlist-playlist-emptyStateContainer", + "yP3JLuwUNDIQHxRFilK3": "playlist-playlist-header", + "QD13ZfPiO5otS0PU89wG": "playlist-playlist-heading", + "tzeKawjOOKFw1KfQ34mG": "playlist-playlist-icon", + "KzOZOlCPgREEBCJH1Ieg": "playlist-playlist-leadingSlot", + "ZbLneLRe2x_OBOYZMX3M": "playlist-playlist-list", + "rjdQaIDkSgcGmxkdI2vU": "playlist-playlist-listItem", + "u9KYiVXeDRQDGlTDH6rM": "playlist-playlist-noBooklistSupportContainer", + "umouqjSkMUbvF4I_Xz6r": "playlist-playlist-paragraph", "dZ3U5sTGUTdanNamXe1z": "playlist-playlist-playlist", "rezqw3Q4OEPB1m4rmwfw": "playlist-playlist-playlistContent", "xgmjVLxjqfcXK5BV_XyN": "playlist-playlist-playlistDescription", + "fUYMR7LuRXv0KJWFvRZA": "playlist-playlist-playlistDescription", "oq1ci28WPaRsWkvRiB_J": "playlist-playlist-playlistImageContainer", + "hVcUafGrnsA6nD1dJzc5": "playlist-playlist-playlistInlineCurationBackButton", + "FC40AOSbVM9LXjVi7bjO": "playlist-playlist-playlistInlineCurationCloseButton", + "Ykd_JWqkR9gSLHISDBwP": "playlist-playlist-playlistInlineCurationSection", + "SMJIXlalPk_TESlyt2pC": "playlist-playlist-playlistInlineCurationTitle", + "g9xHCCSXDR8S5NvTbfwL": "playlist-playlist-playlistInlineCurationWrapper", + "pbkk9BuHlY36lmWvEmbg": "playlist-playlist-promoImage", + "DWkbhLMcDefEZwJ5jXCq": "playlist-playlist-promoRow", + "byOUxNEoiJOtBN6xTY24": "playlist-playlist-promoTitle", + "kwe0I8sSNMv3gYBjkRYP": "playlist-playlist-recommendedTrackList", + "QmGi2oa43BTcEZ5MCr9T": "playlist-playlist-refreshButton", "KodyK77Gzjb8NqPGpcgw": "playlist-playlist-searchBoxContainer", - "Ws8Ec3GREpT5PAUesr9b": "profile-editImage-imageContainer", + "sAPXlA_oxu_8x1Cn0NTC": "playlist-playlist-searchResultListContainer", + "STDuzt77yRCueC4Ohenl": "playlist-playlist-seeMore", + "NCKSUYdZaTMrobq8ilkc": "playlist-playlist-subtitle", + "PZkwbwJD1afoCmJkGt8w": "playlist-playlist-top", + "jpVuvMOCbpaRr_6FLf3W": "playlist-playlist-whiteOpacity", "kHu_FTRgoBLSLeAJtyKY": "profile-editImage-editImageButtonContainer", - "rPV8BmHZXaGIGT2HwvBB": "view-homeShortcutsGrid-shortcuts", - "nlOU1unbFAd7ZHyeSMTH": "view-homeShortcutsGrid-grid", - "Z35BWOA10YGn5uc9YgAp": "view-homeShortcutsGrid-shortcut", + "Ws8Ec3GREpT5PAUesr9b": "profile-editImage-imageContainer", + "zHeo4VUxytwm6Ptr0QyA": "profile-userEditDetails-closeButton", + "XwNfIrI6_hCa_9_T2cQB": "profile-userEditDetails-container", + "so0bdX3oZH6YW5_nGxIR": "profile-userEditDetails-content", + "zGbjZMZ1DTx4futEbN9l": "profile-userEditDetails-disclaimer", + "aM3plU4zzDqjWlvUHGYb": "profile-userEditDetails-header", + "F8_EX1AeKxXNSeh1qiHq": "profile-userEditDetails-image", + "wvLAEV5wF5C5ej6rvimT": "profile-userEditDetails-label", + "gAQfzAUp1FuSXODeZJfP": "profile-userEditDetails-labelText", + "uj7hczcCH1dZpse8Kfmi": "profile-userEditDetails-name", + "oN9QVvJKEtdTH3HGfCu1": "profile-userEditDetails-nameInput", + "MDb7QhAtHeyM4gKj8j8t": "profile-userEditDetails-saveButton", + "umiKMm5NVr5UeBJCHS6U": "profile-userOverview-container", + "wDIZ2yYKjfGI68I4cZ98": "profile-userOverview-header", + "rMpf7sfaPDcj387_52fA": "profile-userOverview-imageContainer", + "jzhwZKbfx4vrC_MYd_7c": "profile-userOverview-section", + "MWWPQQjbjRfoGdPD8D68": "profile-userOverview-subPage", + "uJxNEI2k7x8UCDdMKELt": "profile-userOverview-title", + "kWCnF32FrVtGHmTy8QeV": "profile-userOverview-topTrackSubPage", + "TywOcKZEqNynWecCiATc": "progress-bar", + "Vis45PPawTyED7Lt2_LI": "progress-bar__slider", + "DuvrswZugGajIFNXObAr": "progress-bar--isDragging", + "gTvMl6pwfRD9PobMSB5x": "queue-queuePage-emptyContainer", + "hNAQG0TAe2WFYyf_iZEB": "queue-queuePage-emptyContainerTitle", + "Zhzrb2k9nQRActS2lp4U": "queue-queuePage-findSomething", + "DG9CsoFIptJhAneKoo_F": "queue-queuePage-header", + "H3Puuvc2nV0GoZRrfpRS": "queue-queuePage-nextFrom", + "HckHyQocDDePWQL2baOY": "queue-queuePage-nextInQueue", + "rHpv7osDRvs3SUPMpQ_g": "queue-queuePage-queuePage", + "jf2HafzDEI9jn7Yo05eM": "queue-queuePage-subHeader", + "oaNVBli46GtVjaQKB15g": "queue-tabBar-active", + "FvDsfgxSvLvL3q8d7nQv": "queue-tabBar-chevron", + "Nts_ArOCGeROTDZND3M6": "queue-tabBar-header", + "muYk5XIwKmqR9iNibk_f": "queue-tabBar-headerIsCentered", + "OEFWODerafYHGp09iLlA": "queue-tabBar-headerItem", + "JdlKTdpMquftpMwwegZo": "queue-tabBar-headerItemLink", + "m20ShRDiGGDpJ5LSABTi": "queue-tabBar-moreButton", + "Hvv0e7WKQ4kyftgSQJhg": "queue-tabBar-moreButtonActive", + "vhW0kRN8JJD5UwW4TdXi": "queue-tabBar-nav", + "nRSfonXHVr6utXYgk2Ui": "Root__globalNav", + "wp7mZFPzV7Qmo51F0NA_": "Root__globalNav", + "jEMA2gVoLgPQqAFrPhFw": "Root__main-view", + "mMjg1Gizg9kYk8ILoTdp": "Root__main-view-overlay", + "BdcvqBAid96FaHAmPYw_": "Root__nav-bar", + "JG5J9NWJkaUO9fiKECMA": "Root__now-playing-bar", + "OTfMDdomT5S7B5dbYTT8": "Root__right-sidebar", + "PHgyArRLVFknlaOm31ID": "Root__top-bar", + "ZQftYELq0aOsg6tPbVbV": "Root__top-container", + "H1bRFdpa3qfekTVTeDwC": "Root__top-container--has-notice-bar", + "WIPpgUp9J37Dwd0ZJnv0": "Root__top-container--right-sidebar-hidden", + "lPapCDz3v_LipgXwe8gi": "Root__top-container--right-sidebar-hidden", + "EBaPq6VUr6kjeHD9Wf2s": "Root__top-container--transition-enter", + "nxyZPOEjDd5ToiXtSgdA": "Root__top-container--transition-exit", + "v8nEufWSPrv1ql9ZdMko": "search-modal-emptySearchTermContainer", + "sFFh5DkVxeEcgBGFOvUE": "search-modal-emptyStateContainer", + "AnelgzgI75Dckf_LHUiK": "search-modal-entityImage", + "aIWRvSjvEN4rTMCIi4vG": "search-modal-hasResults", + "kn5N6aKpq6ebWinhrPPK": "search-modal-hidden", + "v2oO4ItuH_0zk3OFj5dh": "search-modal-input", + "kQ22nY00NOOrZjfmRP5J": "search-modal-inputContainer", + "sKrYQkHlFOyAc0bM142q": "search-modal-isSelected", + "EieXgtfUJKc4XQugVglV": "search-modal-key", + "DoibN62ZFcOCvZ0f6xK5": "search-modal-modalAfterOpen", + "_ZcO2wuO5d8P3TbjEukA": "search-modal-modalBase", + "s75RW4QQV6LZ_NCdFtag": "search-modal-modalBeforeClose", + "_p8ywioveAdTZ8yZmPfr": "search-modal-modalWrapper", + "kUkjSLUuPyag37OAbVPH": "search-modal-resultItem", + "zi377dMLSwXnFiejYnRa": "search-modal-searchBar", + "HN_3fmk5t15DGlzDbx1_": "search-modal-searchIcon", + "wIyyGaSPOHR78wksX3Us": "search-modal-searchModalInstructions", + "I9yJ0MC3kmodVJJlA6iq": "search-modal-searchResultRow", + "tz3aYeI1uG6kMzJOPWr6": "search-modal-searchResultTitle", + "TAHnl8KATdqiQLuz2TLv": "search-modal-searchResultType", + "xol36rXFgZ_biOcw6Czk": "search-recentSearches-narrowPage", + "khkfPsJuVBQyL_5cLT7y": "search-recentSearches-searchPageGrid", + "a7lvtXATo3HALtrsOHtO": "search-recentSearches-seeAll", + "rvvoAdb7aaUPYRasW7sK": "search-searchBrowse-browseAllContainer", + "UdXTcsz1eiiInKThkfYp": "search-searchBrowse-browseAllWrapper", + "M7LKuAFiIKaigK0fVguF": "search-searchBrowse-browseAllWrapper", + "CCi1L2OQvgdZvxkRHeKE": "search-searchBrowse-SearchBrowse", + "ijZQH9pePkbB2MbJHCJV": "search-searchCategory-carousel", + "XTk61Y8OkBdUT6Wj4F6i": "search-searchCategory-carouselButton", + "VfDGbMWaJe9rcefizTNk": "search-searchCategory-carouselButtonVisible", + "ZWI7JsjzJaR_G8Hy4W6J": "search-searchCategory-categoryGridItem", + "KjPUGV8uMbl_0bvk9ePv": "search-searchCategory-catergoryGrid", + "e179_Eg8r7Ub6yjjxctr": "search-searchCategory-container", + "bMurPtRDRv5LuN78MTVG": "search-searchCategory-contentArea", + "fVB_YDdnaDlztX7CcWTA": "search-searchCategory-SearchCategory", + "VIeVCUUETJyYPCDpsBif": "search-searchCategory-wrapper", + "nGARy02O1AklvHT7OBLA": "search-searchResult-searchResultGrid", + "iGyMsGo7FgYQQThBj2y9": "search-searchResult-topResult", + "eITFAR9yPwhjL_2gxB09": "search-searchResult-topResultCard", + "Lj3brgOJmjcq6MQ22XKq": "search-searchResult-tracklist", + "QVIrLvegL13F9cEdMqfT": "search-searchResult-tracklistContainer", + "rP1oFnzzvss0GV6VPgGG": "search-searchResult-tracklistHeader", + "PW9eULMYYH14XQgoJ0ui": "search-searchResult-tracklistHeaderText", + "XQakH0M0GDc6g6JKeyds": "search-searchResult-tracklistHeaderWrapper", + "rjgEnbv42_EUDbaiZnA2": "search-searchResult-tracklistLong", + "EbZrO5qZMclA_AaI3NV8": "search-searchResult-tracklistShort", + "DbMYFmOEEz9PH1h1zK9n": "show-episodeBlock-actions", + "LbePDApGej12_NyRphHu": "show-episodeBlock-description", + "upo8sAflD1byxWObSkgn": "show-episodeBlock-descriptionContainer", + "hTRqaN61SDG95erQGMmx": "show-episodeBlock-episodeBlock", + "V0pEigrddg3VxP_sTdAJ": "show-episodeBlock-header", + "ij5_Bi2LfqgWwHzQBXJS": "show-episodeBlock-imageContainer", + "y9kEPjDek0J80YRf8JJw": "show-episodeBlock-metadata", + "o_TP9z7A8LQvMXujJC7N": "show-episodeBlock-showImage", + "bG5fSAAS6rRL8xxU5iyG": "show-episodeBlock-title", + "HLixBI5DbVZNC6lrUbAB": "show-episodeBlock-titleContainer", + "g5gZaZVzR0tGT4pK6iEU": "show-episodeBlock-titleLink", + "jtfSxoRam9rzTtdXIjzc": "show-show-episodesFilter", + "ghfuv80I8uW_ymG_jfx9": "show-show-episodesFilter", + "kR0M2WSYVUj4cohADSFM": "show-show-episodesHeader", + "OodUnm1iCEZTUeL6X1gj": "show-show-moreButton", + "aQMtxnKeiJqZ9XCcDuZ7": "show-showPage-sectionWrapper", "g3f_cI5usQX7ZOQyDtA9": "view-homeShortcutsGrid-draggable", + "vpQWUBWS_lXRLZMRJT7w": "view-homeShortcutsGrid-episodeExtraContent", + "GSv7K805J9Jw7LB9tn2A": "view-homeShortcutsGrid-episodeProgressBar", + "jxXIarsEHgz2HoaVCVzA": "view-homeShortcutsGrid-equaliser", + "nlOU1unbFAd7ZHyeSMTH": "view-homeShortcutsGrid-grid", + "jdqzCrz9SoQp3ZUsU08w": "view-homeShortcutsGrid-gridOf4Columns", + "ima0EKmsnCNUG08T82EM": "view-homeShortcutsGrid-iconDownloaded", "WWDxafTPs4AgThdcX5jN": "view-homeShortcutsGrid-image", "jvWzgRWM_y_9FFTYRCcB": "view-homeShortcutsGrid-imageContainer", "zXwER4Lsqq_e7fVVaPkZ": "view-homeShortcutsGrid-imageWrapper", "Tzzq1pG_inwo_oSOdyjb": "view-homeShortcutsGrid-main", "JFDEiqT_8B5zeG_CDSdK": "view-homeShortcutsGrid-name", + "EzRmGRncgnv1zFgF4dqE": "view-homeShortcutsGrid-name", "TbrIq3NG2VYFoAUMSmp9": "view-homeShortcutsGrid-nameWrapper", - "jb9xD5ECTqKFK02qe3HZ": "view-homeShortcutsGrid-shortcutLink", + "vq0lsCoYrDUDvkuUIaRg": "view-homeShortcutsGrid-playButton", "Kcb74zm1aMqGfPxTwO5s": "view-homeShortcutsGrid-PlayButtonContainer", - "jxXIarsEHgz2HoaVCVzA": "view-homeShortcutsGrid-equaliser", + "s9c9x_mJq197U2hBzGtV": "view-homeShortcutsGrid-PlayButtonContainerVisible", + "DqAHiYCkcPCcDorezUKI": "view-homeShortcutsGrid-recentlyPlayedShortcutIcon", + "Z35BWOA10YGn5uc9YgAp": "view-homeShortcutsGrid-shortcut", + "jb9xD5ECTqKFK02qe3HZ": "view-homeShortcutsGrid-shortcutLink", + "bPmmKmSPLKMhtJSaUJRX": "view-homeShortcutsGrid-shortcutNewEpisodeIndicator", + "rPV8BmHZXaGIGT2HwvBB": "view-homeShortcutsGrid-shortcuts", + "sLw5dxB32cAxVxqiar7J": "view-homeShortcutsGrid-title", + "lt7UxuNqHQBCO6IWyA_G": "view-homeShortcutsGrid-trailingIndicator", + "eEZSnYlv7__34b2yulfm": "volume-bar", + "G4n5bTzWUvlftzDwrFVG": "volume-bar", + "FZhaXNtbN3Crwrgd0TA7": "volume-bar__icon-button", + "rT09bwCEwXECMbLbX_7A": "volume-bar__icon-button", + "x1jWng8HDweDS840aiIA": "volume-bar__slider-container", + "tIr7C6B0Pt6YKdOnqaqj": "volume-bar__slider-container", + "fLS8v3_EfBadEerbGVoR": "x-album-releasesDropdown", + "iqDYHLUedgX8y1eM1zep": "x-carousel-button", + "ge8K7iQqLE77g0FDGfDn": "x-carousel-carousel", + "Em2LrSSfvrgXQoajs6cm": "x-categoryCard-CategoryCard", + "jXeqeqkxEBVeFjA2YydA": "x-categoryCard-CategoryCard", + "tV9cjMpTPaykKsn2OVsw": "x-categoryCard-image", + "Op2n2H4o1iY0Xo2wAUH9": "x-categoryCard-image", + "i2yp6pOoZpYZLd5QWguN": "x-categoryCard-title", + "bQthUEx0_U98DJkT1saO": "x-categoryCard-title", + "jMg2yhvAA3YfgM1Ix5GL": "x-contributorButton-button", + "X1lXSiVj0pzhQCUo_72A": "x-contributorButton-ContributorButton", "HbKLiGoYM4dpuK8L4TMX": "x-downloadButton-button", - "wCl7pMTEE68v1xuZeZiB": "x-filterBox-expandButton", - "QZhV0hWVKlExlKr266jo": "x-filterBox-filterInput", - "JzZyf6OGCGtdscOZGt8Y": "x-filterBox-filterInputContainer", - "uAJxc_psYWeimY8N9bH9": "x-filterBox-overlay", - "CIVozJ8XNPJ60uMN23Yg": "x-filterBox-searchIcon", - "_bjbHn5TABOW2s5LsEGX": "x-filterBox-searchIconContainer", - "w6j_vX6SF5IxSXrrkYw5": "x-sortBox-sortDropdown", - "PDPsYDh4ntfQE3B4duUI": "main-contextMenu-menuItemLabel", - "gtuJjD43VjwtP8ii3H3P": "main-rootlist-statusIcons", - "LOsH9AUZc2uFRlhqtpRT": "x-settings-container", - "DQ9fp5DjBJxKHeHqtFwC": "x-settings-headerContainer", - "NnDXf1J9xlVM5AUuqVt1": "x-settings-header", - "c6TyNYOUJRIsjYZJZofy": "x-settings-section", - "weV_qxFz4gF5sPotO10y": "x-settings-row", - "GMGmbx5FRBd6DOVvzSgk": "x-settings-firstColumn", - "yNitN64xoLNhzJlkfzOh": "x-settings-secondColumn", - "xbm3VfL2kntDlxtyDKwj": "x-settings-crossFadeContainer", - "xK6HEWejcSHKyWfhNiJc": "x-settings-equalizerSection", - "SkbGMKYv49KtJNB5XxdX": "x-settings-input", - "uIJTvxFOg2izOY7aRRiU": "main-home-home", - "I3EivnXTjYMpSbPUiYEg": "main-home-content", - "HsbczDqu9qjcYr7EIdHR": "main-home-homeHeader", - "NTJM_mh36C5kJ5oO8eac": "main-rootlist-expandArrowActive", - "OF_3F0SQCsBtL1jSTlTA": "main-shuffleButton-active", - "tP0mccyU1WAa7I9PevC1": "main-repeatButton-active", - "BkpKedcdaMGbvgXMlmcg": "main-topBar-contentArea", - "tUg9tRrSVbtjHJ4WHnxw": "collection-collection-tabBar", - "fLqEiE5HwKr9eFCbJgeu": "collection-collection-header", - "VuUpAVlUW_OfMfOcDEID": "collection-searchBar-searchBar", - "ZzUvBwE6uj5CAU2pjlQX": "collection-collectionEntityHeroCard-container", - "NGSgqDuaOH2VDApkzoxN": "collection-collectionEntityHeroCard-likedSongs", - "DY2YrJ5MH3ddIhZGORBq": "collection-collectionEntityHeroCard-headerContainer", - "ZXOyJPokUIObMnvTOJvc": "collection-collectionEntityHeroCard-tracksContainer", - "xhPzQCyks9pfizJj_PVK": "collection-collectionEntityHeroCard-descriptionContainer", - "FvDsfgxSvLvL3q8d7nQv": "queue-tabBar-chevron", - "Nts_ArOCGeROTDZND3M6": "queue-tabBar-header", - "JdlKTdpMquftpMwwegZo": "queue-tabBar-headerItemLink", - "oaNVBli46GtVjaQKB15g": "queue-tabBar-active", - "vhW0kRN8JJD5UwW4TdXi": "queue-tabBar-nav", - "m20ShRDiGGDpJ5LSABTi": "queue-tabBar-moreButton", - "Hvv0e7WKQ4kyftgSQJhg": "queue-tabBar-moreButtonActive", - "Q2RPoHcoxygOoPLXLMww": "lyrics-lyrics-contentContainer", - "esRByMgBY3TiENAsbDHA": "lyrics-lyrics-contentWrapper", - "iq4cgi0YEKr6DGaTtzUj": "lyrics-lyricsContent-description", - "gvcgOXnAiNKEe_z92_lw": "x-settings-restartAppButton", - "eBrbJuUWgMoCkOgWs5uw": "main-topBar-topBarContainer", - "fWwn9sakqBBjgiNti7LD": "main-topBar-historyButtons", - "J6VTd7VdGN2PM_oXCAyH": "main-topBar-button", - "ou0osOf3R1ZRWQ1xzFd9": "main-topBar-icon", - "btOYheZlYlaVEyO9iEBk": "main-topBar-sectionWrapper", - "cqO5c3gPyN6tXIddpWfr": "main-topBar-left", - "fl1Ov5aB9YCKnMkJYpEu": "main-topBar-right", - "g3Xinb8x23n81ejvS9Uj": "main-topBar-searchBar", - "t2K4_iLmAyDtH7mcT5Wy": "x-searchInput-searchInputIconContainer", - "rqZoelG5u2vHb3kedEph": "main-topBar-UpgradeButton", - "o4KVKZmeHsoRZ2Ltl078": "main-entityHeader-titleInner", - "YbDIZ84mS7tzHr1tgWE9": "main-entityHeader-roundedCorners", - "kuSGKO1BuKZ3fgas7_T7": "main-entityHeader-creatorButton", - "Yc6ftz7mCqbsTN4ha_ke": "main-entityHeader-metaDataAuthor", - "n4hTP7ZeAOT_UQEkRUR7": "main-entityHeader-divider", - "bkFQH4uasL3pXqN9eDSi": "main-contextMenu-tippyWrapper", - "hWGxHSAKACFWXowXPDTP": "main-shelf-subHeader", - "Oq5wiHCwgjjMg_VYy068": "main-topBar-fullscreenHistoryButtons", - "sNde2kloCY28V4GB9AvP": "main-topBar-topNavBarLinks", - "k0vXhOdr0XE83lAQaJ1O": "main-topBar-topNavBarSeparator", - "LKFFk88SIRC9QKKUWR5u": "main-topBar-loginButtons", - "sibxBMlr_oxWTfBrEz2G": "main-topBar-signupButton", - "jsV182e49Puwz9SIYt2J": "main-trackList-text", - "vBFTtFW3Co9F_yJ_HjF4": "main-trackList-icon", - "FCqh1RprhBCx2nZeC2Xi": "main-trackList-showDisabledAsEnabled", - "dZiDwJihz32GwQunXhnB": "main-trackList-facepile", - "m6Bvw7PNXw2WXqruLOLE": "main-trackList-enhanced", - "uWYVhrrTnV2V_VYhThDl": "main-trackList-facepileAvatar", - "w304euOUWkI5A8qAqFj8": "main-trackList-notificationDot", - "oezNMICqWdJHdR3QV9La": "main-yourEpisodes-coverContainer", - "U_iGRN8gxm_rKG_w2EzR": "main-yourEpisodes-yourEpisodesCard", - "ioDnN5QkrvTdd8oOrl2h": "main-yourEpisodes-coverIcon", - "re2d5HDzt6T4XBgqcBhi": "main-contextMenu-menuHeading", - "f4XfIkH9v3tBTnI8AEDj": "main-playButton-lockIcon", - "rKdWluhLAGpdUFBWN8sK": "main-seeAll-link", - "yOKoknIYYzAE90pe7_SE": "main-image-loading", - "Yn2Ei5QZn19gria6LjZj": "main-image-loaded", - "GB_nwkJosBf_NLdZAgAx": "artist-artistDiscography-active", - "cFKW94askf6sbyOYlRqe": "artist-artistDiscography-artistName", - "Ihlsi5QU3AnIfSgnhorS": "artist-artistDiscography-button", - "h8z21OhjsxoY1IvpR1QP": "artist-artistDiscography-cardGrid", - "Rz6JI4bCxJVeSWe6LtEX": "artist-artistDiscography-firstAlbum", - "O61y0bIacmTFxhhbL1Bl": "artist-artistDiscography-headerButtons", - "fEvxx8vl3zTNWsuC8lpx": "artist-artistDiscography-headerContainer", - "n1EzbHQahSKztskTUAm3": "artist-artistDiscography-headerImage", - "hyHkMMynp3uUsmEtOkSN": "artist-artistDiscography-headerMetadata", - "kRb29P1Fo5blFMPRDSdq": "artist-artistDiscography-headerTitle", - "P7nfAtcLXgPiUCJrlUjA": "artist-artistDiscography-topBar", - "oxpxKtAxG4E2DCK0AJo9": "artist-artistDiscography-tracklist", - "QQasfrfLlxtbcdiJP40s": "artist-artistOffers-description", - "crweb403jWwGSZngXpHU": "artist-artistOffers-name", - "F6RR_jytWUwdg_jiv0Ss": "artist-artistOffers-icon", - "TXVCwyY2iLFPRMSav251": "artist-artistOffers-info", - "RmO04klyCgpCtMspkDMH": "artist-artistOffers-item", - "nMgXBztFcmHCjT0dRQDx": "artist-artistOffers-pic", - "gyHBzoYLUrTsDmijyGQ7": "artist-artistOnTour-date", - "J8F7vs26LDSof1E_qwmN": "artist-artistOnTour-dateDay", - "VbaPExA4ISCqk6SuSe2H": "artist-artistOnTour-dateMonth", - "j1MetdstqbpfRVFl1W01": "artist-artistOnTour-info", - "viRsT27AlJDd4bZyiH_k": "artist-artistOnTour-item", - "RpOhZK9h4ccL8wsEgdwQ": "artist-artistOnTour-title", - "n46Gs0Xh2zys0a2KwSRS": "artist-artistOnTour-time", - "IUF5ct6RQtva_f_DQqg0": "artist-artistOnTour-timeAndVenue", - "BL__GuO2JsHMR6RgNfwY": "artist-artistOverview-artistOverviewContent", - "Sl7tzXKh5stpn_y5prU5": "artist-artistOverview-artistOverviewContainer", - "q9GR66ZTM4HH42Z_qroQ": "artist-artistOverview-popularTracks", - "jJ1PYBjdJy5plPbVprT1": "artist-artistOverview-artistShelfSpacer", - "_7rRmILTMMuCiW77ERpvL": "artist-artistOverview-artistShelfRelatedVideos", - "uVh80THccLWIzZYwgUaQ": "artist-artistOverview-sideBlock", - "yTBLU_z7yk9Xp_oN48Q2": "artist-artistOverview-popularTracksBlock", - "kgR8s9v7IzY4G17ZtLbw": "artist-artistOverview-about", - "qsfp4wSDOv6LBCbFApI1": "artist-artistOverview-events", - "_7MwXzTGa7JMhVlJCeDJ9": "artist-artistOverview-merch", - "ODvt8oN68o6Iy8nxwOuY": "artist-artistOverview-merchSmall", - "NLaDALU71zxOtBUbsrfH": "artist-artistOverview-overview", - "hLkn_NwPkY5VIAETCqCK": "artist-artistOverview-heading", - "NOFtFAj4dIAsXQgVHJcA": "artist-artistOverview-merchShelfContent", - "b0NcxAbHvRbqgs2S8QDg": "artist-artistVerifiedBadge-badge", - "wi2HeHXOI471ZOh8ncCG": "artist-popularTrackList-seeMore", - "Hbwta1_s02edtdkgJ7qZ": "collection-collection-AddToPlaylistIcon", - "nHGnfkVXCk9YYVitV6eu": "collection-collection-emptyStateContainer", - "YV8aNrRwNwFaMozM_Bfo": "collection-collection-adBarEnabled", - "kwe0I8sSNMv3gYBjkRYP": "playlist-playlist-recommendedTrackList", - "fUYMR7LuRXv0KJWFvRZA": "playlist-playlist-playlistDescription", - "PZkwbwJD1afoCmJkGt8w": "playlist-playlist-top", - "yP3JLuwUNDIQHxRFilK3": "playlist-playlist-header", - "NCKSUYdZaTMrobq8ilkc": "playlist-playlist-subtitle", - "QmGi2oa43BTcEZ5MCr9T": "playlist-playlist-refreshButton", - "Ykd_JWqkR9gSLHISDBwP": "playlist-playlist-playlistInlineCurationSection", - "SMJIXlalPk_TESlyt2pC": "playlist-playlist-playlistInlineCurationTitle", - "g9xHCCSXDR8S5NvTbfwL": "playlist-playlist-playlistInlineCurationWrapper", - "FC40AOSbVM9LXjVi7bjO": "playlist-playlist-playlistInlineCurationCloseButton", - "hVcUafGrnsA6nD1dJzc5": "playlist-playlist-playlistInlineCurationBackButton", - "rARdlCShKVQsvuXamFOX": "playlist-playlist-artistResultListTitle", - "STDuzt77yRCueC4Ohenl": "playlist-playlist-seeMore", - "Bl_kg24BjWgcXPokgEKy": "playlist-playlist-emptyStateContainer", - "sAPXlA_oxu_8x1Cn0NTC": "playlist-playlist-searchResultListContainer", - "_Z2TnFjt8GB5ryOtvyti": "playlist-playlist-emptySearchTermContainer", - "tzeKawjOOKFw1KfQ34mG": "playlist-playlist-icon", - "s1jyNJBxq16eqkqCf6Ax": "main-trackInfo-enhanced", - "IcyWfMS5VkeOhaI7OWIx": "main-coverSlotCollapsed-navAltContainer", - "qvXMfQh1CjESoKKX49Bl": "main-topBar-buttonActive", - "OOsg_GCQDERDXc1d0EmC": "main-topBar-entryPoints", - "tV9cjMpTPaykKsn2OVsw": "x-categoryCard-image", - "i2yp6pOoZpYZLd5QWguN": "x-categoryCard-title", - "jMg2yhvAA3YfgM1Ix5GL": "x-contributorButton-button", - "X1lXSiVj0pzhQCUo_72A": "x-contributorButton-ContributorButton", + "VmwiDoU6RpqyzK_n7XRO": "x-downloadButton-cancelDownload", + "l_MW0G9qeeCKlVJwBykT": "x-downloadButton-cancelDownloadButton", "BKsbV2Xl786X9a09XROH": "x-downloadButton-DownloadButton", - "w699O0LgQRghXyl3bs9u": "x-progressBar-sliderArea", + "rEx3EYgBzS8SoY7dmC6x": "x-downloadButton-progress", + "_APVWqivXc4YqgsnpFkP": "x-downloadButton-removeDownload", + "OadpZJiOaGfX6Qp4j6n5": "x-entityImage-circle", + "AeEoI6ueagbJtaHl2cRd": "x-entityImage-defaultSize", + "iJp40IxKg6emF6KYJ414": "x-entityImage-image", + "vreceNX3ABcxyddeS83B": "x-entityImage-imageContainer", + "Ozitxbqs1vcOukDz3GDw": "x-entityImage-imagePlaceholder", + "SBpny8HrUTBzSjk7Vtk1": "x-entityImage-large", + "H71KtIrytVayf_dFofu7": "x-entityImage-medium", + "O5_0cReFdHe81E0xFAD1": "x-entityImage-small", + "CxurIfvXVb_TqGF4q8Yf": "x-entityImage-square", + "g3kBhX1E4EYEC2NFhhxG": "x-entityImage-xsmall", + "EsqEJ_NPrHsPkTbX4FW8": "x-filterBox-clearButton", + "wCl7pMTEE68v1xuZeZiB": "x-filterBox-expandButton", + "t6HIrX67Lp80Nj6tGauz": "x-filterBox-expandedOrHasFilter", + "KAydWoHSkQRqhQ1vkVwK": "x-filterBox-expandRight", + "QZhV0hWVKlExlKr266jo": "x-filterBox-filterInput", + "JzZyf6OGCGtdscOZGt8Y": "x-filterBox-filterInputContainer", + "iiNt4l0UwY2wL42vyBc2": "x-filterBox-fullWidth", + "uAJxc_psYWeimY8N9bH9": "x-filterBox-overlay", + "CIVozJ8XNPJ60uMN23Yg": "x-filterBox-searchIcon", + "_bjbHn5TABOW2s5LsEGX": "x-filterBox-searchIconContainer", "epWhU7hHGktzlO_dop6z": "x-progressBar-fillColor", - "ADri2r8kq8LVqSsNNvIr": "x-searchHistoryEntries-searchHistoryEntry", + "NoOAOv6U6vtqj_ybS1Cd": "x-progressBar-progressBarBg", + "w699O0LgQRghXyl3bs9u": "x-progressBar-sliderArea", + "AavUTirpKSAHapguSAy0": "x-proxySettings-fullWidth", + "qfjicQPaTTPrLWJWRxMQ": "x-proxySettings-horizontalPair", + "acVhMt5pELcXQyLaaPuV": "x-proxySettings-ProxySettings", "fOEOTcOAgPryvbYRYfOo": "x-searchHistoryEntries-clearSingleSearchHistory", "xmJl0s8mcJ3bfhtnoaP1": "x-searchHistoryEntries-clearSingleSearchHistoryButton", - "RArlOXg8S6l3NgRKrGsO": "main-cardSubHeader-text", - "FegbnTtU6poHbemMzmBP": "main-coverSlotExpanded-enter", - "i1SMAJ9KRyK_muq63Pmg": "main-coverSlotExpanded-enterActive", - "Q4cc5RktWgz2H8_vDrIS": "main-coverSlotExpanded-exitActive", - "CCi1L2OQvgdZvxkRHeKE": "search-searchBrowse-SearchBrowse", - "rvvoAdb7aaUPYRasW7sK": "search-searchBrowse-browseAllContainer", - "UdXTcsz1eiiInKThkfYp": "search-searchBrowse-browseAllWrapper", - "M7LKuAFiIKaigK0fVguF": "search-searchBrowse-browseAllWrapper", - "khkfPsJuVBQyL_5cLT7y": "search-recentSearches-searchPageGrid", - "fVB_YDdnaDlztX7CcWTA": "search-searchCategory-SearchCategory", - "e179_Eg8r7Ub6yjjxctr": "search-searchCategory-container", - "VIeVCUUETJyYPCDpsBif": "search-searchCategory-wrapper", - "bMurPtRDRv5LuN78MTVG": "search-searchCategory-contentArea", - "KjPUGV8uMbl_0bvk9ePv": "search-searchCategory-catergoryGrid", - "ZWI7JsjzJaR_G8Hy4W6J": "search-searchCategory-categoryGridItem", - "ijZQH9pePkbB2MbJHCJV": "search-searchCategory-carousel", - "XTk61Y8OkBdUT6Wj4F6i": "search-searchCategory-carouselButton", - "VfDGbMWaJe9rcefizTNk": "search-searchCategory-carouselButtonVisible", - "Lj3brgOJmjcq6MQ22XKq": "search-searchResult-tracklist", - "QVIrLvegL13F9cEdMqfT": "search-searchResult-tracklistContainer", - "EbZrO5qZMclA_AaI3NV8": "search-searchResult-tracklistShort", - "rjgEnbv42_EUDbaiZnA2": "search-searchResult-tracklistLong", - "rP1oFnzzvss0GV6VPgGG": "search-searchResult-tracklistHeader", - "XQakH0M0GDc6g6JKeyds": "search-searchResult-tracklistHeaderWrapper", - "PW9eULMYYH14XQgoJ0ui": "search-searchResult-tracklistHeaderText", - "nGARy02O1AklvHT7OBLA": "search-searchResult-searchResultGrid", - "iGyMsGo7FgYQQThBj2y9": "search-searchResult-topResult", - "eITFAR9yPwhjL_2gxB09": "search-searchResult-topResultCard", - "DFtdzavKSbEhwKYkPTa6": "playback-progressbar-isInteractive", - "gQoa8JTSpjSmYyABcag2": "main-connectBar-connectBar", - "KAZD28usA1vPz5GVpm63": "main-genericButton-button", - "RK45o6dbvO1mb0wQtSwq": "main-genericButton-buttonActive", - "EHxL6K_6WWDlTCZP6x5w": "main-genericButton-buttonActiveDot", - "PrhIVExjBkmjHt6Ea4XE": "main-devicePicker-button", - "n8Bz0c0v17whD3KfMdOk": "album-albumPage-sectionWrapper", - "aQMtxnKeiJqZ9XCcDuZ7": "show-showPage-sectionWrapper", - "YJMECPbMHWgMUs8RFdcV": "folder-folderPage-sectionWrapper", - "tr8V5eHsUaIkOYVw7eSG": "lyrics-lyrics-container", - "L9xhJOJnV2OL5Chm3Jew": "lyrics-lyrics-background", - "NiCdLCpp3o2z6nBrayOn": "lyrics-lyricsContent-lyric", - "MEjuIn9iTBQbnCqHpkoQ": "lyrics-lyricsContent-highlight", - "kGR_hu4tdj9PnUlSPaRL": "lyrics-lyricsContent-provider", - "arY01KDGhWNgzlAHlhpd": "lyrics-lyricsContent-active", - "HxblHEsl2WX2yhubfVIc": "lyrics-lyricsContent-unsynced", - "YAYCVnYpPvmYV4JyTmn5": "playlist-inlineSearchBox-filterInputContainer", - "FeWwGSRANj36qpOBoxdx": "playlist-inlineSearchBox-filterInput", - "_h5mio6VqcL_fmiXAb1S": "playlist-inlineSearchBox-overlay", - "Hfgj4Zbb2ijt8g54MlCA": "playlist-inlineSearchBox-searchIconContainer", - "sgZ_MgcS1NlccH19fYsa": "playlist-inlineSearchBox-searchIcon", - "JzyZE2R09wq7xtjECDeR": "playlist-inlineSearchBox-clearButton", - "PiFWoUIRceOm8SHTCakS": "x-settings-equalizerResetButtonWrapper", + "ADri2r8kq8LVqSsNNvIr": "x-searchHistoryEntries-searchHistoryEntry", + "ZtY42R4YSo_W7VMeAg9m": "x-searchInput-searchInputClearButton", + "mOLTJ2mxkzHJj6Y9_na_": "x-searchInput-searchInputClearIcon", + "t2K4_iLmAyDtH7mcT5Wy": "x-searchInput-searchInputIconContainer", + "QO9loc33XC50mMRUCIvf": "x-searchInput-searchInputInput", + "XD3TMuMHmKsfbqieC6q_": "x-searchInput-searchInputOnSearch", + "H6jh9Xd7DNOq3NsLDmCB": "x-searchInput-searchInputSearchIcon", + "rFFJg1UIumqUUFDgo6n7": "x-settings-button", + "LOsH9AUZc2uFRlhqtpRT": "x-settings-container", + "xbm3VfL2kntDlxtyDKwj": "x-settings-crossFadeContainer", "gv7Rcc2ouDRSd0pto7Df": "x-settings-equalizerPanelCanvas", - "bn2UNQDs5GLY5rjp5Ljh": "artist-artistVerifiedBadge-fillColor", - "idI9vydtCzXVhU1BaKLw": "artist-followButton-button", - "fEbcweEiUPPy2eaIaD3F": "artist-followButton-followed", - "Qq16641w1flRfBavPaAn": "artist-followButton-disabled", - "fLS8v3_EfBadEerbGVoR": "x-album-releasesDropdown", - "v2oO4ItuH_0zk3OFj5dh": "search-modal-input", - "kQ22nY00NOOrZjfmRP5J": "search-modal-inputContainer", - "HN_3fmk5t15DGlzDbx1_": "search-modal-searchIcon", - "kUkjSLUuPyag37OAbVPH": "search-modal-resultItem", - "sKrYQkHlFOyAc0bM142q": "search-modal-isSelected", - "_p8ywioveAdTZ8yZmPfr": "search-modal-modalWrapper", - "_ZcO2wuO5d8P3TbjEukA": "search-modal-modalBase", - "DoibN62ZFcOCvZ0f6xK5": "search-modal-modalAfterOpen", - "s75RW4QQV6LZ_NCdFtag": "search-modal-modalBeforeClose", - "EhyK_jJzB2PcWXd5lg24": "main-keyboardShortcutsHelpModal-container", - "NyIynkmMpZXSoaE3XGhA": "main-navBar-banner", - "WJsKJXEbycxxq8OcGHM1": "main-navBar-logo", - "WvLkmOVB2R2vzI2ibR_r": "main-navBar-downloadItem", - "uhxXhw9alI7KR1YTc904": "main-navBar-premiumNavItem", - "b2KVTiBUcXV1kT0OjL2p": "main-navBar-navBarItemDropTarget", - "GKnnhbExo0U9l7Jz2rdc": "main-navBar-premiumLink", - "TPcD_1UTh6DS32DfZxhA": "artist-artistAbout-artistOverviewContent", - "RHlPX8sl9gW1cmKdm1E9": "artist-artistAbout-artistOverviewContainer", - "fPw1FkQQDEJvxJwTalo5": "artist-artistAbout-popularTracks", - "Ev5jVfYlqmjaZh6ziail": "artist-artistAbout-artistShelfSpacer", - "y72RJ2LhCkAyAfZ8tzUt": "artist-artistAbout-sideBlock", - "Apg1EshcUJs6y4ITDWwV": "artist-artistAbout-popularTracksBlock", - "HPNSn7d7aZf4nfre61sk": "artist-artistAbout-about", - "H3lKAypjVfPoxoQkkCJQ": "artist-artistAbout-events", - "e2S7FcJ1QgVLlcUbl2Kn": "artist-artistAbout-merch", - "iZ_BsoftrZBB78FRQ3Yq": "artist-artistAbout-merchSmall", - "yzXX2lW3wGayC_cdup_m": "artist-artistAbout-overview", - "XbP5GUst__JF8uVtbozd": "artist-artistAbout-heading", - "Er5rIejLMh22M0OiF8wH": "artist-artistAbout-merchShelfContent", - "uhDzVbFHyCQDH6WrWZaC": "artist-artistAbout-container", - "ejNsts52hRq0uZcc_NXi": "artist-artistAbout-content", - "k4MNlyGrhsL0qgnENxqh": "artist-artistAbout-backgroundImage", - "CjnwbSTpODW56Gerg7X6": "artist-artistAbout-bio", - "xaeunxBdlShScWay5mQR": "artist-artistAbout-artistGridContainer", - "oMsgQk2LPTIE4yinSHOQ": "artist-artistAbout-image", - "ml8qANY77Ah3fx5VTjoe": "artist-artistAbout-columnContainer", - "Fzu8dfizHyYedxyDjaQ2": "artist-artistAbout-bioContainer", - "ndIZG_atdpv_tBZtqQhk": "artist-artistAbout-statsContainer", - "upZIQtiBy1Tr0ZbvhnSL": "artist-artistAbout-stats", - "hdS8jsvbJhsJXHAZlWwz": "artist-artistAbout-postedBy", - "mM_me6VjRfHLPkqAMqEI": "artist-artistAbout-postedByAvatar", - "PAlX44btlstKkPJfe2uU": "artist-artistAbout-avatar", - "pSn5vOGhTHswAWTC_3tE": "artist-artistAbout-modal", - "pHrwZOFBdT8FNXnmcPPI": "artist-artistAbout-scrollbars", - "MHIOvvlSYRmF7VAJDLWy": "artist-artistAbout-close", - "hIhnD0UMvYHG6TnluwnX": "artist-artistAbout-modalBase", - "KUUFCMOavSKiLbBMXu0f": "artist-artistAbout-modalAfterOpen", - "Xr7SnQlqJFl6FSMeiSsw": "artist-artistAbout-modalBeforeClose", - "tQp8UOu8jGduQXUTcv0c": "artist-artistAbout-rank", - "Q_OUHp7iDNLBcO2ZYI2x": "artist-artistAbout-cityBlock", - "N5_bW94EwvHFbWWoRucu": "artist-artistOnTour-condensed", - "P5l28MUwDXvStz4OF0IE": "artist-artistOnTour-elevated", - "dvPKZDevT0Llia4bmaJX": "artist-artistOnTour-timeAndVenueText", - "Oq3xjFrLaBAabx847xea": "artist-artistOnTour-onTourShelfGrid", - "ERcmpF077M1XT1X0fIxB": "artist-artistOnTour-metadata", - "h3FvLvcLCaK12strxe2F": "artist-artistOnTour-location", - "AzO2ondhaHJntbGy_3_S": "main-buddyFeed-container", - "v_YrAYQP6fHG_z0hyg7C": "main-buddyFeed-scrollBarContainer", - "NdQkQZhcYIEcJnRdAYcQ": "main-buddyFeed-header", - "zuwPpHAEtIqahnB2u9NR": "main-buddyFeed-content", - "Lcc_yFPFIr7HSbt6aQbQ": "main-buddyFeed-title", - "t345U9kQY1pF704d79oY": "main-buddyFeed-closeButton", - "YEaaNScT6lyJCVBeQoxd": "main-buddyFeed-actions", - "xol36rXFgZ_biOcw6Czk": "search-recentSearches-narrowPage", - "gTvMl6pwfRD9PobMSB5x": "queue-queuePage-emptyContainer", - "hNAQG0TAe2WFYyf_iZEB": "queue-queuePage-emptyContainerTitle", - "Zhzrb2k9nQRActS2lp4U": "queue-queuePage-findSomething", - "zuf9gCpkf86KkzzCtkJN": "main-topBar-navLink", - "UYeKN11KAw61rZoyjcgZ": "main-yourLibraryX-navLink", - "DzWw3g4E_66wu9ktqn36": "main-yourLibraryX-navLinkActive", - "LU0q0itTx2613uiATSig": "main-yourLibraryX-navItem", - "EZFyDnuQnx5hw78phLqP": "main-yourLibraryX-entryPoints", - "QuHe04rU4bj0Z5U9E2Tk": "main-yourLibraryX-navItems", - "hjb8tUL3rpUa0ez4ZtAj": "main-yourLibraryX-library", - "PpUTJL2NIYDUnmfzVIbE": "main-yourLibraryX-libraryContainer", - "oLOECYtBhVmBtyisKwew": "main-yourLibraryX-libraryOnDrop", - "tXkgloQ88DHF_inQE69J": "main-yourLibraryX-libraryBeforeDrop", - "g581mszC8syz99uMMWsr": "main-yourLibraryX-libraryAfterDrop", - "dNphEfQzPRaQufS04jUm": "main-yourLibraryX-libraryIsCollapsed", - "kJ_Q4aphh_uCJCZdzPpD": "main-yourLibraryX-libraryIsExpanded", - "_K79lE9KrIAkl_bUSSUM": "main-yourLibraryX-libraryItemContainer", - "ifVI2CEdOZGgMWIUN2Cw": "main-yourLibraryX-libraryRootlist", - "_XBlEstA77PgWTJzWbe1": "main-yourLibraryX-libraryItem", - "y2UicQnlTq148rL8Y0jp": "main-yourLibraryX-isScrolled", - "wBsWS202aGdsul2kEGUf": "main-yourLibraryX-filterArea", - "MLbFLVC33caOj3FgSQMC": "main-yourLibraryX-filters", - "UvXqRORKQr_N3jlgGTcS": "main-yourLibraryX-header", - "O2Vp_sNHMLHUcgMPVnOA": "main-yourLibraryX-headerIsCollapsed", - "j8iKBDzqTDtnDv4XbmrK": "main-yourLibraryX-headerContent", - "OMCDc2F7g_AufJAtaKfL": "main-yourLibraryX-button", - "prGqQr33U0mG14TJ5V8a": "main-yourLibraryX-collapseButton", - "RAWO6AczuDMOTI0qAc0a": "main-yourLibraryX-collapseButtonWrapper", - "BhKGkKPprp2wm9bvfRKG": "main-yourLibraryX-collapseButtonIsCollapsed", - "ksmcxhImUuj3_s1lcIm0": "main-yourLibraryX-createButton", - "TxO7Ee8iwqBpkgznKHsd": "main-yourLibraryX-iconOnly", - "ufICQKJq0XJE5iiIsZfj": "main-useDropTarget-base", - "vOp2HlcPkxOHebo3If32": "main-useDropTarget-album", - "VNdHKKznHkpJ0VHoDmai": "main-useDropTarget-artist", - "ETclQEbcAcQdGdSioHaJ": "main-useDropTarget-episode", - "cuH8l_VHkTiz_NYVslQe": "main-useDropTarget-folder", - "kXEKypZEUzxx9rNJy09C": "main-useDropTarget-playlist", - "eZnAGhYcXE4Bt0a7958z": "main-useDropTarget-playlistV2", - "ratGUXdpLCkyXZNaJryg": "main-useDropTarget-show", - "caTDfb6Oj7a5_8jBLUSo": "main-useDropTarget-track", - "aRyoyQFJkzhoSOnf2ERM": "main-useDropTarget-local", - "NxEINIJHGytq4gF1r2N1": "main-useDropTarget-base", - "O0AN8Ty_Cxd4iLwyKATB": "main-useDropTarget-album", - "wQnUXn1m6Gy4PH8jhslb": "main-useDropTarget-artist", - "XNjgtSbyhshr7YQcVvry": "main-useDropTarget-episode", - "mhuhir0ikRqXAPHU8ZZ1": "main-useDropTarget-folder", - "D8wJ9TPfJzLeLJYxnad2": "main-useDropTarget-playlist", - "oE8LAmRhbeQqsZrQo4lb": "main-useDropTarget-show", - "or84FBarW2zQhXfB9VFb": "main-useDropTarget-track", - "odS2IW9wfNVHhkhc0l_X": "main-useDropTarget-local", - "zWWLnqWslTLHwq3wBgGB": "main-useDropTarget-audiobook", - "pTvxY5yAQklZgb7VZFGS": "main-useDropTarget-pseudoPlaylist", - "X8yW2lJbFCQfV5GjoRwL": "main-contextMenu-tippy", - "nYdM55iHFByRTzJUmx9X": "main-contextMenu-tippy", - "mph1R_QkS44EPi4lrhxd": "main-contextMenu-tippyEnter", - "sNOxi993vqYCWYgo_N3H": "main-contextMenu-tippyEnter", - "v5IUMJNPJgol0273zQXD": "main-contextMenu-tippyEnterActive", - "z_29i58eLFLK50jAs_4a": "main-contextMenu-tippyEnterActive", - "RbsCNNM9a0WkFCM2UzBA": "main-addButton-button", - "SPC4uzYXJmknkCGKpxHw": "main-addButton-active", - "nzUMgk_XBD4uFFgA_LOI": "main-addButton-disabled", - "GolAZOzxNIKbfZdIApC_": "main-addButton-helmet", - "LuK6ZGXdwxSW92X3FodG": "main-addButton-zoomInAnimation", - "BzunmwrVMyWGpopPJRt2": "main-avatar-withBadge", - "yzLEMgdzXgAnIZZwMHO1": "main-avatar-piled", - "ENopS3htmKy15q_QCR2j": "main-avatar-piledIcon", - "KdxlBanhDJjzmHfqhP0X": "main-avatar-placeholderWrapper", - "m95Ymx847hCaxHjmyXKX": "main-avatar-placeholderTransparent", - "ylTErJiI2Ir_LqmrsaXV": "main-buddyFeed-panelTransition", - "eZCD3dqbvZaABVAhIniT": "main-buddyFeed-closeContainer", - "cwcgvNz4amFDKqakIqxc": "main-buddyFeed-titleContainer", - "tli6RLZf7DdPtClCKK6_": "main-buddyFeed-link", - "n6rSk6R7nfmSGSgTRR5_": "main-buddyFeed-loadingFriends", - "nGInMrf62TCFD9MBnEzz": "main-buddyFeed-friendsList", - "QO_OHdGt6X6luPH6_Lfg": "main-cardHeader-hasNewEpisodeIndicator", - "qucSNjx66ofSGZDzCuEk": "main-cardSubHeader-isHero", - "RVgHI2ejYct8LjT1AO7m": "main-confirmDialog-container", - "m0yIuS1Q6XRA5R4PNEhl": "main-confirmDialog-overlay", - "X05XDhpQJ7THPHfgbUk1": "main-confirmDialog-buttonContainer", - "eG930DCaQXDFqjhxRGIs": "main-contextMenu-filterPlaylistSearch", - "i8EjndRQjYlli0aLGYEm": "main-contextMenu-filterPlaylistSearchContainer", - "OVv1uDz67TLurN8o6LtQ": "main-contextMenu-addToPlaylistTitle", - "Cm3jbLBimhqdYEcNTVPj": "main-contextMenu-addToPlaylistSubtitle", - "M0E2Al6URHV3iyoDbvi_": "main-contextMenu-highlightedText", - "Fih6l1HD6F3NRrdCEMFE": "main-coverSlotExpanded-expanding", - "LROBF2WtGaVryVpVbSOu": "main-coverSlotExpanded-containerExpanding", - "jmu6DFPvhxRl0wSfmv2O": "main-dropDown-isSafari", - "Foyk_HJx16yh22JYmQ56": "main-downloadClient-container", - "Fyc_tPyPKyRIT_59VZ2B": "main-downloadClient-actionContainer", - "AdF5F5BxQXGeWkfceg9A": "main-duplicateTrackModal-container", - "YDfNb_CMrwg2Z6FeLyNu": "main-duplicateTrackModal-title", - "XBJ5gUPLDUdlCFkWV7PZ": "main-duplicateTrackModal-description", - "T596E9OFZtarwLZV_Opk": "main-duplicateTrackModal-buttonContainer", - "CdHBSRh3RhPwBNIBQtkD": "main-editImageButton-rounded", - "NkDkQMd75JY5xes9xFVe": "main-heroCard-isDownloadable", - "liYe8rZ0FEQBy8j8XGJH": "main-heroCard-isPlaying", - "BuzoTjBZd1UqCn6DmFJr": "main-loadingIndicator-circle", - "HKamyJi9H31s99erfVyG": "main-loadingIndicator-loadingIcon", - "AptbKyUcObu7QQ1sxqgb": "main-lyricsCinema-lyricsCinemaVisible", - "YtsqA6txqmCqkKq0G2Ta": "main-lyricsCinema-nonDisplayedArea", - "y7xcnM6yyOOrMwI77d5t": "main-lyricsCinema-container", - "xnPS9Fa6efctzBjM05O4": "main-lyricsCinema-controls", - "TITRkcJffQbL60GWevgh": "main-lyricsCinema-content", - "w3PliL6VjTaj2VfscF_k": "main-notificationBubble-closeIcon", - "mwpJrmCgLlVkJVtWjlI1": "main-nowPlayingBar-extraControls", - "uVRRxsH6RKj3Dzhl40Ok": "main-nowPlayingBar-topButton", - "Xmv2oAnTB85QE4sqbK00": "main-nowPlayingBar-lyricsButton", - "wh7q2LxxjhyXLJvxRQGG": "main-nowPlayingBar-buddyFeedIcon", - "ExuDUBJ7bk8vT6INnm9F": "main-nowPlayingBar-volumeBar", - "QIuMX9iPlMiflBPUkrEQ": "main-nowPlayingView-container", - "MPBLLykSgRJIlLSbQVgy": "main-nowPlayingView-gradient", - "jtqtOeRP46XAlHWx4C0D": "main-nowPlayingView-content", - "SfAYznqZyNk_AvvxIkUx": "main-nowPlayingView-header", - "wkl1CJw1cTKpqlKDAiln": "main-nowPlayingView-panelOpenDiv", - "fIpDXK7M3W0Bn3FgLSRe": "main-nowPlayingView-nowPlayingWidget", - "j9I5h3Z4o0fKNgI1fIjb": "main-nowPlayingView-coverArt", - "aaFQbW0j0N40v_siz0kX": "main-nowPlayingView-contextItemInfo", - "hfdkySA4kiUldFsPj9lD": "main-nowPlayingView-trackInfo", - "Ai_McRq9wJEYK21w8nX_": "main-nowPlayingView-section", - "EVqc6HChiM9pEqBYAiUE": "main-nowPlayingView-sectionHeader", - "zZdI03asKaUCNlbhjDAv": "main-nowPlayingView-sectionHeaderText", - "gpDSOimnzH4zTJmE7UR5": "main-nowPlayingView-sectionHeaderSpacing", - "N9Xjnxz8vGgWwbEBE5g7": "main-nowPlayingView-lyricsTitle", - "KzMnBC9eFK8cAfcFTg9b": "main-nowPlayingView-lyricsControls", - "I2WIloMMjsBeMaIS8H3v": "main-nowPlayingView-lyricsGradient", - "hzUuLPdH48AzgQun5NYQ": "main-nowPlayingView-lyricsContent", - "kUyRPckYBgHDaJp8bmXi": "main-nowPlayingView-creditsHeader", - "g5zF2gHZOarew6ApvZB6": "main-nowPlayingView-creditsGroup", - "PqjIyA05rhDaDg2S1qIQ": "main-nowPlayingView-creditsSource", - "Mj718TwbPAUi_iNAcsmz": "main-nowPlayingView-queueItem", - "Nyxk_izrYbGecpgmtp91": "main-nowPlayingView-queueItemEntityImage", - "byIN5OSjNcJHipcI9kuf": "main-nowPlayingView-playNext", - "V6Fgup3wwQdhZVYVntrH": "main-nowPlayingView-playNextIcon", - "LT6lpp3S4Tx8VsbnPzuA": "main-nowPlayingView-playNextButton", - "A4e013b7hUST0QPHFqKr": "main-nowPlayingView-playNextButtonIcon", - "y6bXimbi8JAcblOFxTap": "main-trackInfo-equalGradientWidth", - "aMhBfOqJxn4jKzFN07Lg": "main-trackInfo-rightToLeft", - "eSMjmiD29Ox35O95waw6": "main-trackInfo-overlay", - "W5cB_o0XkkU7Q8tlTGxq": "main-trackInfo-contentContainer", - "PGSe59fD1Hwc9yUM2d3U": "main-trackInfo-contentWrapper", - "h8Dik_naJfcSoNM_4FKX": "main-whatsNewFeed-content", - "pNM_LHG1Yp9WV_mBN6du": "main-whatsNewFeed-list", - "LLxSqFbzfI5SPTK_22ZU": "main-whatsNewFeed-listHeader", - "MCctbQkmLVbJyz3NSbq2": "main-whatsNewFeed-listRow", - "nQTI7556vneVslJT_fJv": "main-whatsNewFeed-listContent", - "ThG4UqWk7ASXCMm69Opn": "main-whatsNewFeed-listSubtitleLink", - "GBycF4NUOkA5ZUHneLYa": "main-whatsNewFeed-listImageWrapper", - "ymzFgL9iToSvtRvCWY3b": "main-whatsNewFeed-listExplicitIcon", - "zKLP_l7gmiomI7kW3BMw": "main-whatsNewFeed-listTimeAgo", - "LXfpmhx6aZ9YVV8x4PEI": "main-whatsNewFeed-listPlayButton", - "nHEYUQKiBurmQ7SD4uzF": "main-whatsNewFeed-listFooter", - "BQD_pE0Nva_z6z7CvZww": "main-whatsNewFeed-listEpisodeBody", - "TTFwcgaxN1VxbkjC80_Z": "main-whatsNewFeed-listFallbackIcon", - "_0FuodatXU4_fToYAuYtY": "main-yourLibraryX-libraryFilter", - "RGofdOZulhL2p9MRA5hg": "main-yourLibraryX-librarySort", - "XZRX_ea9eNn4rOLpNGLp": "main-yourLibraryX-librarySortWrapper", - "qEiVyQ28VnOKb0LeijqL": "main-yourLibraryX-listItem", - "ojrThQm1wxR2gZ6GntJB": "main-yourLibraryX-listItemGroup", - "nZSNG58XEPTX69mkNi9n": "main-yourLibraryX-listRowEntityImage", - "d33vqKRxohS9RxzCic1D": "main-yourLibraryX-listRowLink", - "LSrBzBljgLeDhcm3Soye": "main-yourLibraryX-listRowSubtitle", - "gj1L_SVM_H8GteWMdEF_": "main-yourLibraryX-listRowTitleLink", - "G7aCptcOZswI1fN6dGkO": "main-yourLibraryX-listRowIcon", - "HdTF8gsRm5MgWvEYlokG": "main-yourLibraryX-listRowSubtitleLeadingWrapper", - "CmR9tHJ5ta6oWJlKBm3k": "artist-artistVerifiedBadge-wrapper", - "kST1INfbHSxzydJffBq_": "collection-collectionEntityHeroCard-yourEpisodes", - "lBs1v3T3HAPrOxfyWemr": "collection-collectionEntityHeroCard-skeletonRow", - "d8ifuAZX8mK644AwlRZK": "collection-collectionEntityHeroCard-opacityText", - "QoUF6etsDFiL979QR7aC": "collection-collectionEntityHeroCard-moreText", - "iPBJpp5EVkRE24N6vmGA": "lyrics-lyrics-coverTopBar", - "wIyyGaSPOHR78wksX3Us": "search-modal-searchModalInstructions", - "kn5N6aKpq6ebWinhrPPK": "search-modal-hidden", - "EieXgtfUJKc4XQugVglV": "search-modal-key", - "QD13ZfPiO5otS0PU89wG": "playlist-playlist-heading", - "ZbLneLRe2x_OBOYZMX3M": "playlist-playlist-list", - "rjdQaIDkSgcGmxkdI2vU": "playlist-playlist-listItem", - "umouqjSkMUbvF4I_Xz6r": "playlist-playlist-paragraph", - "jpVuvMOCbpaRr_6FLf3W": "playlist-playlist-whiteOpacity", - "muYk5XIwKmqR9iNibk_f": "queue-tabBar-headerIsCentered", - "rHpv7osDRvs3SUPMpQ_g": "queue-queuePage-queuePage", - "DG9CsoFIptJhAneKoo_F": "queue-queuePage-header", - "jf2HafzDEI9jn7Yo05eM": "queue-queuePage-subHeader", - "H3Puuvc2nV0GoZRrfpRS": "queue-queuePage-nextFrom", - "HckHyQocDDePWQL2baOY": "queue-queuePage-nextInQueue", - "VmwiDoU6RpqyzK_n7XRO": "x-downloadButton-cancelDownload", - "l_MW0G9qeeCKlVJwBykT": "x-downloadButton-cancelDownloadButton", - "_APVWqivXc4YqgsnpFkP": "x-downloadButton-removeDownload", - "rEx3EYgBzS8SoY7dmC6x": "x-downloadButton-progress", - "vreceNX3ABcxyddeS83B": "x-entityImage-imageContainer", - "Ozitxbqs1vcOukDz3GDw": "x-entityImage-imagePlaceholder", - "OadpZJiOaGfX6Qp4j6n5": "x-entityImage-circle", - "CxurIfvXVb_TqGF4q8Yf": "x-entityImage-square", - "g3kBhX1E4EYEC2NFhhxG": "x-entityImage-xsmall", - "O5_0cReFdHe81E0xFAD1": "x-entityImage-small", - "H71KtIrytVayf_dFofu7": "x-entityImage-medium", - "SBpny8HrUTBzSjk7Vtk1": "x-entityImage-large", - "AeEoI6ueagbJtaHl2cRd": "x-entityImage-defaultSize", - "iJp40IxKg6emF6KYJ414": "x-entityImage-image", - "t6HIrX67Lp80Nj6tGauz": "x-filterBox-expandedOrHasFilter", - "iiNt4l0UwY2wL42vyBc2": "x-filterBox-fullWidth", - "KAydWoHSkQRqhQ1vkVwK": "x-filterBox-expandRight", - "EsqEJ_NPrHsPkTbX4FW8": "x-filterBox-clearButton", - "XD3TMuMHmKsfbqieC6q_": "x-searchInput-searchInputOnSearch", - "mOLTJ2mxkzHJj6Y9_na_": "x-searchInput-searchInputClearIcon", - "HGN6qJ4noxOV2YSJWj3g": "x-settings-equalizerPanelWrapper", - "PumO62RLWafcexCJx0oe": "x-settings-equalizerPanelPreset", - "aOnWJeLmOj8plFB5QPSt": "x-settings-equalizerPanelFilters", "zrn877LGjVA_oYp2IKeu": "x-settings-equalizerPanelFilter", - "KGnDzV9IPjGQ8Ude8Cgl": "x-settings-equalizerPanelInput", - "NWmefh0djDBBQmHr_mdf": "x-settings-equalizerPanelLabel", + "aOnWJeLmOj8plFB5QPSt": "x-settings-equalizerPanelFilters", "L9sAZBDUVTnJLn7TqR1E": "x-settings-equalizerPanelGainLabel", - "YKGOZh1y8HVOqQgbJB9F": "x-settings-equalizerPanelGainLabelUp", "aPIPHZU8F7TMi6LEw_Yq": "x-settings-equalizerPanelGainLabelDown", - "j7cPtD65ArW8eWnGNrUo": "x-settings-equalizerPresetsContainer", - "ZzNb8P1Bz1VHtlhimIWM": "x-settings-equalizerPresetsLabel", - "FulR95cAh4QPdw6wUeRw": "x-settings-equalizerWrapper", - "ZQftYELq0aOsg6tPbVbV": "Root__top-container", - "WIPpgUp9J37Dwd0ZJnv0": "Root__top-container--right-sidebar-hidden", - "H1bRFdpa3qfekTVTeDwC": "Root__top-container--has-notice-bar", - "EBaPq6VUr6kjeHD9Wf2s": "Root__top-container--transition-enter", - "nxyZPOEjDd5ToiXtSgdA": "Root__top-container--transition-exit", - "H0HbpIM3UrcupWIAjLWu": "cover-art", - "W0TACB7OY0iXtKVOtEhY": "cover-art-auto-height", - "FqmFsMhuF4D0s35Z62Js": "cover-art-image", - "zmOtW0vqqn1qpZrtQ_w9": "cover-art-icon", - "iKgf4UDhbRTHxmZSuAEc": "lyrics-lyrics-adLeaderboardIsEnabled", - "SaEkeiyzAoXnWVSDiTR7": "lyrics-lyrics-vocalRemoval", - "_LKG3z7SnerR0eigPCoK": "lyrics-lyricsContent-isInteractive", - "T3hkVxXuSbCYOD2GIeQd": "main-connectBar-connected", - "GcHojieewpdN1c8vbtwk": "main-connectBar-connecting", - "IbmaxRtjqCjqTBpFwCgw": "main-devicePicker-connected", - "l79vgNZqvs1q9nw6Q8A2": "main-devicePicker-connecting", - "E3EJEgTSJdjF1NrDf9GB": "main-devicePicker-connectingIcon", - "INitzTSjokOMEJOc6P2H": "main-devicePicker-controlButton", - "WFRr38dFOxh75JyzSTj5": "main-devicePicker-indicator", - "_w3sHVCUhYgvQar5WNHw": "main-dragAndDrop-dndImage", - "vb8kSzIiZbfkwqWZROkW": "main-dragAndDrop-dndImageShelter", - "PmW2UCL9vlTcNPD7J0KJ": "main-gridContainer-uniformRowHeight", - "tT6x7wFZmjldiCeh6HzO": "main-nowPlayingBar-isAnonymous", - "RtrMo_s0acvzbSRLovVW": "main-nowPlayingBar-enter", - "D4el1GTrNd7l_TFyRGO8": "main-nowPlayingBar-enterActive", - "HOZJyu9UCJodOQSVvduV": "main-nowPlayingBar-enterDone", - "j96cpCtZAIdqxcDrYHPI": "main-nowPlayingWidget-trackInfo", - "cIUedsmg_cTnTxvOYTKR": "main-nowPlayingView-nowPlayingGrid", - "n4_WcnoVeg2SeDJPWnKK": "main-nowPlayingView-nextInQueue", - "PqL625rkFi7CBiMggYTP": "main-nowPlayingView-openQueue", - "J0xJcBaKhwl9EIuzvhLg": "main-playlistRemoveMultipleModal-container", - "ce3qMCnc2kDVSi7k74fh": "main-playlistRemoveMultipleModal-title", - "tlBLfMv0fCxd31jPTQhL": "main-playlistRemoveMultipleModal-description", - "AytCc2WKUld6N212Pcpu": "main-playlistRemoveMultipleModal-buttonContainer", - "WkSW1U6jr3HDz3vApM56": "main-shelf-skeletonShelf", - "VGKBvschhennrwdTibUE": "main-topBar-rightSidebarVisible", - "Wn5NpEuR1Qw99DelnfxX": "main-trackList-concertTrackList", - "AlqlOMBoMUPbFmLmkhhg": "main-yourLibraryX-navItemOffline", - "a7lvtXATo3HALtrsOHtO": "search-recentSearches-seeAll", - "zi377dMLSwXnFiejYnRa": "search-modal-searchBar", - "aIWRvSjvEN4rTMCIi4vG": "search-modal-hasResults", - "sFFh5DkVxeEcgBGFOvUE": "search-modal-emptyStateContainer", - "v8nEufWSPrv1ql9ZdMko": "search-modal-emptySearchTermContainer", - "tz3aYeI1uG6kMzJOPWr6": "search-modal-searchResultTitle", - "TAHnl8KATdqiQLuz2TLv": "search-modal-searchResultType", - "I9yJ0MC3kmodVJJlA6iq": "search-modal-searchResultRow", - "AnelgzgI75Dckf_LHUiK": "search-modal-entityImage", - "u9KYiVXeDRQDGlTDH6rM": "playlist-playlist-noBooklistSupportContainer", - "iqDYHLUedgX8y1eM1zep": "x-carousel-button", - "ge8K7iQqLE77g0FDGfDn": "x-carousel-carousel", - "IebnAuNOhIG5mDVNJQ5M": "main-noConnection-isError", - "N3juGUCH1EhEzmffNHAp": "main-noConnection-isNotice", - "g_OLJCea3ISA_OEZXMld": "main-topBarStatusIndicator-enter", - "eUtkhxZmvSKe4G9vJbvG": "main-topBarStatusIndicator-enterActive", - "y0CwI5JkA0h0OyLFf53Q": "main-topBarStatusIndicator-exitActive", - "JbIx9RVHwxVXRbXAJaeN": "main-topBarStatusIndicator-notMinimized", - "FannkPV_e2vWawF9QgVA": "main-topBarStatusIndicator-tooltipEnter", - "CtNz_OQHOZ5Z0mJMHjzw": "main-topBarStatusIndicator-tooltipEnterActive", - "rSvmoStBWe2Cft5bw9ya": "main-topBarStatusIndicator-tooltipIsError", - "PHgyArRLVFknlaOm31ID": "Root__top-bar", - "BdcvqBAid96FaHAmPYw_": "Root__nav-bar", - "jEMA2gVoLgPQqAFrPhFw": "Root__main-view", - "lPapCDz3v_LipgXwe8gi": "Root__top-container--right-sidebar-hidden", - "UalNRoO1omHtEEniypS5": "main-downloadClient-container", - "OTfMDdomT5S7B5dbYTT8": "Root__right-sidebar", - "mMjg1Gizg9kYk8ILoTdp": "Root__main-view-overlay", - "UnLGG6p932k7WyjkB9Vo": "desktopmodals-aboutSpotifyModal-container", - "GSFvITwD84dS2JA62Mtj": "desktopmodals-aboutSpotifyModal-closeButton", - "KlzblASEYfUfaykBFZgM": "desktopmodals-aboutSpotifyModal-content", - "XF1XXenkrbdAK2rRoxoU": "desktopmodals-aboutSpotifyModal-copyright", - "Ifnz1lh1jjvqPqJ4KPo8": "desktopmodals-aboutSpotifyModal-licensing", - "qi0hX8uXrbQyS6tvdDBt": "desktopmodals-versionStatus-container", - "WomzHWnDO_yFyjnkd49P": "desktopmodals-versionStatus-content", - "R83hOohwVshnd6bEkDO4": "desktopmodals-versionStatus-copyButton", - "uYKs_kQMPOziaeDj877B": "desktopmodals-licensesModal-container", - "i8qeSJJVx4PXb7fsvOTd": "desktopmodals-licensesModal-content", - "WhIzm3S3R6Ker3XvpYW6": "desktopmodals-licensesModal-licensesFrame", - "qsKpcFrhrA8KtuTVIN_y": "desktopmodals-licensesModal-buttonContainer", - "FKzolQvIeUcXEOsjtw8l": "main-appShell-container", - "cBPbfBWIIPDzhIT6i3ih": "main-buddyFeed-addFriendPlaceholderText", - "MObmOrMxbQpO10ebAtZA": "main-buddyFeed-emptyBuddyFeed", - "Irsd58UNEmDPxdhXKXCs": "main-buddyFeed-playIcon", - "v1Gs5xaHy8aBhUMEobSn": "main-collectionLinkButton-dragEnter", - "bQy_F9QVENlCAL8Qan9_": "main-entityHeader-mermaidGradientOverlay", - "_kVOt2H6WxXzURx2FRLM": "main-home-withAds", - "DQRst2WAECYq2xsrsPRA": "main-home-isOffline", - "sqKERfoKl4KwrtHqcKOd": "main-navBar-mainNav", - "umiKMm5NVr5UeBJCHS6U": "profile-userOverview-container", - "jzhwZKbfx4vrC_MYd_7c": "profile-userOverview-section", - "MWWPQQjbjRfoGdPD8D68": "profile-userOverview-subPage", - "rMpf7sfaPDcj387_52fA": "profile-userOverview-imageContainer", - "kWCnF32FrVtGHmTy8QeV": "profile-userOverview-topTrackSubPage", - "uJxNEI2k7x8UCDdMKELt": "profile-userOverview-title", - "wDIZ2yYKjfGI68I4cZ98": "profile-userOverview-header", - "F8_EX1AeKxXNSeh1qiHq": "profile-userEditDetails-image", - "XwNfIrI6_hCa_9_T2cQB": "profile-userEditDetails-container", - "aM3plU4zzDqjWlvUHGYb": "profile-userEditDetails-header", - "zHeo4VUxytwm6Ptr0QyA": "profile-userEditDetails-closeButton", - "MDb7QhAtHeyM4gKj8j8t": "profile-userEditDetails-saveButton", - "zGbjZMZ1DTx4futEbN9l": "profile-userEditDetails-disclaimer", - "so0bdX3oZH6YW5_nGxIR": "profile-userEditDetails-content", - "uj7hczcCH1dZpse8Kfmi": "profile-userEditDetails-name", - "wvLAEV5wF5C5ej6rvimT": "profile-userEditDetails-label", - "gAQfzAUp1FuSXODeZJfP": "profile-userEditDetails-labelText", - "oN9QVvJKEtdTH3HGfCu1": "profile-userEditDetails-nameInput", - "acVhMt5pELcXQyLaaPuV": "x-proxySettings-ProxySettings", - "AavUTirpKSAHapguSAy0": "x-proxySettings-fullWidth", - "qfjicQPaTTPrLWJWRxMQ": "x-proxySettings-horizontalPair", - "rFFJg1UIumqUUFDgo6n7": "x-settings-button", - "l35q2le3C8eAxw1TKELD": "x-settings-wordBreakAll", + "YKGOZh1y8HVOqQgbJB9F": "x-settings-equalizerPanelGainLabelUp", + "KGnDzV9IPjGQ8Ude8Cgl": "x-settings-equalizerPanelInput", + "NWmefh0djDBBQmHr_mdf": "x-settings-equalizerPanelLabel", + "PumO62RLWafcexCJx0oe": "x-settings-equalizerPanelPreset", + "HGN6qJ4noxOV2YSJWj3g": "x-settings-equalizerPanelWrapper", + "j7cPtD65ArW8eWnGNrUo": "x-settings-equalizerPresetsContainer", + "ZzNb8P1Bz1VHtlhimIWM": "x-settings-equalizerPresetsLabel", + "PiFWoUIRceOm8SHTCakS": "x-settings-equalizerResetButtonWrapper", + "xK6HEWejcSHKyWfhNiJc": "x-settings-equalizerSection", + "FulR95cAh4QPdw6wUeRw": "x-settings-equalizerWrapper", + "GMGmbx5FRBd6DOVvzSgk": "x-settings-firstColumn", + "NnDXf1J9xlVM5AUuqVt1": "x-settings-header", + "DQ9fp5DjBJxKHeHqtFwC": "x-settings-headerContainer", "V4Bh2Ch7KvYUdn2s9ZdX": "x-settings-hidden", - "EvQHNTBhaU3rGCRRlAWj": "artist-artistDiscography-topBar", - "QplCuuGSoV4updqTSLq9": "artist-artistDiscography-topBarScrolled", - "GGx57b6ZwGgzUeTpynUw": "main-collectionLinkButton-iconWrapper", - "GoU8CT9Vm_TP_LyYJTsf": "main-entityHeader-imageContainerClickable", - "k4sYYpEpX2f7RMAPHv3F": "main-contextMenu-menu", - "qUeWph4VP9DwR4xOfabh": "main-contextMenu-menuHeading", - "SN9k988q2Seb_joCaEny": "main-contextMenu-menuItemButton", - "jJzb9peSGYsUDKbc5QBy": "main-contextMenu-disabled", - "IJYRnAk_0OE4UPQABQcl": "main-contextMenu-subMenuIcon", - "GqvHlGax1jo6vO9D0wHH": "main-contextMenu-menuItem", - "hYwu7ZpcbQIP6iM5fzAu": "main-contextMenu-dividerBefore", - "pXsnH0sMlWUGBffe24cr": "main-contextMenu-dividerAfter", - "ctAknuakI8idqf_S9tvT": "main-contextMenu-menuItemLabel", - "dJzYRtCWK2U6k08EtqAg": "main-contextMenu-filterInputContainer", - "IErtLy9qyhR17riTrzYh": "main-contextMenu-expanded", - "pc7Mq0FHh8Nlho4sOJH7": "main-contextMenu-expandButton", - "ycGdaksV3Z5Y7eav3ZyQ": "main-contextMenu-filterInput", - "zfZEbT8RJbcAg13pTMDl": "main-contextMenu-filterInputFullWidth", - "T2BaFHODss7KUUqG8Ryq": "main-contextMenu-overlay", - "qCnh1KNFmroitPazoXOc": "main-contextMenu-expandRight", - "dgc81JRAlkNQTsZae3Bz": "main-contextMenu-searchIconContainer", - "_PqnQJddudWUtaIxOzo7": "main-contextMenu-searchIcon", - "EyDGMdJOp8ktTzmRFcQM": "main-contextMenu-clearButton", - "U3kNTAyv7lhF9nBuwgB6": "main-nowPlayingView-aboutArtist", - "Tk7SUvI_ULiUuC5gZsIx": "main-nowPlayingView-aboutArtistButton", - "ldx08BCI74rTPhgD3vbj": "main-nowPlayingView-aboutArtistContent", - "HISuyqmMLx0amzWHxgN1": "main-nowPlayingView-aboutArtistHasImage", - "RJvcrFChbhxGRIi8mBXJ": "main-nowPlayingView-aboutArtistPlaceholderWrapper", - "DjnRJuC2FcNrQ6Q6DerZ": "main-nowPlayingView-aboutArtistTextContent", - "muTn937T_T9l0xqjlN8A": "main-nowPlayingView-aboutArtistBio", - "vbsB4OQJkFHLU8SbSGzS": "main-nowPlayingView-aboutArtistV2", - "hd6a3g_3QyF8MFL0wWs1": "main-nowPlayingView-aboutArtistV2Button", - "GTmlByXpJj7V6AwVq0Vk": "main-nowPlayingView-aboutArtistV2ImageContainer", - "ouorHKa6NI5cm666H3tp": "main-nowPlayingView-aboutArtistV2Image", - "z9CDQr2gnyXDtcc1uF05": "main-nowPlayingView-aboutArtistV2HasImage", - "yIPdY6L6pcwR4L5Xf0vY": "main-nowPlayingView-aboutArtistV2PlaceholderWrapper", - "jLPxNlznfpZHUtITCFnb": "main-nowPlayingView-aboutArtistV2Avatar", - "vkS_Ks0svKls4w2s2ppT": "main-nowPlayingView-aboutArtistV2Title", - "QkOkUShDYWFx5Cz40Bcn": "main-nowPlayingView-aboutArtistV2TextContent", - "iWpZp7Ab_9h7s_U1SsLN": "main-nowPlayingView-aboutArtistV2Listeners", - "zhQX2DOI2muMo8EKsZ6h": "main-nowPlayingView-aboutArtistV2ListenersCount", - "kVP43jHrJeS7afn8mOgX": "main-nowPlayingView-aboutArtistV2FollowButton", - "COJ84QbXPrd4jkO1HU2N": "main-nowPlayingView-aboutArtistV2Name", - "r9m6lHy7RyIPDzW1Youe": "main-nowPlayingView-aboutArtistV2Bio", - "wpJvLvrrnyP0_C7hLkqg": "main-nowPlayingView-merch", - "qbOrWcMUhSri1nPkZLQA": "main-nowPlayingView-queue", - "l2PpoXJouAgqFCuNT3iB": "main-nowPlayingView-credits", - "bBldZtWu4QtzmrTfHOKm": "main-nowPlayingView-creditsShowAll", - "IgTMXVbZtqtZwu3GZASd": "main-nowPlayingView-artistOnTour", - "uvIvZ4XqfEFs88BAPaI8": "main-nowPlayingView-artistOnTourItem", - "svHFeMC3Ef_TpSdRyvsM": "main-nowPlayingView-artistOnTourShowAll", - "JG5J9NWJkaUO9fiKECMA": "Root__now-playing-bar", - "IAyWaeDamLJLjxuPeVKw": "main-topBar-buddyFeed", - "WtC1lGbmQRplD6JBhNFU": "main-topBar-buddyFeed", - "W0bXxvPV_DhyzwdJWRuU": "main-topBar-buddyFeedActive", - "CE17OcVsW2svuK7ebBcx": "main-topBar-buddyFeedIcon", - "I4p8r1UNjIGk9yv3H2Ms": "main-topBar-whatsNewFeed", - "t794tYAiOJib_IAmmdqq": "main-topBar-whatsNewFeedActive", - "t93PZphItuM19kPhX7tC": "main-topBar-whatsNewFeedIcon", - "RJGA3d0jzObTXwoMUH4p": "main-topBar-whatsNewFeedNotification", - "dmF7or26BvPJs5kQtYVH": "main-topBar-whatsNewFeedNotificationTitle", - "kwTbLplLLsW6T_LrtR7_": "main-topBar-whatsNewFeedNotificationDot", - "Fxnb0xe6bL7I7W8V0p6C": "main-userWidget-boxCondensed", - "RfdRTSGwulyQdDepLUTT": "main-userWidget-showDisplayName", - "VdLuku6YQT4tNLT6ojlD": "main-userWidget-unableToUpdate", - "YqPjzOfhtzbCf_QD3P1f": "main-userWidget-setupPlan", - "pEG0W4wkbkrOYURhz82H": "main-userWidget-hasAvatar", - "Dtr130mQSR0j8k7bu5KS": "main-yourLibraryX-listItemGroupCompact", - "o_wMyH9_LbAmIwlVqsF0": "main-yourLibraryX-listRowIconWrapper", - "TiJahFhH6KZaibhRtEOA": "main-yourLibraryX-isFlattened", - "B_HdWVSEWPHaOf9LQAtC": "main-yourLibraryX-rowCover", + "SkbGMKYv49KtJNB5XxdX": "x-settings-input", + "gvcgOXnAiNKEe_z92_lw": "x-settings-restartAppButton", + "weV_qxFz4gF5sPotO10y": "x-settings-row", + "yNitN64xoLNhzJlkfzOh": "x-settings-secondColumn", + "c6TyNYOUJRIsjYZJZofy": "x-settings-section", "GuwMf98GUBSpCDgf8KRA": "x-settings-tooltip", - "qBZYab2T7Yc4O5Nh0mjA": "x-settings-tooltipIconWrapper", "nW1RKQOkzcJcX6aDCZB4": "x-settings-tooltipIcon", - "aCtCKL9BxAoHeVZS0uRs": "main-popper-container", - "QavgDs_52SpJ2rw0LNYz": "main-popper-arrow", - "bk509U3ZhZc9YBJAmoPB": "main-devicePicker-tooltip", - "tyZF5iwaJ6J5raHWkxwu": "main-devicePicker-connectBarVisible", - "b46WEWO1Sc_P4WK5RTg0": "main-devicePicker-tooltipArrow", - "ItaYxdM8MiuHsa2VXuGQ": "main-devicePicker-tooltipContent", - "uWvwXlS0Da1bWsRX6KOw": "main-devicePicker-nowPlayingActiveIcon", - "AXkwHpGa_BG7Dy4v7o2V": "main-devicePicker-header", - "tm3lCLoFzk25Q_df5g5K": "main-devicePicker-heading", - "SzZayhxQEuTPMFgNrLOG": "main-devicePicker-headingContent", - "gz7xPnsQVKVMnQY2KjJs": "main-devicePicker-headingConnected", - "E9qsFEgJZJnARk6hOCsj": "main-devicePicker-headingTitle", - "TJ5Bjp6vgnWVbh6mGN0n": "main-devicePicker-headingSubtitle", - "YY5a3DPS6akIYNqJdwn3": "main-devicePicker-headingTechIcon", - "pXrRjiuo3ZpGwIvDAGzJ": "main-devicePicker-headingAction", - "LVp1auH4vtD3hvb1s4gl": "main-devicePicker-moreButton", - "pUkuSEO5HGdvTiujyI6H": "main-devicePicker-section", - "IdxmFS96lyE7c5uiTnLM": "main-devicePicker-sectionHeading", - "HVCCFeUiHVwZVv74p34a": "main-devicePicker-sectionWrapper", - "ntdp2T_przGKYzhwYSGz": "main-devicePicker-menuOpen", - "hwP4Oum2PB765sb8jigI": "main-devicePicker-devices", - "zFqMGX3h5z2CO3f2uEiL": "main-devicePicker-devicesList", - "h3qSlLeqACMUaASiKDHa": "main-devicePicker-devicesHeading", - "MMjN8VsyKsAlLjFw4RMa": "main-devicePicker-devicesOtherNetworksHeading", - "YUyFyiI58gL8VuLdbOD6": "main-devicePicker-troubleshooting", - "AN2rvWrkrs7UsnY12hL8": "main-devicePicker-troubleshootingList", - "QClIatTm05fvjVzODr8X": "main-devicePicker-troubleshootingItemIcon", - "OTuSSciCS3NJqFG8OKX2": "main-devicePicker-troubleshootingItemSubtitle", - "SFgYidQmrqrFEVh65Zrg": "main-userWidget-boxCondensed", - "EsgR8WWJIEa9L2wBAKxg": "artist-artistOverview-artistSides", - "_yUo81yeoON6wNqCV_ud": "artist-artistOverview-artistSidesBlock", - "N3mpQyWevHz7lrgLkOBM": "artist-artistAbout-artistSides", - "TxASgfgEtA4JmUkhkNUN": "artist-artistAbout-artistSidesBlock", - "gWUxbU2cIHAajHxsVLMZ": "main-buddyFeed-section", - "WjW1oRtpaNrY37daDP6Y": "main-buddyFeed-sectionFadeEnter", - "T27BYdtZ9ugE_X_JpP1A": "main-buddyFeed-sectionFadeExit", - "C3bqciZSM7rPG_L3ohdC": "main-buddyFeed-sectionFadeEnterActive", - "RLdiPAZ3grZgi7lfHjXA": "main-buddyFeed-sectionFadeExitActive", - "lD5bMttyrRNzsKch6ysa": "main-entityHeader-newEntityHeaders", - "k9LEjzjnGgVaEm3BvhAb": "main-entityHeader-largeHeader", - "_osiFNXU9Cy1X0CYaU9Z": "main-entityHeader-imageContainerNew", - "zjsGbrMpvbdA1HJ4rpfi": "main-entityHeader-smallMadeForIcon", - "A3ohAQNHsDIMv2EM3Ytp": "lyrics-lyricsContent-text", - "aAYpzGljXQv1_zfopxaH": "main-card-cardContainer", - "llTZj1tjDr5ZnIOkKdHv": "main-contextMenu-menuItemStatic", - "abJqsjKClbniwiTCZ7bC": "main-contextMenu-subMenuLeading", - "uEPiT_llP0oFNDYu_QZR": "main-contextMenu-loadingContainer", - "ExGt4YQfmcwvVFGM7tpN": "main-contextMenu-trigger", - "lp9Tfm4rsM9_pfbIE0zd": "main-entityHeader-pretitle", - "YW4dYEf5ZuLzMfSjsqZk": "main-entityHeader-piled", - "sLw5dxB32cAxVxqiar7J": "view-homeShortcutsGrid-title", - "jdqzCrz9SoQp3ZUsU08w": "view-homeShortcutsGrid-gridOf4Columns", - "DqAHiYCkcPCcDorezUKI": "view-homeShortcutsGrid-recentlyPlayedShortcutIcon", - "EzRmGRncgnv1zFgF4dqE": "view-homeShortcutsGrid-name", - "bPmmKmSPLKMhtJSaUJRX": "view-homeShortcutsGrid-shortcutNewEpisodeIndicator", - "vpQWUBWS_lXRLZMRJT7w": "view-homeShortcutsGrid-episodeExtraContent", - "GSv7K805J9Jw7LB9tn2A": "view-homeShortcutsGrid-episodeProgressBar", - "s9c9x_mJq197U2hBzGtV": "view-homeShortcutsGrid-PlayButtonContainerVisible", - "vq0lsCoYrDUDvkuUIaRg": "view-homeShortcutsGrid-playButton", - "Sdmk6QLCvk5EuAP54IN5": "main-shelf-shelfGridResponsive", - "PodseQtNc4pWHyOfGkgA": "main-shelf-shelfGridResponsiveMultiRows", - "ixZyJJ3SHxsSb3NHkhWn": "main-trackList-trackListCompactMode", - "bnolo3jJ8KBxI6jyN7bD": "main-trackList-rowFeedback", - "B2Dwok3Y07k2ttjGDssH": "main-trackList-queuePanelTracklist", - "vDk3w0iWhhczk8PS_K3B": "main-trackList-isRecommendedTrackListRow", - "KJeaWI3jCZemsmu4eYL3": "main-trackList-curationButton", - "UeRAfdSphrPaohh2HWmB": "main-trackList-rowCompactMode", - "gQnx5tArze5q1wfG6AWJ": "main-trackList-rowMainContentCompact", - "nEZjuVeUuGSmYaQWgXTd": "main-trackList-ownedBySelf", - "vL_PgycspyjCBwfFg9j9": "main-trackList-eventVenue", - "rTTxX5loXbtazDI0NLAj": "artist-artistOnTour-eventName", - "QbD9zl7z3AhEQu_TGmo8": "main-home-subfeedSection", - "Cjga8q3TFvtKCu9qfm27": "main-contextMenu-menuItemStatic", - "wtEUrk4Sxa5e3QZhvbrs": "main-contextMenu-subMenuLeading", - "ibA08TpSVrM0wThmotVd": "main-contextMenu-loadingContainer", - "zL6hQR4mukVUUQaa_7K1": "main-nowPlayingView-coverArtContainer", - "jXeqeqkxEBVeFjA2YydA": "x-categoryCard-CategoryCard", - "Op2n2H4o1iY0Xo2wAUH9": "x-categoryCard-image", - "bQthUEx0_U98DJkT1saO": "x-categoryCard-title", - "eEZSnYlv7__34b2yulfm": "volume-bar", - "FZhaXNtbN3Crwrgd0TA7": "volume-bar__icon-button", - "x1jWng8HDweDS840aiIA": "volume-bar__slider-container", - "NH6UaoYYe47eIHA2Rmal": "main-card-imageContainerOld", - "AYwATC_zEPwCkmO1yc8R": "main-card-imageContainerSkeleton", - "coBkWVskipFo8KxLKief": "main-topBar-withBackgroundBlur", - "ep0_ry7CLwf91E1rN6Cv": "main-yourLibraryX-pulse", - "RmWKJG2G0fTrx11zKv_j": "main-entityHeader-theyFollowUs", - "kzlksKUC9aLBM62Bckxo": "main-whatsNewFeed-actions", - "bcU463yG4LHEtlBCOa8Q": "main-whatsNewFeed-buttonAlwaysVisible", - "n5y3jDsz8siC0JsxtS83": "main-whatsNewFeed-buttonVisibleOnHover", - "CONFZNJkrMwpneVuYWXC": "main-whatsNewFeed-description", - "Z1qkHjt67N3DaWqnEM0w": "main-whatsNewFeed-imageContainer", - "nzZgeVfx1Y6nZe7Z9DsA": "main-whatsNewFeed-showImage", - "j45TgktnaHqgEqeO3eXI": "main-whatsNewFeed-largeImage", - "lgo_zhUnwxG2Qan4WLBY": "main-whatsNewFeed-dateAndTime", - "uuqowKOQLu0zbk4zguPM": "main-whatsNewFeed-medium", - "uSj66OUSURBfFwFhD7Ed": "main-whatsNewFeed-separator", - "sQnWbTOGnPZBNn3lZTtI": "main-whatsNewFeed-separatorAlbum", - "eyWbmr17oov600GluVsy": "main-whatsNewFeed-divider", - "_MBf1tVqzfo2AefcuHwv": "main-whatsNewFeed-listRow", - "Z3LszrbA1M2fpLsEhlQT": "main-whatsNewFeed-progressBar", - "rwdnt1SmeRC_lhLVfIzg": "main-topBar-topbarContentRight", - "CWFTCu03cdDALodezHmA": "main-topBar-responsiveForward", - "ima0EKmsnCNUG08T82EM": "view-homeShortcutsGrid-iconDownloaded", - "lt7UxuNqHQBCO6IWyA_G": "view-homeShortcutsGrid-trailingIndicator", - "xHz124sSHSCYHecLCTfi": "main-card-cardTitle", - "r9Oj1LabijReMkOyeUxw": "main-card-newEpisodeIndicator", - "Bob5Qz4qd2ApsH6o1loA": "main-trackList-resizeHandle", - "r53kBgGOdrCYj2Jux0iN": "main-trackList-columnResizing", - "Ty1q4GZz5EJ7Yl2jHs5I": "main-trackInfo-xsmallBadges", - "MIsUJlamzLYuAlvPbmZz": "main-confirmDialog-button", - "KzOZOlCPgREEBCJH1Ieg": "playlist-playlist-leadingSlot", - "a4FkPOXWBc0nK4yzsJCf": "playlist-playlist-concertsFooter", - "DWkbhLMcDefEZwJ5jXCq": "playlist-playlist-promoRow", - "byOUxNEoiJOtBN6xTY24": "playlist-playlist-promoTitle", - "IWWS0F3oiajJG7nlrjXj": "playlist-playlist-ctaLink", - "pbkk9BuHlY36lmWvEmbg": "playlist-playlist-promoImage", - "mWbx87vgssexrOs2tx4I": "playlist-playlist-disclaimerContainer", - "hTRqaN61SDG95erQGMmx": "show-episodeBlock-episodeBlock", - "HLixBI5DbVZNC6lrUbAB": "show-episodeBlock-titleContainer", - "g5gZaZVzR0tGT4pK6iEU": "show-episodeBlock-titleLink", - "bG5fSAAS6rRL8xxU5iyG": "show-episodeBlock-title", - "upo8sAflD1byxWObSkgn": "show-episodeBlock-descriptionContainer", - "LbePDApGej12_NyRphHu": "show-episodeBlock-description", - "ij5_Bi2LfqgWwHzQBXJS": "show-episodeBlock-imageContainer", - "o_TP9z7A8LQvMXujJC7N": "show-episodeBlock-showImage", - "V0pEigrddg3VxP_sTdAJ": "show-episodeBlock-header", - "DbMYFmOEEz9PH1h1zK9n": "show-episodeBlock-actions", - "y9kEPjDek0J80YRf8JJw": "show-episodeBlock-metadata", - "OodUnm1iCEZTUeL6X1gj": "show-show-moreButton", - "kR0M2WSYVUj4cohADSFM": "show-show-episodesHeader", - "jtfSxoRam9rzTtdXIjzc": "show-show-episodesFilter", - "ghfuv80I8uW_ymG_jfx9": "show-show-episodesFilter", - "XGCdw_LcXQHrxmvpxjwi": "main-seekForwardButton-button", - "MRfNcNMd_djj3KOg_VOB": "main-seekBackButton-button", - "d89qxCxbCRj4y1Woft8j": "main-smartShuffleButton-active", - "tr1hDrJgoPSbMXlXU_sl": "npv-nowPlayingBar-container", - "mbUrqWP55sK6zhspiR72": "npv-nowPlayingBar-controls", - "SVGHXIQcH9HYU7uGITw5": "npv-nowPlayingBar-section", - "N5cWYDvyLrfnyMZuqQHo": "npv-nowPlayingBar-left", - "gIobRDHAxkAvUaF4_OOL": "npv-nowPlayingBar-center", - "FTi9QEhetf4Q4__5sb4S": "npv-nowPlayingBar-right", - "Gw7E7MkWci1ttQhb4EK0": "npv-exitFullScreenButton-button", - "KAq2kDjXj2VS4eXrFL4i": "main-userWidget-box", - "LKfKy7bXKmlkMEANVJMS": "main-avatar-avatar", - "nRSfonXHVr6utXYgk2Ui": "Root__globalNav", - "Z6t_8rA6LOBrX3huqRJG": "main-globalNav-historyButtonsContainer", - "VizXsWMIuNfKGN5pMyox": "main-globalNav-historyButtons", - "rBX1EWVZ2EaPwP4y1Gkd": "main-globalNav-icon", - "W02pQCvfy5Bin7z4EAzo": "main-globalNav-searchSection", - "QrpHSphgBSqzODEHqr_t": "main-globalNav-searchContainer", - "jdlOKroADlFeZZQeTdp8": "main-globalNav-link-icon", - "PvsV2JgJRDME1vDn6IJL": "main-globalNav-searchInputSection", - "fksI89zEXwqKWm1O6sJm": "main-globalNav-searchInputContainer", - "OomFKn3bsxs5JfNUoWhz": "main-globalNav-buddyFeed", - "bWBqSiXEceAj1SnzqusU": "main-globalNav-navLink", - "voA9ZoTTlPFyLpckNw3S": "main-globalNav-navLinkActive", - "cUwQnQoE3OqXqSYLT0hv": "link-subtle", - "rQ6LXqVlEOGZdGIG0LgP": "main-contextMenu-menuItem", - "mWj8N7D_OlsbDgtQx5GW": "main-contextMenu-menuItemButton", - "NbcaczStd8vD2rHWwaKv": "main-contextMenu-menu" + "qBZYab2T7Yc4O5Nh0mjA": "x-settings-tooltipIconWrapper", + "l35q2le3C8eAxw1TKELD": "x-settings-wordBreakAll", + "w6j_vX6SF5IxSXrrkYw5": "x-sortBox-sortDropdown", + "es9mguuOfkp6pBe1Bjlw": "x-toggle-indicator", + "Js64TOfWtHksI6TQ6knT": "x-toggle-indicatorWrapper", + "n8tsDTs8wDH73kejYfXs": "x-toggle-input", + "JWYoNAyrIIdW30u4PSGE": "x-toggle-wrapper" } diff --git a/jsHelper/spicetifyWrapper.js b/jsHelper/spicetifyWrapper.js index 95cc955977..f89a6021e9 100644 --- a/jsHelper/spicetifyWrapper.js +++ b/jsHelper/spicetifyWrapper.js @@ -437,7 +437,17 @@ window.Spicetify = { const functionModules = modules.filter(module => typeof module === "function"); const exportedReactObjects = groupBy(modules.filter(Boolean), x => x.$$typeof); const exportedMemos = exportedReactObjects[Symbol.for("react.memo")]; + const exportedForwardRefs = exportedReactObjects[Symbol.for("react.forward_ref")]; const exportedMemoFRefs = exportedMemos.filter(m => m.type.$$typeof === Symbol.for("react.forward_ref")); + const exposeReactComponentsUI = ({ modules, functionModules, exportedForwardRefs }) => { + const componentNames = Object.keys(modules.filter(Boolean).find(e => e.BrowserDefaultFocusStyleProvider)); + const componentRegexes = componentNames.map(n => new RegExp(`"data-encore-id":(?:[a-zA-Z_\$][\w\$]*\\.){2}${n}\\b`)); + const componentPairs = [functionModules.map(f => [f, f]), exportedForwardRefs.map(f => [f.render, f])] + .flat() + .map(([s, f]) => [componentNames.find((_, i) => s.toString().match(componentRegexes[i])), f]); + return Object.fromEntries(componentPairs); + }; + const reactComponentsUI = exposeReactComponentsUI({ modules, functionModules, exportedForwardRefs }); const knownMenuTypes = ["album", "show", "artist", "track"]; const menus = modules @@ -543,28 +553,21 @@ window.Spicetify = { m.toString().includes("action") && m.toString().includes("open") && m.toString().includes("trigger") && m.toString().includes("right-click") ), TooltipWrapper: functionModules.find(m => m.toString().includes("renderInline") && m.toString().includes("showDelay")), - ButtonPrimary: modules.find(m => m?.render && m?.displayName === "ButtonPrimary"), - ButtonSecondary: modules.find(m => m?.render && m?.displayName === "ButtonSecondary"), - ButtonTertiary: modules.find(m => m?.render && m?.displayName === "ButtonTertiary"), + ButtonPrimary: reactComponentsUI.ButtonPrimary, + ButtonSecondary: reactComponentsUI.ButtonSecondary, + ButtonTertiary: reactComponentsUI.ButtonTertiary, Snackbar: { wrapper: functionModules.find(m => m.toString().includes("encore-light-theme") && m.toString().includes("elevated")), simpleLayout: functionModules.find(m => ["leading", "center", "trailing"].every(keyword => m.toString().includes(keyword))), ctaText: functionModules.find(m => m.toString().includes("ctaText")), styledImage: functionModules.find(m => m.toString().includes("placeholderSrc")) }, - Chip: modules.find(m => m?.render?.toString().includes("invertedDark") && m?.render?.toString().includes("isUsingKeyboard")), + Chip: reactComponentsUI.Chip, Toggle: functionModules.find(m => m.toString().includes("onSelected") && m.toString().includes('type:"checkbox"')), Cards: { - Default: functionModules.find( - m => m.toString().includes("?highlight") && m.toString().includes("headerText") && m.toString().includes("imageContainer") - ), + Default: reactComponentsUI.Card, Hero: functionModules.find(m => m?.toString().includes('"herocard-click-handler"')), - CardImage: functionModules.find( - m => - m.toString().includes("isHero") && - (m.toString().includes("withWaves") || m.toString().includes("isCircular")) && - m.toString().includes("imageWrapper") - ), + CardImage: reactComponentsUI.CardImage, ...Object.fromEntries(cards) }, Router: functionModules.find(m => m.toString().includes("navigationType") && m.toString().includes("static")), @@ -573,6 +576,7 @@ window.Spicetify = { StoreProvider: functionModules.find(m => m.toString().includes("notifyNestedSubs") && m.toString().includes("serverState")), Navigation: exportedMemoFRefs.find(m => m.type.render.toString().includes("navigationalRoot")), ScrollableContainer: functionModules.find(m => m.toString().includes("scrollLeft") && m.toString().includes("showButtons")), + IconComponent: reactComponentsUI.Icon, ...Object.fromEntries(menus) }, ReactHook: { @@ -991,9 +995,13 @@ Spicetify._getStyledClassName = (args, component) => { "$size", "$iconColor", "$variant", - "$semanticColor" + "$semanticColor", + "$buttonSize", + "$position", + "$iconSize" ]; - const customKeys = ["padding", "blocksize"]; + const customKeys = ["blocksize"]; + const customExactKeys = ["$padding", "padding"]; const element = Array.from(args).find( e => @@ -1001,6 +1009,7 @@ Spicetify._getStyledClassName = (args, component) => { e?.dangerouslySetInnerHTML || typeof e?.className !== "undefined" || includedKeys.some(key => typeof e?.[key] !== "undefined") || + customExactKeys.some(key => typeof e?.[key] !== "undefined") || customKeys.some(key => Object.keys(e).some(k => k.toLowerCase().includes(key))) ); @@ -1014,7 +1023,7 @@ Spicetify._getStyledClassName = (args, component) => { } } - const excludedKeys = ["children", "className", "style", "dir", "key", "ref", "as", "isUsingKeyboard", "$autoMirror", "$hasFocus", ""]; + const excludedKeys = ["children", "className", "style", "dir", "key", "ref", "as", "$autoMirror", "$hasFocus", ""]; const excludedPrefix = ["aria-"]; const childrenProps = ["iconLeading", "iconTrailing", "iconOnly"]; @@ -1033,7 +1042,10 @@ Spicetify._getStyledClassName = (args, component) => { } const customEntries = Object.entries(element).filter( - ([key, value]) => customKeys.some(k => key.toLowerCase().includes(k)) && typeof value === "string" && value.length + ([key, value]) => + (customKeys.some(k => key.toLowerCase().includes(k)) || customExactKeys.some(k => key.toLowerCase().includes(k))) && + typeof value === "string" && + value.length ); for (const [key, value] of customEntries) { @@ -2033,6 +2045,7 @@ Spicetify.Topbar = (() => { let rightContainer; const leftButtonsStash = new Set(); const rightButtonsStash = new Set(); + const generatedClassName = "Button-medium-medium-buttonTertiary-iconOnly-condensed-disabled-isUsingKeyboard-useBrowserDefaultFocusStyle"; class Button { constructor(label, icon, onClick, disabled = false, isRight = false) { @@ -2058,10 +2071,7 @@ Spicetify.Topbar = (() => { } else { this.button.classList.add("main-topBar-button"); if (globalHistoryButtons) { - this.button.classList.add( - "main-globalNav-icon", - "Button-medium-medium-buttonTertiary-iconOnly-condensed-disabled-useBrowserDefaultFocusStyle" - ); + this.button.classList.add("main-globalNav-icon", generatedClassName); } leftButtonsStash.add(this.element); @@ -2120,15 +2130,9 @@ Spicetify.Topbar = (() => { const buttonElement = button.querySelector("button"); if (globalHistoryButtons) { - buttonElement.classList.add( - "main-globalNav-icon", - "Button-medium-medium-buttonTertiary-iconOnly-condensed-disabled-useBrowserDefaultFocusStyle" - ); + buttonElement.classList.add("main-globalNav-icon", generatedClassName); } else { - buttonElement.classList.remove( - "main-globalNav-icon", - "Button-medium-medium-buttonTertiary-iconOnly-condensed-disabled-useBrowserDefaultFocusStyle" - ); + buttonElement.classList.remove("main-globalNav-icon", generatedClassName); } } leftContainer.append(...leftButtonsStash); diff --git a/spicetify.go b/spicetify.go index 0af1310340..fe6bc981c7 100644 --- a/spicetify.go +++ b/spicetify.go @@ -51,7 +51,7 @@ func init() { // Separates flags and commands for _, v := range os.Args[1:] { - if v[0] == '-' && v != "-1" { + if len(v) > 0 && v[0] == '-' && v != "-1" { if v[1] != '-' && len(v) > 2 { for _, char := range v[1:] { flags = append(flags, "-"+string(char)) @@ -356,17 +356,17 @@ path Prints path of Spotify's executable, userdata, and more. 4. Toggle focus with flags: spicetify path