commit 3edd92e1b8e09ecb2b22e33f66be028147c2555c Author: khanhas Date: Wed Jun 2 00:01:11 2021 +1000 add: Dribbblish v2 diff --git a/README.md b/README.md new file mode 100644 index 0000000..9510158 --- /dev/null +++ b/README.md @@ -0,0 +1,92 @@ +# Dribbblish + +### base +![base](base.png) +### white +![white](white.png) +### dark +![dark](dark.png) +### nord-light +![nord-light](nord-light.png) +### nord-dark +![nord-dark](nord-dark.png) +### beach-sunset +![beach-sunset](beach-sunset.png) +### purple +![purple](purple.png) +### samourai +![samourai](samourai.png) + +## Features +### Resizable sidebar + +img + +### Customizable sidebar +Rearrange icons positions, stick icons to header or hide unnecessary to save space. +Turn on Config mode in Profile menu and hover on icon to show control buttons. +After you finish customizing, turn off Config mode in Profile menu to save. + +img + +### Playlist Folder image +Right click at folder and choose images for your playlist folder. Every image formats supported by Chrome can be used, but do keep image size small and in compressed format. + +img + +### Left/Right expanded cover +In profile menu, toggle option "Right expanded cover" to change expaned current track cover image to left or right side, whereever you prefer. + +## Install +Make sure you are using spicetify v2 and Spotify v1.1.58 or later. + +Run these commands: + +### Linux and MacOS: +In **Bash**: +```bash +cd "$(dirname "$(spicetify -c)")/Themes/Dribbblish" +mkdir -p ../../Extensions +cp dribbblish.js ../../Extensions/. +spicetify config extensions dribbblish.js +spicetify config current_theme Dribbblish color_scheme base +spicetify config inject_css 1 replace_colors 1 overwrite_assets 1 +spicetify apply +``` + +### Windows +In **Powershell**: +```powershell +cd "$(spicetify -c | Split-Path)\Themes\Dribbblish" +Copy-Item dribbblish.js ..\..\Extensions +spicetify config extensions dribbblish.js +spicetify config current_theme Dribbblish color_scheme base +spicetify config inject_css 1 replace_colors 1 overwrite_assets 1 +spicetify apply +``` + +## Change Color Schemes +There are 9 color schemes you can choose: `base`, `white`, `dark`, `dracula`, `nord-dark`, `nord-light`, `samourai`, `purple`. Change scheme with commands: +``` +spicetify config color_scheme +spicetify apply +``` + +## Hide Window Controls +Windows user, please edit your Spotify shortcut and add flag `--transparent-window-controls` after the Spotify.exe: +![instruction1](./windows-shortcut-instruction.png) + +Alternatively, you can use `SpotifyNoControl.exe`, included in this theme package, to completely remove all windows controls and title menu (three dot at top left corner). Title menu still can be access via Alt key. Closing, minimizing can be done via right click menu at top window region. +`SpotifyNoControl.exe` could be used as Spotify launcher, it opens Spotify and hides controls right after. You can drag and drop it to your taskbar but make sure you unpin the original Spotify icon first. Alternatively you can make a shortcut for it and add to desktop or start menu. +Moreover, by default, Spotify adjusted sidebar items and profile menu icon to stay out of Windows native controls region. If you decided to use `SpotifyNoControl.exe` from now on, please open `user.css` file and change variable `--os-windows-icon-dodge` value to 0 as instruction to snap icons back to their original position. + +![nocontrol](https://i.imgur.com/qdZyv1t.png) + +## Uninstall + +Remove the dribbblish script with the following commands + +``` +spicetify config extensions dribbblish.js- +spicetify apply +``` diff --git a/assets/glue-resources/fonts/GoogleSansDisplayMedium.woff2 b/assets/glue-resources/fonts/GoogleSansDisplayMedium.woff2 new file mode 100644 index 0000000..2430944 Binary files /dev/null and b/assets/glue-resources/fonts/GoogleSansDisplayMedium.woff2 differ diff --git a/assets/glue-resources/fonts/GoogleSansDisplayRegular.woff2 b/assets/glue-resources/fonts/GoogleSansDisplayRegular.woff2 new file mode 100644 index 0000000..911e5f8 Binary files /dev/null and b/assets/glue-resources/fonts/GoogleSansDisplayRegular.woff2 differ diff --git a/assets/glue-resources/fonts/Roboto.woff2 b/assets/glue-resources/fonts/Roboto.woff2 new file mode 100644 index 0000000..9a0064e Binary files /dev/null and b/assets/glue-resources/fonts/Roboto.woff2 differ diff --git a/assets/glue-resources/fonts/RobotoMedium.woff2 b/assets/glue-resources/fonts/RobotoMedium.woff2 new file mode 100644 index 0000000..6a88805 Binary files /dev/null and b/assets/glue-resources/fonts/RobotoMedium.woff2 differ diff --git a/base.png b/base.png new file mode 100644 index 0000000..ce56373 Binary files /dev/null and b/base.png differ diff --git a/beach-sunset.png b/beach-sunset.png new file mode 100644 index 0000000..3cf9f78 Binary files /dev/null and b/beach-sunset.png differ diff --git a/color.ini b/color.ini new file mode 100644 index 0000000..437d5e0 --- /dev/null +++ b/color.ini @@ -0,0 +1,162 @@ +[base] +text = FFFFFF +subtext = F0F0F0 +sidebar-text = FFFFFF +main = 000000 +sidebar = 1ed760 +player = 000000 +card = 000000 +shadow = 202020 +selected-row = 797979 +button = 1ed760 +button-active = 1ed760 +button-disabled = 535353 +tab-active = 166632 +notification = 1db954 +notification-error = e22134 +misc = BFBFBF + + +[white] +text = 363636 +subtext = 3D3D3D +sidebar-text = FFF9F4 +main = FFF9F4 +sidebar = FFA789 +player = FFF9F4 +card = FFF9F4 +shadow = d3d3d3 +selected-row = 6D6D6D +button = ff8367 +button-active = ff8367 +button-disabled = 535353 +tab-active = ffdace +notification = FFA789 +notification-error = e22134 +misc = BFBFBF + +[dark] +text = F0F0F0 +subtext = F0F0F0 +sidebar-text = 0a0e14 +main = 0a0e14 +sidebar = C2D935 +player = 0a0e14 +card = 0a0e14 +shadow = 202020 +selected-row = DEDEDE +button = C2D935 +button-active = C2D935 +button-disabled = 535353 +tab-active = 727d2b +notification = C2D935 +notification-error = e22134 +misc = BFBFBF + +[dracula] +text = f8f8f2 +subtext = f8f8f2 +sidebar-text = F0F0F0 +main = 44475a +sidebar = 6272a4 +player = 44475a +card = 6272a4 +shadow = 000000 +selected-row = bd93f9 +button = ffb86c +button-active = 8be9fd +button-disabled = 535353 +tab-active = 6272a4 +notification = bd93f9 +notification-error = e22134 +misc = BFBFBF + +[nord-light] +text = 2e3440 +subtext = 3b4252 +sidebar-text = ECEFF4 +main = ECEFF4 +sidebar = 5E81AC +player = ECEFF4 +card = ebcb8b +shadow = eceff4 +selected-row = 4c566a +button = 81a1c1 +button-active = 81a1c1 +button-disabled = c0c0c0 +tab-active = ebcb8b +notification = a3be8c +notification-error = bf616a +misc = BFBFBF + +[nord-dark] +text = ECEFF4 +subtext = E5E9F0 +sidebar-text = 434c5e +main = 2e3440 +sidebar = 88C0D0 +player = 2e3440 +card = 2e3440 +shadow = 2E3440 +selected-row = D8DEE9 +button = 81A1C1 +button-active = 81A1C1 +button-disabled = 434C5E +tab-active = 434C5E +notification = A3BE8C +notification-error = BF616A +misc = BFBFBF + +[purple] +text = f1eaff +subtext = f1eaff +sidebar-text = e0d0ff +main = 0A0E14 +sidebar = 6F3C89 +player = 0A0E14 +card = 0A0E14 +shadow = 3a2645 +selected-row = EBDFFF +button = c76af6 +button-active = 6F3C89 +button-disabled = 535353 +tab-active = 58306D +notification = ff9e00 +notification-error = f61379 +misc = DEDEDE + +[samourai] +text = ebdbb2 +subtext = ebdbb2 +sidebar-text = 461217 +main = 461217 +sidebar = ebdbb2 +player = 461217 +card = 461217 +shadow = 3a2645 +selected-row = 909090 +button = e7a52d +button-active = e7a52d +button-disabled = 535353 +tab-active = e7a52d +notification = e7a52d +notification-error = e22134 +misc = BFBFBF + +[beach-sunset] +text = FFFFFF +subtext = F0F0F0 +sidebar-text = F0F0F0 +main = 262626 +sidebar = bd3e3e +player = 262626 +card = 262626 +shadow = 000000 +selected-row = d1d6e2 +button = f1a84f +button-active = c98430 +button-disabled = 535353 +tab-active = f1a84f +notification = c98430 +notification-error = e22134 +misc = BFBFBF \ No newline at end of file diff --git a/dark.png b/dark.png new file mode 100644 index 0000000..e3d85db Binary files /dev/null and b/dark.png differ diff --git a/dribbblish.js b/dribbblish.js new file mode 100644 index 0000000..80f578a --- /dev/null +++ b/dribbblish.js @@ -0,0 +1,398 @@ +// Hide popover message +// document.getElementById("popover-container").style.height = 0; +const DribbblishShared = { + configMenu: new Spicetify.Menu.SubMenu("Dribbblish", []), + rightBigCover: localStorage.getItem("dribs-right-big-cover") === "true", + setRightBigCover: () => { + if (DribbblishShared.rightBigCover) { + document.documentElement.classList.add("right-expanded-cover"); + } else { + document.documentElement.classList.remove("right-expanded-cover"); + } + } +}; + +DribbblishShared.configMenu.register(); +DribbblishShared.configMenu.subItems.push(new Spicetify.Menu.Item( + "Right expanded cover", + DribbblishShared.rightBigCover, + (self) => { + self.isEnabled = !self.isEnabled; + DribbblishShared.rightBigCover = self.isEnabled; + localStorage.setItem("dribs-right-big-cover", self.isEnabled); + DribbblishShared.setRightBigCover(); + } +)); +DribbblishShared.setRightBigCover(); + +function waitForElement(els, func, timeout = 100) { + const queries = els.map(el => document.querySelector(el)); + if (queries.every(a => a)) { + func(queries); + } else if (timeout > 0) { + setTimeout(waitForElement, 300, els, func, --timeout); + } +} + +waitForElement([".main-rootlist-rootlistPlaylistsScrollNode ul"], ([query]) => { + /** Replace Playlist name with their pictures */ + function loadPlaylistImage() { + const sidebarItem = query.querySelectorAll("li.GlueDropTarget"); + for (let i = 0; i < sidebarItem.length; i++) { + const item = sidebarItem[i]; + let link = item.querySelector("a"); + if (!link) continue; + + let [_, app, uid ] = link.pathname.split("/"); + let uri; + if (app === "playlist") { + uri = Spicetify.URI.playlistV2URI(uid); + } else if (app === "folder") { + const base64 = localStorage.getItem("dribbblish:folder-image:" + uid); + let img = link.querySelector("img"); + if (!img) { + img = document.createElement("img"); + img.classList.add("playlist-picture"); + link.prepend(img); + } + if (base64) { + img.src = base64; + } else { + img.src = ""; + } + continue; + } + + Spicetify.CosmosAsync.get( + `sp://core-playlist/v1/playlist/${uri.toURI()}/metadata`, + { policy: { picture: true } } + ).then(res => { + const meta = res.metadata; + let img = link.querySelector("img"); + if (!img) { + img = document.createElement("img"); + img.classList.add("playlist-picture"); + link.prepend(img); + } + img.src = meta.picture; + }); + } + } + + DribbblishShared.loadPlaylistImage = loadPlaylistImage; + loadPlaylistImage(); + + new MutationObserver(loadPlaylistImage) + .observe(query, {childList: true}); +}); + +waitForElement([".Root__main-view"], ([mainView]) => { + const shadow = document.createElement("div"); + shadow.id = "dribbblish-back-shadow"; + mainView.prepend(shadow); +}); + +waitForElement([".main-rootlist-rootlistPlaylistsScrollNode"], (queries) => { + const fade = document.createElement("div"); + fade.id = "dribbblish-sidebar-fade-in"; + queries[0].append(fade); +}); + +waitForElement([ + ".main-navBar-entryPoints", + ".main-rootlist-rootlistPlaylistsScrollNode .os-content", + ".main-rootlist-rootlistContent" +], ([appItems, playlistItems, personalLibrary]) => { + const HIDDEN = 0, SHOW = 1, STICKY = 2; + + let buttons = []; + let storage = []; + let ordered; + const list = document.createElement("ul"); + const hiddenList = document.createElement("ul"); + hiddenList.id = "dribs-hidden-list"; + hiddenList.classList.add("hidden-visually"); + const playlistList = playlistItems.querySelector("ul"); + playlistList.id = "dribs-playlist-list"; + playlistItems.prepend(list, hiddenList); + + const up = document.createElement("button"); up.innerText = "Up"; + const down = document.createElement("button"); down.innerText = "Down"; + const hide = document.createElement("button"); + const stick = document.createElement("button"); + const container = document.createElement("div"); + container.id = "dribs-sidebar-config"; + container.append(up, down, hide, stick); + + for (const ele of appItems.children) { + ele.dataset.id = ele.querySelector("a").pathname; + buttons.push(ele); + } + + for (const ele of personalLibrary.querySelectorAll("div.GlueDropTarget")) { + const link = ele.querySelector("a"); + if (!link) { + ele.dataset.id = "/add"; + } else { + ele.dataset.id = link.pathname; + } + ele.classList.add("personal-library"); + buttons.push(ele); + } + + try { + storage = JSON.parse(localStorage.getItem("dribs-sidebar-config")) + if (!Array.isArray(storage)) throw ""; + } catch { + storage = buttons.map(el => [el.dataset.id, SHOW]); + } + + function arrangeItems() { + const newButtons = [...buttons]; + const orderedButtons = []; + for (const ele of storage) { + const index = newButtons.findIndex(a => ele[0] === a?.dataset.id); + if (index !== -1) { + orderedButtons.push([newButtons[index], ele[1]]); + newButtons[index] = undefined; + } + } + newButtons + .filter(a => a) + .forEach(a => orderedButtons.push([a, STICKY])); + ordered = orderedButtons; + } + + function appendItems() { + const toShow = [], toHide = [], toStick = []; + for (const el of ordered) { + const [ item, status ] = el; + if (status === STICKY) { + appItems.append(item); + toStick.push(el); + } else if (status === SHOW) { + list.append(item); + toShow.push(el); + } else { + hiddenList.append(item); + toHide.push(el); + } + } + ordered = [ ...toStick, ...toShow, ...toHide ]; + } + + function writeStorage() { + const array = ordered.map(a => [a[0].dataset.id, a[1]]); + console.log(array); + localStorage.setItem("dribs-sidebar-config", JSON.stringify(array)); + } + + arrangeItems(); + appendItems(); + + const observer = new MutationObserver(() => { + const residues = personalLibrary.querySelectorAll(".main-rootlist-rootlistContent > div.GlueDropTarget"); + for (const ele of residues) { + ele.dataset.id = ele.querySelector("a").pathname; + ele.classList.add("personal-library"); + buttons.push(ele); + } + arrangeItems(); + appendItems(); + }); + observer.observe(personalLibrary, { childList: true }); + setTimeout(() => observer.disconnect(), 10000); + + function onSwap(item, dir) { + container.remove(); + const curPos = ordered.findIndex(e => e[0] === item); + const newPos = curPos + dir; + if (newPos < 0 || newPos > (ordered.length - 1)) return; + if (ordered[curPos][1] !== ordered[newPos][1]) return; + [ordered[curPos], ordered[newPos]] = [ordered[newPos], ordered[curPos]]; + appendItems(); + } + + function onChangeStatus(item, status) { + container.remove(); + const curPos = ordered.findIndex(e => e[0] === item); + ordered[curPos][1] = ordered[curPos][1] === status ? SHOW : status; + appendItems(); + } + + function injectInteraction() { + document.documentElement.style.setProperty("--sidebar-width", "280px"); + document.documentElement.classList.remove("sidebar-hide-text"); + hiddenList.classList.remove("hidden-visually"); + for (const el of ordered) { + el[0].onmouseover = () => { + const [ item, status ] = el; + const index = ordered.findIndex(a => a === el); + if (index === 0 || ordered[index][1] !== ordered[index - 1][1]) { + up.disabled = true; + } else { + up.disabled = false; + up.onclick = () => onSwap(item, -1); + } + if (index === (ordered.length - 1) || ordered[index][1] !== ordered[index + 1][1]) { + down.disabled = true; + } else { + down.disabled = false; + down.onclick = () => onSwap(item, 1); + } + + stick.innerText = status === STICKY ? "Unstick" : "Stick"; + hide.innerText = status === HIDDEN ? "Unhide" : "Hide"; + hide.onclick = () => onChangeStatus(item, HIDDEN); + stick.onclick = () => onChangeStatus(item, STICKY); + + item.append(container); + }; + } + } + + function removeInteraction() { + hiddenList.classList.add("hidden-visually"); + container.remove(); + ordered.forEach(a => a[0].onmouseover = undefined); + writeStorage(); + } + + DribbblishShared.configMenu.subItems.push(new Spicetify.Menu.Item( + "Sidebar config", + false, + (self) => { + self.isEnabled = !self.isEnabled; + if (self.isEnabled) { + injectInteraction(); + } else { + removeInteraction(); + } + } + )); +}); + +waitForElement([".Root__nav-bar .LayoutResizer__input"], ([resizer]) => { + const observer = new MutationObserver(updateVariable); + observer.observe(resizer, { attributes: true, attributeFilter: ["value"]}); + function updateVariable() { + let value = resizer.value; + if (value < 121) { + value = 72; + document.documentElement.classList.add("sidebar-hide-text"); + } else { + document.documentElement.classList.remove("sidebar-hide-text"); + } + document.documentElement.style.setProperty( + "--sidebar-width", value + "px"); + } + updateVariable(); +}); + +waitForElement([".Root__main-view .os-resize-observer-host"], ([resizeHost]) => { + const observer = new ResizeObserver(updateVariable); + observer.observe(resizeHost); + function updateVariable([ event ]) { + document.documentElement.style.setProperty( + "--main-view-width", event.contentRect.width + "px"); + document.documentElement.style.setProperty( + "--main-view-height", event.contentRect.height + "px"); + if (event.contentRect.width < 700) { + document.documentElement.classList.add("minimal-player"); + } else { + document.documentElement.classList.remove("minimal-player"); + } + if (event.contentRect.width < 550) { + document.documentElement.classList.add("extra-minimal-player"); + } else { + document.documentElement.classList.remove("extra-minimal-player"); + } + } +}); + +(function Dribbblish() { + const progBar = document.querySelector(".playback-bar"); + + if (!Spicetify.Player.origin || !progBar) { + setTimeout(Dribbblish, 300); + return; + } + + const tooltip = document.createElement("div"); + tooltip.className = "prog-tooltip"; + progBar.append(tooltip); + + const progKnob = progBar.querySelector(".progress-bar__slider"); + + Spicetify.Player.addEventListener("onprogress", ({ data: e }) => { + const offsetX = progKnob.offsetLeft + progKnob.offsetWidth / 2; + const maxWidth = progBar.offsetWidth; + const curWidth = Spicetify.Player.getProgressPercent() * maxWidth; + const ttWidth = tooltip.offsetWidth / 2; + if (curWidth < ttWidth) { + tooltip.style.left = String(offsetX) + "px"; + } else if (curWidth > maxWidth - ttWidth) { + tooltip.style.left = String(offsetX - ttWidth * 2) + "px"; + } else { + tooltip.style.left = String(offsetX - ttWidth) + "px"; + } + tooltip.innerText = Spicetify.Player.formatTime(e) + " / " + + Spicetify.Player.formatTime(Spicetify.Player.getDuration()); + }); + + const filePickerForm = document.createElement("form"); + filePickerForm.setAttribute("aria-hidden", true); + filePickerForm.innerHTML = ''; + document.body.appendChild(filePickerForm); + /** @type {HTMLInputElement} */ + const filePickerInput = filePickerForm.childNodes[0]; + filePickerInput.accept = [ + "image/jpeg", + "image/apng", + "image/avif", + "image/gif", + "image/png", + "image/svg+xml", + "image/webp" + ].join(","); + + filePickerInput.onchange = () => { + if (!filePickerInput.files.length) return; + + const file = filePickerInput.files[0]; + const reader = new FileReader; + reader.onload = (event) => { + const result = event.target.result; + const id = Spicetify.URI.from(filePickerInput.uri).id; + try { + localStorage.setItem( + "dribbblish:folder-image:" + id, + result + ); + } catch { + Spicetify.showNotification("File too large"); + } + DribbblishShared.loadPlaylistImage?.call(); + } + reader.readAsDataURL(file); + } + + new Spicetify.ContextMenu.Item("Remove folder image", + ([uri]) => { + const id = Spicetify.URI.from(uri).id; + localStorage.removeItem("dribbblish:folder-image:" + id); + DribbblishShared.loadPlaylistImage?.call(); + }, + ([uri]) => Spicetify.URI.isFolder(uri), + "x", + ).register(); + new Spicetify.ContextMenu.Item("Choose folder image", + ([uri]) => { + filePickerInput.uri = uri; + filePickerForm.reset(); + filePickerInput.click(); + }, + ([uri]) => Spicetify.URI.isFolder(uri), + "edit", + ).register(); +})(); diff --git a/nord-dark.png b/nord-dark.png new file mode 100644 index 0000000..3f01074 Binary files /dev/null and b/nord-dark.png differ diff --git a/nord-light.png b/nord-light.png new file mode 100644 index 0000000..da10386 Binary files /dev/null and b/nord-light.png differ diff --git a/purple.png b/purple.png new file mode 100644 index 0000000..30c9074 Binary files /dev/null and b/purple.png differ diff --git a/samourai.png b/samourai.png new file mode 100644 index 0000000..fa9505c Binary files /dev/null and b/samourai.png differ diff --git a/user.css b/user.css new file mode 100644 index 0000000..a62344e --- /dev/null +++ b/user.css @@ -0,0 +1,770 @@ +:root { + --bar-height: 70px; + --bar-cover-art-size: 40px; + --main-gap: 10px; + --main-corner-radius: 10px; + --scrollbar-vertical-size: 8px; + --cover-border-radius: 8px; + --os-windows-icon-dodge: 0; +} + +@font-face { + font-family: "Google Sans Display"; + src: url("https://local_resource_host/fonts/GoogleSansDisplayRegular.woff2") format("woff2"); + font-style: normal; + font-weight: 400; +} + +@font-face { + font-family: "Google Sans Display"; + src: url("https://local_resource_host/fonts/GoogleSansDisplayMedium.woff2") format("woff2"); + font-style: normal; + font-weight: 500; +} + +@font-face { + font-family: "Roboto"; + src: url("https://local_resource_host/fonts/Roboto.woff2") format("woff2"); + font-style: normal; + font-weight: 400; +} + +@font-face { + font-family: "Roboto"; + src: url("https://local_resource_host/fonts/RobotoMedium.woff2") format("woff2"); + font-style: normal; + font-weight: 500; +} + +body { + --glue-font-family: "Google Sans Display","Roboto",spotify-circular,spotify-circular-cyrillic,spotify-circular-arabic,spotify-circular-hebrew,Helvetica Neue,helvetica,arial,Hiragino Kaku Gothic Pro,Meiryo,MS Gothic,sans-serif; + --info-font-family: "Roboto",spotify-circular,spotify-circular-cyrillic,spotify-circular-arabic,spotify-circular-hebrew,Helvetica Neue,helvetica,arial,Hiragino Kaku Gothic Pro,Meiryo,MS Gothic,sans-serif; + font-family: var(--glue-font-family); + letter-spacing: normal; +} + +.main-type-mesto, +.main-type-mestoBold, +.main-type-ballad, +.main-type-balladBold, +.main-type-canon { + font-family: var(--info-font-family); + letter-spacing: normal; +} + +.main-type-ballad { + font-weight: 500; +} + +.lyrics-lyricsContainer-LyricsLine { + font-family: var(--glue-font-family); + letter-spacing: normal !important; +} + +.main-rootlist-rootlistDividerGradient { + background: unset; +} + +input { + background-color: unset !important; + border-bottom: solid 1px var(--spice-text) !important; + border-radius: 0 !important; + padding: 6px 10px 6px 48px; + color: var(--spice-text) !important; +} + +.x-searchInput-searchInputSearchIcon, +.x-searchInput-searchInputClearButton { + color: var(--spice-text) !important; +} + +.main-home-homeHeader, +.x-entityHeader-overlay, +.x-actionBarBackground-background, +.main-actionBarBackground-background, +.main-entityHeader-overlay, +.main-entityHeader-backgroundColor +{ + background-color: unset !important; + background-image: unset !important; +} + +.main-playButton-PlayButton.main-playButton-primary { + color: white; +} + +.connect-title, .connect-header { + display: none; +} + +.connect-device-list { + margin: 0px -5px; +} + +/* Remove Topbar background colour */ +.main-topBar-background { + background-color: unset !important; +} +.main-topBar-overlay { + background-color: var(--spice-main); +} + +.main-entityHeader-shadow, +.main-contextMenu-menu, +.connect-device-list-container { + box-shadow: 0 4px 20px #21212130; +} + +.main-trackList-playingIcon { + filter: grayscale(1); +} + +span.artist-artistVerifiedBadge-badge svg:nth-child(1) { + fill: black; +} + +/* Full window artist background */ +.main-entityHeader-background.main-entityHeader-gradient { + opacity: 0.3; +} + +.main-entityHeader-container.main-entityHeader-withBackgroundImage, +.main-entityHeader-background, +.main-entityHeader-background.main-entityHeader-overlay:after { + height: 100vh; +} + +.main-entityHeader-withBackgroundImage .main-entityHeader-headerText { + justify-content: center; +} + +.main-entityHeader-container.main-entityHeader-nonWrapped.main-entityHeader-withBackgroundImage { + padding-left: 9%; +} + +.main-entityHeader-background.main-entityHeader-overlay:after { + background-image: linear-gradient(transparent,transparent),linear-gradient(var(--spice-main), var(--spice-main)); +} + +.artist-artistOverview-overview .main-entityHeader-withBackgroundImage h1 { + font-size: 175px !important; + line-height: 175px !important; +} + +/** Hightlight selected playlist */ +.main-rootlist-rootlistItemLink.main-rootlist-rootlistItemLinkActive { + background: var(--spice-button); + border-radius: 4px; +} + +.main-navBar-navBarLinkActive { + background: var(--spice-button); +} + +.main-contextMenu-menu { + background-color: var(--spice-button); +} + +.main-contextMenu-menuHeading, +.main-contextMenu-menuItemButton, +.main-contextMenu-menuItemButton:not(.main-contextMenu-disabled):focus, +.main-contextMenu-menuItemButton:not(.main-contextMenu-disabled):hover { + color: var(--spice-main); +} + +.main-playPauseButton-button { + background-color: var(--spice-button); + color: white; +} + +/** Queue page header */ +.queue-queue-title, +.queue-playHistory-title { + color: var(--spice-text) !important; +} + +/** Artist page */ +.artist-artistOverview-heading { + color: var(--spice-text) !important; +} +.artist-artistAbout-content .artist-artistAbout-cityBlock div, +.artist-artistAbout-content .artist-artistAbout-stats div { + color: var(--spice-text) !important; +} +.artist-artistAbout-content div { + color: var(--spice-text) !important; +} + +/** Cards */ +.main-cardImage-imageWrapper { + background-color: transparent; + box-shadow: unset; + -webkit-box-shadow: unset; +} + +.main-cardImage-imagePlaceholder, .main-cardImage-image { + border-radius: var(--cover-border-radius); +} + +.main-rootlist-rootlistDivider { + background-color: unset; +} + +.main-nowPlayingBar-nowPlayingBar { + height: var(--bar-height); +} + +.Root__top-bar { + border-radius: var(--main-corner-radius) var(--main-corner-radius) 0 0; +} + +.main-topBar-background { + border-radius: var(--main-corner-radius) var(--main-corner-radius) 0 0; +} + +.Root__main-view { + background-color: var(--spice-main); + border-radius: var(--main-corner-radius) var(--main-corner-radius) 0 0; + overflow: hidden; +} + +.main-buddyFeed-buddyFeed { + box-shadow: unset; + -webkit-box-shadow: unset; + z-index: 0; +} + +.main-buddyFeed-headerTitle, +.main-buddyFeed-activityMetadata .main-buddyFeed-username a { + color: var(--spice-sidebar-text); +} + +.main-buddyFeed-activityMetadata .main-buddyFeed-artistAndTrackName a, +.main-buddyFeed-activityMetadata .main-buddyFeed-playbackContextLink, +.main-buddyFeed-activityMetadata .main-buddyFeed-timestamp { + color: rgba(var(--spice-rgb-sidebar-text), 0.8); +} + +.main-avatar-avatar, +.main-buddyFeed-overlay { + width: 32px !important; + height: 32px !important; +} + +.main-buddyFeed-avatarContainer { + padding-left: 4px; +} + +.main-avatar-avatar.main-avatar-withBadge:after { + box-shadow: 0 0 0 2px var(--spice-sidebar); + background-color: var(--spice-notification); + right: 0; +} + +.Root__now-playing-bar { + border-radius: 0 0 var(--main-corner-radius) var(--main-corner-radius); + background-color: unset; +} + +.main-nowPlayingBar-container { + border-radius: 0 0 var(--main-corner-radius) var(--main-corner-radius); + background-color: unset; + background: radial-gradient(ellipse at right 50% bottom -80px, rgba(var(--spice-rgb-button), 0.55), var(--spice-main) 60%); + border-top: 0; + min-width: 518px; +} + +.main-connectBar-connectBar { + border-radius: 0 0 var(--main-corner-radius) var(--main-corner-radius); + border: 2px solid var(--spice-main); + border-top: 0; +} + +@media(max-width:768px){ + /* .control-button{ + display: none; + } */ + .volume-bar { + flex: 0 1 40px; + } + .volume-bar .progress-bar-wrapper { + display: none; + } +} + +.Root__nav-bar { + height: 100%; + z-index: 1; + width: var(--sidebar-width) !important; +} + +.main-buddyFeed-buddyFeedRoot { + height: 100%; +} + +.main-buddyFeed-buddyFeedRoot .os-content { + padding-top: 0 !important; +} + +html, +.Root__nav-bar, +.main-buddyFeed-buddyFeed { + background-color: var(--spice-sidebar) !important; +} + +.Root__nav-bar .link-subtle, +.main-rootlist-rootlistItemLink:link, +.main-rootlist-rootlistItemLink:visited, +.main-rootlist-rootlistContent span, +.main-navBar-entryPoints span { + color: var(--spice-sidebar-text) +} + +.main-navBar-navBarItem svg { + width: 24px !important; + height: 24px !important; +} + +.main-navBar-navBarItem { + padding: 0 8px; +} + +.main-rootlist-statusIcons { + color: var(--spice-sidebar-text); + padding-right: 16px; +} + +.main-rootlist-statusIcons .main-playButton-button { + color: var(--spice-sidebar-text); +} + +.main-rootlist-expandArrow { + position: absolute; + top: 20px; + right: 4px; + width: 16px; + height: 16px; + color: var(--spice-sidebar-text) !important; + background-color: var(--spice-button); + border-radius: 50%; + box-shadow: 0 0 0 2px var(--spice-sidebar); + opacity: 0; +} + +li.GlueDropTarget:hover .main-rootlist-expandArrow { + opacity: 1; +} + +html:not(.sidebar-hide-text) .main-rootlist-expandArrow { + opacity: 1; +} + +.main-rootlist-expandArrow::before { + font-size: 10px; + padding-bottom: 3px; +} + +html.sidebar-hide-text .main-navBar-navBarItem span, +html.sidebar-hide-text .main-rootlist-rootlistContent span, +html.sidebar-hide-text .main-rootlist-rootlistItem span, +html.sidebar-hide-text .main-rootlist-statusIcons, +html.sidebar-hide-text .GlueDropTarget span { + display: none; +} + +.main-rootlist-rootlist { + margin-top: 0; +} + +.Root__nav-bar .os-scrollbar-vertical, +.main-buddyFeed-buddyFeedRoot .os-scrollbar-vertical { + display: none; +} + +/** */ +.main-topBar-historyButtons .main-topBar-button { + background-color: unset; + width: 24px; + height: 24px; +} + +.main-topBar-historyButtons svg { + color: var(--spice-button); + fill: var(--spice-button); +} + +.playback-bar__progress-time, +.main-playbackBarRemainingTime-container { + display: none; +} + +.playback-bar { + position: absolute; + width: var(--main-view-width); + left: var(--sidebar-width); + bottom: calc(var(--main-gap) + var(--bar-height) - 12px / 2); +} + +.Root.is-connectBarVisible .playback-bar { + bottom: calc(var(--main-gap) + var(--bar-height) + 24px - 12px / 2); +} + +.main-nowPlayingWidget-coverArt .cover-art { + width: var(--bar-cover-art-size) !important; + height: var(--bar-cover-art-size) !important; +} + +.player-controls__buttons { + margin-bottom: 0; +} + +.progress-bar { + --progress-bar-height: 2px; + --fg-color: var(--spice-button); + --bg-color: rgba(var(--spice-rgb-text), .2); +} + +.minimal-player .player-controls__buttons { + width: 120px; +} +.minimal-player .volume-bar { + flex: 0 1 70px; +} +.extra-minimal-player .main-shuffleButton-button, +.extra-minimal-player .main-repeatButton-button, +.extra-minimal-player .ExtraControls__connect-device-picker, +.extra-minimal-player .volume-bar .progress-bar-wrapper { + display: none; +} +.extra-minimal-player .volume-bar { + flex: 0 0 32px; +} + +.main-trackInfo-name { + font-weight: 500; +} + +.main-topBar-topbarContent .main-playButton-PlayButton { + --size: 35px !important; +} + +.main-entityHeader-image { + border-radius: 5px; +} + +.main-entityHeader-metaDataText, +.main-duration-container { + color: var(--spice-subtext); +} + +/** Sidebar */ +.main-rootlist-rootlist .os-content { + padding: 0 0 8px 0 !important; +} + +.main-rootlist-rootlistDividerContainer { + display: none; +} + +.main-rootlist-rootlistItem a { + align-items: center; + border-radius: 4px; + display: flex; + height: 56px; + padding: 0 12px; +} + +img.playlist-picture { + width: 32px; + height: 32px; + flex: 0 0 32px; + background-size: cover; + background-position: center; + border-radius: 50%; +} + +.main-rootlist-rootlistItem a span { + margin-left: 24px; +} + +.main-rootlist-rootlistItem { + padding-left: calc(var(--indentation)*var(--left-sidebar-item-indentation-width)); + padding-right: 0; +} + +html.sidebar-hide-text .main-rootlist-rootlistItem { + padding: 0; +} + +.main-rootlist-dropIndicator { + background: var(--spice-selected-row); + height: 2px; +} + +.main-navBar-navBarLink { + height: 56px; +} + +.main-navBar-navBarLink .icon, +.main-collectionLinkButton-icon, +.main-createPlaylistButton-icon, +.main-collectionLinkButton-icon { + margin-right: 24px; +} + +li.GlueDropTarget { + padding: 0 8px; +} + +/** OS-specific window controls dodge */ +.spotify__os--is-windows .main-navBar-navBar { + padding-top: calc(var(--os-windows-icon-dodge) * 24px); +} + +.spotify__container--is-desktop:not(.fullscreen).spotify__os--is-windows .main-navBar-entryPoints { + padding-top: calc(var(--os-windows-icon-dodge) * 12px + 12px); +} + +.spotify__os--is-windows .main-buddyFeed-header { + padding-top: calc(var(--os-windows-icon-dodge) * 32px); +} + +.spotify__container--is-desktop.spotify__os--is-windows[dir=ltr] .main-topBar-container { + padding-right: calc(var(--os-windows-icon-dodge) * 135px + 32px); +} + +.main-topBar-container { + max-width: unset; +} + +/** Custom elements */ +#dribbblish-sidebar-fade-in { + position: absolute; + bottom: 0; + width: 100%; + height: 20%; + background: linear-gradient(to top, var(--spice-sidebar) 10%, transparent); + z-index: 3; + pointer-events: none; +} +#dribs-playlist-list { + padding-bottom: 56px; +} +#dribbblish-back-shadow { + position: fixed; + width: var(--main-view-width); + height: calc(var(--main-view-height) + var(--bar-height)); + box-shadow: 0 0 10px 3px #0000003b; + border-radius: var(--main-corner-radius); + z-index: 2; + pointer-events: none; +} + +.playback-bar .prog-tooltip { + position: absolute; + min-width: 100px; + width: unset; + height: 25px; + top: -35px; + padding: 0 5px; + border-radius: 4px; + text-align: center; + color: var(--spice-text); + background-color: var(--spice-button); + opacity: 0; + transition: opacity,left 0.2s ease; +} + +.playback-bar:hover .prog-tooltip { + opacity: 1; +} + +/** Rearrange player bar */ +.main-shuffleButton-button { + order: 1; +} + +.main-nowPlayingBar-left { + order: 1; + flex: 1; + width: auto; + min-width: unset !important; +} + +.main-nowPlayingBar-center { + order: 0; + flex: 1; + width: auto; + min-width: unset !important; +} + +.main-nowPlayingBar-right { + order: 2; + flex: 1; + width: auto; + min-width: unset !important; +} + +.main-nowPlayingWidget-nowPlaying { + justify-content: center; +} + +.player-controls { + justify-content: flex-start; + flex-direction: row; +} + +.main-playPauseButton-button { + background-color: transparent; +} + +.main-playPauseButton-button svg { + width: 32px !important; + height: 32px !important; + color: var(--spice-button); +} + +/** Main container */ +.contentSpacing { + padding-left: 64px; + padding-right: 64px; +} + +@media (min-width: 1024px) { + .contentSpacing { + padding-left: 128px; + padding-right: 128px; + } +} + +.main-collectionLinkButton-collectionLinkButton .main-collectionLinkButton-icon, +.main-collectionLinkButton-collectionLinkButton .main-collectionLinkButton-collectionLinkText, +.main-createPlaylistButton-button { + opacity: 1; +} + +.main-likedSongsButton-likedSongsIcon, +.main-yourEpisodesButton-yourEpisodesIcon, +.main-createPlaylistButton-createPlaylistIcon { + background: unset !important; +} + +.main-createPlaylistButton-icon, +.main-collectionLinkButton-icon, +.main-createPlaylistButton-icon { + height: 40px; +} + +.main-likedSongsButton-likedSongsIcon svg, +.main-yourEpisodesButton-yourEpisodesIcon svg, +.main-createPlaylistButton-createPlaylistIcon svg { + fill: var(--spice-sidebar-text); + width: 32px; + height: 32px; +} +.main-yourEpisodesButton-yourEpisodesIcon svg path { + fill: var(--spice-sidebar-text); +} + +/** Grid */ +.Root__top-container { + grid-template-areas: + "nav-bar main-view buddy-feed" + "nav-bar now-playing-bar buddy-feed"; + padding: var(--main-gap) 0; +} + +html:not(.buddyfeed-visible) .Root__top-container { + padding-right: var(--main-gap); +} + +/** Minimal profile button */ +span.main-userWidget-displayName, +.main-userWidget-box svg { + display: none; +} + +/** Sidebar config */ +#dribs-hidden-list { + background-color: rgba(var(--spice-rgb-main), .3); +} + +#dribs-sidebar-config { + position: relative; + width: 100%; + height: 0; + display: flex; + justify-content: space-evenly; + align-items: center; + top: -30px; + left: 0; +} + +#dribs-sidebar-config button { + min-width: 60px; + border-radius: 3px; + background-color: var(--spice-main); + color: var(--spice-text); + border: 1px solid var(--spice-text); +} +#dribs-sidebar-config button:disabled { + color: var(--spice-button-disabled); +} + +.main-navBar-entryPoints { + --left-sidebar-padding-left: 24px; + --left-sidebar-padding-right: 24px; +} + +div.GlueDropTarget.personal-library { + padding: 0 8px; +} +div.GlueDropTarget.personal-library >* { + padding: 0 16px; + height: 56px; + border-radius: 4px; +} + +div.GlueDropTarget.personal-library >*.active { + background: var(--spice-button); +} + +/** Big cover, small cover */ +.main-coverSlotExpanded-container { + position: fixed; + z-index: 2; + width: 250px; + height: 250px; + bottom: calc(var(--main-gap) + var(--bar-height) + 10px); + left: calc(var(--sidebar-width) + 10px); +} + +.Root.is-connectBarVisible .main-coverSlotExpanded-container { + bottom: calc(var(--main-gap) + var(--bar-height) + 24px + 10px); +} + +html.right-expanded-cover .main-coverSlotExpanded-container { + right: calc(var(--main-gap) + 10px); + left: unset; +} + +html.right-expanded-cover.buddyfeed-visible .main-coverSlotExpanded-container { + right: calc(var(--main-gap) + var(--buddy-feed-width) + 10px); + left: unset; +} + +.main-coverSlotExpanded-container img { + border-radius: 4px; +} + +.cover-art { + border-radius: 4px; +} + +.main-nowPlayingWidget-coverExpanded .main-coverSlotCollapsed-container { + opacity: 0; +} + +.main-nowPlayingWidget-coverExpanded { + transform: translateX(-27px); +} \ No newline at end of file diff --git a/white.png b/white.png new file mode 100644 index 0000000..07d6db6 Binary files /dev/null and b/white.png differ