spicetify added
This commit is contained in:
parent
030529e98c
commit
a9eeb3517a
16 changed files with 6513 additions and 0 deletions
59
.config/spicetify/Extensions/adblock.js
Normal file
59
.config/spicetify/Extensions/adblock.js
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
//@ts-check
|
||||||
|
|
||||||
|
// NAME: adblock
|
||||||
|
// AUTHOR: CharlieS1103
|
||||||
|
// DESCRIPTION: Block all audio and UI ads on Spotify
|
||||||
|
|
||||||
|
/// <reference path="../../spicetify-cli/globals.d.ts" />
|
||||||
|
|
||||||
|
(function adblock() {
|
||||||
|
const { Platform} = Spicetify;
|
||||||
|
if (!(Platform)) {
|
||||||
|
setTimeout(adblock, 300)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var styleSheet = document.createElement("style")
|
||||||
|
|
||||||
|
styleSheet.innerHTML =
|
||||||
|
`
|
||||||
|
.MnW5SczTcbdFHxLZ_Z8j, .WiPggcPDzbwGxoxwLWFf, .ReyA3uE3K7oEz7PTTnAn, .main-leaderboardComponent-container, .sponsor-container, a.link-subtle.main-navBar-navBarLink.GKnnhbExo0U9l7Jz2rdc{
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
document.body.appendChild(styleSheet)
|
||||||
|
delayAds()
|
||||||
|
var billboard = Spicetify.Platform.AdManagers.billboard.displayBillboard;
|
||||||
|
Spicetify.Platform.AdManagers.billboard.displayBillboard = function (arguments) {
|
||||||
|
Spicetify.Platform.AdManagers.billboard.finish()
|
||||||
|
// hook before call
|
||||||
|
var ret = billboard.apply(this, arguments);
|
||||||
|
// hook after call
|
||||||
|
console.log("Adblock.js: Billboard blocked! Leave a star!")
|
||||||
|
Spicetify.Platform.AdManagers.billboard.finish()
|
||||||
|
const observer = new MutationObserver((mutations, obs) => {
|
||||||
|
const billboardAd = document.getElementById('view-billboard-ad');
|
||||||
|
if (billboardAd) {
|
||||||
|
Spicetify.Platform.AdManagers.billboard.finish()
|
||||||
|
obs.disconnect();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(document, {
|
||||||
|
childList: true,
|
||||||
|
subtree: true
|
||||||
|
});
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
function delayAds() {
|
||||||
|
console.log("Ads delayed: Adblock.js")
|
||||||
|
Spicetify.Platform.AdManagers.audio.audioApi.cosmosConnector.increaseStreamTime(-100000000000)
|
||||||
|
Spicetify.Platform.AdManagers.billboard.billboardApi.cosmosConnector.increaseStreamTime(-100000000000)
|
||||||
|
}
|
||||||
|
setInterval(delayAds, 720 *10000);
|
||||||
|
|
||||||
|
|
||||||
|
})()
|
||||||
|
|
||||||
|
|
39
.config/spicetify/Extensions/catppuccin-macchiato.js
Normal file
39
.config/spicetify/Extensions/catppuccin-macchiato.js
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// Color map
|
||||||
|
let colorPalette = {
|
||||||
|
rosewater: "#f4dbd6",
|
||||||
|
flamingo: "#f0c6c6",
|
||||||
|
pink: "#f5bde6",
|
||||||
|
maroon: "#ee99a0",
|
||||||
|
red: "#ed8796",
|
||||||
|
peach: "#f5a97f",
|
||||||
|
yellow: "#eed49f",
|
||||||
|
green: "#a6da95",
|
||||||
|
teal: "#8bd5ca",
|
||||||
|
blue: "#8aadf4",
|
||||||
|
sky: "#91d7e3",
|
||||||
|
lavender: "#b7bdf8",
|
||||||
|
white: "#d9e0ee"
|
||||||
|
}
|
||||||
|
|
||||||
|
// waitForElement borrowed from:
|
||||||
|
// https://github.com/morpheusthewhite/spicetify-themes/blob/master/Dribbblish/dribbblish.js
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the color label for a given hex color value
|
||||||
|
function getKeyByValue(object, value) {
|
||||||
|
return Object.keys(object).find(key => object[key] === value.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used to select matching equalizer-animated-COLOR.gif
|
||||||
|
waitForElement([".Root"], (root) => {
|
||||||
|
let spiceEq = getComputedStyle(document.querySelector(":root")).getPropertyValue("--spice-equalizer");
|
||||||
|
let eqColor = getKeyByValue(colorPalette, spiceEq);
|
||||||
|
root[0].classList.add(`catppuccin-eq-${eqColor}`);
|
||||||
|
});
|
654
.config/spicetify/Extensions/copyPlaylist.js
Normal file
654
.config/spicetify/Extensions/copyPlaylist.js
Normal file
|
@ -0,0 +1,654 @@
|
||||||
|
// NAME: Copy Playlists
|
||||||
|
// AUTHOR: einzigartigerName
|
||||||
|
// DESCRIPTION: copy/combine playlist/queue directly in Spotify
|
||||||
|
|
||||||
|
(function CopyPlaylist() {
|
||||||
|
|
||||||
|
const { CosmosAPI, BridgeAPI, LocalStorage, PlaybackControl, ContextMenu, URI } = Spicetify
|
||||||
|
if (!(CosmosAPI || BridgeAPI)) {
|
||||||
|
setTimeout(CopyPlaylist, 1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const STORAGE_KEY = "combine_buffer_spicetify"
|
||||||
|
const TOP_BTN_TOOLTIP = "Combine Playlists"
|
||||||
|
const MENU_BTN_CREATE_NEW = "Create Playlist"
|
||||||
|
const MENU_BTN_INSERT_BUFFER = "Copy to Buffer"
|
||||||
|
|
||||||
|
class PlaylistCollection {
|
||||||
|
constructor() {
|
||||||
|
const menu = createMenu()
|
||||||
|
this.container = menu.container
|
||||||
|
this.items = menu.menu
|
||||||
|
this.lastScroll = 0
|
||||||
|
this.container.onclick = () => {
|
||||||
|
this.storeScroll()
|
||||||
|
this.container.remove()
|
||||||
|
}
|
||||||
|
this.pattern
|
||||||
|
this.apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
apply() {
|
||||||
|
this.items.textContent = '' // Remove all childs
|
||||||
|
this.items.append(createMenuItem("Create Playlist", () => highjackCreateDialog(mergePlaylists(this.pattern))))
|
||||||
|
this.items.append(createMenuItem("Clear Buffer", () => LIST.clearStorage()))
|
||||||
|
|
||||||
|
const select = createPatternSelect(this.filter);
|
||||||
|
select.onchange = (event) => {
|
||||||
|
this.pattern = event.srcElement.selectedIndex;
|
||||||
|
}
|
||||||
|
this.items.append(select);
|
||||||
|
|
||||||
|
const collection = this.getStorage();
|
||||||
|
collection.forEach((item) => this.items.append(new CardContainer(item)))
|
||||||
|
}
|
||||||
|
|
||||||
|
getStorage() {
|
||||||
|
const storageRaw = LocalStorage.get(STORAGE_KEY);
|
||||||
|
let storage = [];
|
||||||
|
|
||||||
|
if (storageRaw) {
|
||||||
|
storage = JSON.parse(storageRaw);
|
||||||
|
} else {
|
||||||
|
LocalStorage.set(STORAGE_KEY, "[]")
|
||||||
|
}
|
||||||
|
|
||||||
|
return storage;
|
||||||
|
}
|
||||||
|
|
||||||
|
addToStorage(data) {
|
||||||
|
|
||||||
|
/** @type {Object[]} */
|
||||||
|
const storage = this.getStorage();
|
||||||
|
storage.push(data);
|
||||||
|
|
||||||
|
LocalStorage.set(STORAGE_KEY, JSON.stringify(storage));
|
||||||
|
this.apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
removeFromStorage(id) {
|
||||||
|
const storage = this.getStorage()
|
||||||
|
.filter(item => item.id !== id)
|
||||||
|
|
||||||
|
LocalStorage.set(STORAGE_KEY, JSON.stringify(storage));
|
||||||
|
this.apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
clearStorage() {
|
||||||
|
LocalStorage.set(STORAGE_KEY, "[]");
|
||||||
|
this.apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
moveItem(uri, direction) {
|
||||||
|
var storage = this.getStorage()
|
||||||
|
|
||||||
|
var from;
|
||||||
|
|
||||||
|
for (var i = 0; i < storage.length; i++) {
|
||||||
|
if (storage[i].uri === uri) {
|
||||||
|
from = i
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!from) { return }
|
||||||
|
|
||||||
|
var to = from + direction
|
||||||
|
if (to < 0 || to >= storage.length) { return }
|
||||||
|
|
||||||
|
var tmp = storage[from]
|
||||||
|
storage[from] = storage[to]
|
||||||
|
storage[to] = tmp
|
||||||
|
|
||||||
|
LocalStorage.set(STORAGE_KEY, JSON.stringify(storage));
|
||||||
|
this.apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
changePosition(x, y) {
|
||||||
|
this.items.style.left = x + "px"
|
||||||
|
this.items.style.top = y + 10 + "px"
|
||||||
|
}
|
||||||
|
|
||||||
|
storeScroll() {
|
||||||
|
this.lastScroll = this.items.scrollTop
|
||||||
|
}
|
||||||
|
|
||||||
|
setScroll() {
|
||||||
|
this.items.scrollTop = this.lastScroll
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Displays Stored Playlist
|
||||||
|
* {id, uri, name, tracks, imgUri, owner}
|
||||||
|
*/
|
||||||
|
class CardContainer extends HTMLElement {
|
||||||
|
constructor(info) {
|
||||||
|
super()
|
||||||
|
|
||||||
|
this.innerHTML = `
|
||||||
|
<div class="card card-horizontal card-type-album ${info.imgUri ? "" : "card-hidden-image"}" data-uri="${info.uri}" data-contextmenu="">
|
||||||
|
<div class="card-attention-highlight-box"></div>
|
||||||
|
<div class="card-horizontal-interior-wrapper">
|
||||||
|
${info.imgUri ? `
|
||||||
|
<div class="card-image-wrapper">
|
||||||
|
<div class="card-image-hit-area">
|
||||||
|
<a class="card-image-link" link="${info.uri}">
|
||||||
|
<div class="card-hit-area-counter-scale-left"></div>
|
||||||
|
<div class="card-image-content-wrapper">
|
||||||
|
<div class="card-image" style="background-image: url('${info.imgUri}')"></div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<div class="card-overlay"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
` : ""}
|
||||||
|
<div class="card-info-wrapper">
|
||||||
|
<div class="order-controls">
|
||||||
|
<div class="order-controls-up">
|
||||||
|
<button class="button button-green button-icon-only spoticon-chevron-up-16" data-tooltip="Move Up"></button>
|
||||||
|
</div>
|
||||||
|
<div class="order-controls-remove">
|
||||||
|
<button class="button button-green button-icon-only spoticon-x-16" data-tooltip="Remove"></button>
|
||||||
|
</div>
|
||||||
|
<div class="order-controls-down">
|
||||||
|
<button class="button button-green button-icon-only spoticon-chevron-down-16" data-tooltip="Move Down"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a class="card-info-link" ${info.uri}>
|
||||||
|
<div class="card-info-content-wrapper">
|
||||||
|
<div class="card-info-title"><span class="card-info-title-text">${info.name}</span></div>
|
||||||
|
<div class="card-info-subtitle-owner"><span>${info.owner}</span></div>
|
||||||
|
<div class="card-info-subtitle-tracks"><span>${info.tracks.length === 1 ? "1 Track" : `${info.tracks.length} Tracks`}</span></div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
|
||||||
|
const up = this.querySelector(".order-controls-up")
|
||||||
|
up.onclick = (event) => {
|
||||||
|
LIST.moveItem(info.uri, -1)
|
||||||
|
event.stopPropagation()
|
||||||
|
}
|
||||||
|
|
||||||
|
const remove = this.querySelector(".order-controls-remove")
|
||||||
|
remove.onclick = (event) => {
|
||||||
|
LIST.removeFromStorage(info.id)
|
||||||
|
event.stopPropagation()
|
||||||
|
}
|
||||||
|
|
||||||
|
const down = this.querySelector(".order-controls-down")
|
||||||
|
down.onclick = (event) => {
|
||||||
|
LIST.moveItem(info.uri, +1)
|
||||||
|
event.stopPropagation()
|
||||||
|
}
|
||||||
|
|
||||||
|
const imageLink = this.querySelector(".card-image-link");
|
||||||
|
const infoLink = this.querySelector(".card-info-link");
|
||||||
|
|
||||||
|
if (imageLink) imageLink.addEventListener("click", ((e) => showPlaylist(e)));
|
||||||
|
|
||||||
|
if (infoLink) infoLink.addEventListener("click", ((e) => showPlaylist(e)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("combine-buffer-card-container", CardContainer)
|
||||||
|
|
||||||
|
const LIST = new PlaylistCollection()
|
||||||
|
|
||||||
|
// New Playlist Button
|
||||||
|
const playlistDialogButton = document.querySelector("#new-playlist-button-mount-point > div > button")
|
||||||
|
if (!playlistDialogButton) return;
|
||||||
|
|
||||||
|
document.querySelector("#view-browser-navigation-top-bar")
|
||||||
|
.append(createTopBarButton())
|
||||||
|
|
||||||
|
createPlaylistContextMenu().register()
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
UI Building
|
||||||
|
**************************************************************************/
|
||||||
|
// If Queue Page add Buttons
|
||||||
|
const iframeInterval = setInterval(() => {
|
||||||
|
/** @type {HTMLIFrameElement} */
|
||||||
|
const currentIframe = document.querySelector("iframe.active");
|
||||||
|
if (!currentIframe ||
|
||||||
|
currentIframe.id !== "app-queue"
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const headers = currentIframe.contentDocument.querySelectorAll(
|
||||||
|
".glue-page-header__buttons"
|
||||||
|
);
|
||||||
|
|
||||||
|
for (const e of headers) {
|
||||||
|
e.append(createQueueButton(
|
||||||
|
"Save as Playlist",
|
||||||
|
"Save the current Queue as a new Playlist",
|
||||||
|
() => {
|
||||||
|
let tracks = getQueueTracks();
|
||||||
|
highjackCreateDialog(tracks);
|
||||||
|
},
|
||||||
|
));
|
||||||
|
|
||||||
|
e.append(createQueueButton(
|
||||||
|
"Copy into Buffer",
|
||||||
|
"Insert the current Queue into the Buffer",
|
||||||
|
() => { queueToBuffer() },
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headers.length > 0) clearInterval(iframeInterval);
|
||||||
|
}, 500)
|
||||||
|
|
||||||
|
// Creates the Main Menu
|
||||||
|
function createMenu() {
|
||||||
|
const container = document.createElement("div")
|
||||||
|
container.id = "combine-playlist-spicetify"
|
||||||
|
container.className = "context-menu-container"
|
||||||
|
container.style.zIndex = "1029"
|
||||||
|
|
||||||
|
const style = document.createElement("style")
|
||||||
|
style.textContent = `
|
||||||
|
#combine-menu {
|
||||||
|
display: inline-block;
|
||||||
|
width: 33%;
|
||||||
|
max-height: 70%;
|
||||||
|
overflow: hidden auto;
|
||||||
|
padding: 10px
|
||||||
|
}
|
||||||
|
.combine-pattern {
|
||||||
|
margin-top: 7px;
|
||||||
|
}
|
||||||
|
.order-controls {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
padding: 0 5px 5px 0;
|
||||||
|
z-index: 3
|
||||||
|
}
|
||||||
|
.button.button-icon-only::before {
|
||||||
|
color: var(--modspotify_main_fg);
|
||||||
|
}
|
||||||
|
.order-controls-up {
|
||||||
|
position: relative;
|
||||||
|
top: 100%;
|
||||||
|
}
|
||||||
|
.order-controls-remove {
|
||||||
|
position: relative;
|
||||||
|
top: 50%;
|
||||||
|
}
|
||||||
|
.order-controls-down {
|
||||||
|
position: relative;
|
||||||
|
bottom: 100%;
|
||||||
|
}
|
||||||
|
.card-info-subtitle-owner {
|
||||||
|
color: var(--modspotify_secondary_fg);
|
||||||
|
}
|
||||||
|
.card-info-subtitle-tracks {
|
||||||
|
font-weight: lighter;
|
||||||
|
color: var(--modspotify_secondary_fg);
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const menu = document.createElement("ul")
|
||||||
|
menu.id = "combine-menu"
|
||||||
|
menu.className = "context-menu"
|
||||||
|
|
||||||
|
container.append(style, menu)
|
||||||
|
|
||||||
|
return { container, menu }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a Button in the Combine Menu
|
||||||
|
function createMenuItem(name, callback) {
|
||||||
|
const item = document.createElement("div");
|
||||||
|
item.classList.add("item");
|
||||||
|
item.onclick = callback;
|
||||||
|
item.onmouseover = () => item.classList.add("hover");
|
||||||
|
item.onmouseleave = () => item.classList.remove("hover");
|
||||||
|
|
||||||
|
const text = document.createElement("span");
|
||||||
|
text.classList.add("text");
|
||||||
|
text.innerText = name;
|
||||||
|
|
||||||
|
item.append(text);
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates the SubMenu in Playlist Context
|
||||||
|
function createPlaylistContextMenu() {
|
||||||
|
var createFromCurrent = new Spicetify.ContextMenu.Item(
|
||||||
|
MENU_BTN_CREATE_NEW,
|
||||||
|
(uris) => {
|
||||||
|
if (uris.length === 1) {
|
||||||
|
fetchPlaylist(uris[0])
|
||||||
|
.then((buffer) => highjackCreateDialog(buffer.tracks))
|
||||||
|
.catch((err) => Spicetify.showNotification(`${err}`));
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
Spicetify.showNotification("Unable to find Playlist URI")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(_) => true
|
||||||
|
)
|
||||||
|
|
||||||
|
var insertIntoBuffer = new Spicetify.ContextMenu.Item(
|
||||||
|
MENU_BTN_INSERT_BUFFER,
|
||||||
|
(uris) => {
|
||||||
|
|
||||||
|
if (uris.length === 1) {
|
||||||
|
fetchPlaylist(uris[0])
|
||||||
|
.then((buffer) => {LIST.addToStorage(buffer)})
|
||||||
|
.catch((err) => Spicetify.showNotification(`${err}`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(_) => true
|
||||||
|
)
|
||||||
|
|
||||||
|
return new Spicetify.ContextMenu.SubMenu(
|
||||||
|
"Copy Playlist",
|
||||||
|
[ createFromCurrent, insertIntoBuffer],
|
||||||
|
(uris) => {
|
||||||
|
if (uris.length === 1) {
|
||||||
|
const uriObj = Spicetify.URI.fromString(uris[0]);
|
||||||
|
switch (uriObj.type) {
|
||||||
|
case Spicetify.URI.Type.PLAYLIST:
|
||||||
|
case Spicetify.URI.Type.PLAYLIST_V2:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Multiple Items selected.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates the Button to View Merge Buffer
|
||||||
|
function createTopBarButton() {
|
||||||
|
const button = document.createElement("button")
|
||||||
|
button.classList.add("button", "spoticon-copy-16", "merge-button")
|
||||||
|
button.setAttribute("data-tooltip", TOP_BTN_TOOLTIP)
|
||||||
|
button.setAttribute("data-contextmenu", "")
|
||||||
|
button.setAttribute("data-uri", "spotify:special:copy")
|
||||||
|
button.onclick = () => {
|
||||||
|
const bound = button.getBoundingClientRect()
|
||||||
|
LIST.changePosition(bound.left, bound.top)
|
||||||
|
document.body.append(LIST.container)
|
||||||
|
LIST.setScroll()
|
||||||
|
}
|
||||||
|
return button
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates the Dropdown Menu for Merge Pattern
|
||||||
|
function createPatternSelect(defaultOpt = 0) {
|
||||||
|
const select = document.createElement("select");
|
||||||
|
select.className = "GlueDropdown combine-pattern";
|
||||||
|
|
||||||
|
const appendOpt = document.createElement("option");
|
||||||
|
appendOpt.text = "Append";
|
||||||
|
|
||||||
|
const shuffleOpt = document.createElement("option");
|
||||||
|
shuffleOpt.text = "Shuffle";
|
||||||
|
|
||||||
|
const alternateOpt = document.createElement("option");
|
||||||
|
alternateOpt.text = "Alternate";
|
||||||
|
|
||||||
|
select.onclick = (ev) => ev.stopPropagation();
|
||||||
|
select.append(appendOpt, shuffleOpt, alternateOpt);
|
||||||
|
select.options[defaultOpt].selected = true;
|
||||||
|
|
||||||
|
return select;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Queue button
|
||||||
|
function createQueueButton(name, tooltip, callback) {
|
||||||
|
const b = document.createElement("button");
|
||||||
|
b.classList.add("button", "button-green");
|
||||||
|
b.innerText = name;
|
||||||
|
b.setAttribute("data-tooltip", tooltip);
|
||||||
|
b.onclick = callback;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Highjack Spotifies 'New Playlist' Dialog
|
||||||
|
function highjackCreateDialog(tracks) {
|
||||||
|
playlistDialogButton.click()
|
||||||
|
|
||||||
|
var createButton = document.querySelector("body > div.Modal__portal > div > div > div > div.PlaylistAnnotationModal__submit-button-container > button")
|
||||||
|
var buttonContainer = document.querySelector("body > div.Modal__portal > div > div > div > div.PlaylistAnnotationModal__submit-button-container")
|
||||||
|
|
||||||
|
var highjackedButton = createButton.cloneNode(true)
|
||||||
|
highjackedButton.addEventListener("click", () => onCreateNewPlaylist(tracks))
|
||||||
|
|
||||||
|
window.addEventListener("keypress", (event) => {
|
||||||
|
if (event.code === `Enter`) {
|
||||||
|
// Cancel the default action, if needed
|
||||||
|
event.preventDefault();
|
||||||
|
// Trigger the button element with a click
|
||||||
|
createButton.click();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
createButton.remove()
|
||||||
|
buttonContainer.insertAdjacentElement("afterbegin", highjackedButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
OnCLick Functions
|
||||||
|
**************************************************************************/
|
||||||
|
// Create a new Playlist from Inputs
|
||||||
|
function onCreateNewPlaylist(tracks) {
|
||||||
|
var exitButton = document.querySelector("body > div.Modal__portal > div > div > div > div.PlaylistAnnotationModal__close-button > button");
|
||||||
|
var nameInput = document.querySelector("body > div.Modal__portal > div > div > div > div.PlaylistAnnotationModal__content > div.PlaylistAnnotationModal__playlist-name > input")
|
||||||
|
var descInput = document.querySelector("body > div.Modal__portal > div > div > div > div.PlaylistAnnotationModal__content > div.PlaylistAnnotationModal__playlist-description > textarea")
|
||||||
|
var imageInput = document.querySelector("body > div.Modal__portal > div > div > div > div.PlaylistAnnotationModal__content > div.PlaylistAnnotationModal__img-container > div > div.PlaylistAnnotationModal__img-holder > img")
|
||||||
|
|
||||||
|
var name = nameInput.value
|
||||||
|
if (!name) {
|
||||||
|
name = nameInput.getAttribute("placeholder")
|
||||||
|
}
|
||||||
|
|
||||||
|
var desc = descInput.value
|
||||||
|
|
||||||
|
var img;
|
||||||
|
if (imageInput) {
|
||||||
|
img = imageInput.getAttribute("src")
|
||||||
|
}
|
||||||
|
|
||||||
|
createPlaylist(name)
|
||||||
|
.then(res => addTracks(res.uri, tracks))
|
||||||
|
.then((_) => Spicetify.showNotification(`Created Playlist: "${name}"`))
|
||||||
|
.catch((err) => Spicetify.showNotification(`${err}`));
|
||||||
|
|
||||||
|
exitButton.click()
|
||||||
|
|
||||||
|
if (exitButton) {
|
||||||
|
exitButton.click()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get All Tracks in Queue and remove delimiter
|
||||||
|
function getQueueTracks() {
|
||||||
|
return Spicetify.Queue.next_tracks
|
||||||
|
.map((t) => t.uri)
|
||||||
|
.filter((t) => { return t != "spotify:delimiter"; })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the Queue to the Combine Buffer
|
||||||
|
function queueToBuffer() {
|
||||||
|
let tracks = getQueueTracks();
|
||||||
|
|
||||||
|
var date = new Date()
|
||||||
|
var year = new Intl.DateTimeFormat('en', { year: 'numeric' }).format(date);
|
||||||
|
var month = new Intl.DateTimeFormat('en', { month: 'short' }).format(date);
|
||||||
|
var day = new Intl.DateTimeFormat('en', { day: '2-digit' }).format(date);
|
||||||
|
|
||||||
|
const timeOptions = { hour: 'numeric', minute: 'numeric', hour12: false};
|
||||||
|
var time = new Intl.DateTimeFormat(`en`, timeOptions).format(date);
|
||||||
|
|
||||||
|
let queue = {
|
||||||
|
id: `spotify:queue-${date}`,
|
||||||
|
uri: `spotify:queue`,
|
||||||
|
name: "Queue",
|
||||||
|
imgUri: undefined,
|
||||||
|
tracks: tracks,
|
||||||
|
owner: `${time} - ${day} ${month} ${year}`,
|
||||||
|
}
|
||||||
|
|
||||||
|
LIST.addToStorage(queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the clicked Playlist
|
||||||
|
async function showPlaylist(event) {
|
||||||
|
console.log(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
Merge Playlists
|
||||||
|
**************************************************************************/
|
||||||
|
// Merge all Playlists
|
||||||
|
function mergePlaylists(pattern) {
|
||||||
|
var tracks = LIST.getStorage().map((pl) => pl.tracks)
|
||||||
|
|
||||||
|
switch (pattern) {
|
||||||
|
case 1: return shuffle(tracks);
|
||||||
|
case 2: return alternate(tracks);
|
||||||
|
default: return append(tracks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alternate Playlists
|
||||||
|
function alternate(arrays) {
|
||||||
|
var combined = []
|
||||||
|
|
||||||
|
while (arrays.length != 0) {
|
||||||
|
var current = arrays.shift()
|
||||||
|
if (current.length != 0) {
|
||||||
|
combined.push(current.shift())
|
||||||
|
|
||||||
|
if (current.length != 0) {
|
||||||
|
arrays.push(current)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return combined
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shuffle all tracks using the Durstenfeld Shuffle
|
||||||
|
function shuffle(arrays) {
|
||||||
|
var combined = append(arrays)
|
||||||
|
|
||||||
|
for (var i = combined.length - 1; i > 0; i--) {
|
||||||
|
var j = Math.floor(Math.random() * (i + 1));
|
||||||
|
var temp = combined[i];
|
||||||
|
combined[i] = combined[j];
|
||||||
|
combined[j] = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return combined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simply Concat all Playlist
|
||||||
|
function append(arrays) {
|
||||||
|
var combined = []
|
||||||
|
arrays.forEach((arr) => combined = combined.concat(arr))
|
||||||
|
|
||||||
|
return combined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
Calls to the CosmosAPI
|
||||||
|
**************************************************************************/
|
||||||
|
// Fetch all Track from Playlist URI
|
||||||
|
async function fetchPlaylist(uri) {
|
||||||
|
return await new Promise((resolve, reject) => {
|
||||||
|
Spicetify.BridgeAPI.cosmosJSON(
|
||||||
|
{
|
||||||
|
method: "GET",
|
||||||
|
uri: `sp://core-playlist/v1/playlist/${uri}/`,
|
||||||
|
body: {
|
||||||
|
policy: {
|
||||||
|
link: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
(error, res) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let id = `${uri}-${new Date()}`
|
||||||
|
let tracks = res.items.map((track) => track.link)
|
||||||
|
let img = res.playlist.picture
|
||||||
|
let name = res.playlist.name
|
||||||
|
let owner = res.playlist.owner.name
|
||||||
|
|
||||||
|
let playlist = {id: id, uri: uri, name: name, tracks: tracks, imgUri: img, owner: owner}
|
||||||
|
|
||||||
|
resolve(playlist);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new Playlist
|
||||||
|
async function createPlaylist(name) {
|
||||||
|
return await new Promise((resolve, reject) => {
|
||||||
|
Spicetify.BridgeAPI.cosmosJSON(
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
uri: `sp://core-playlist/v1/rootlist`,
|
||||||
|
body: {
|
||||||
|
operation: "create",
|
||||||
|
playlist: !0,
|
||||||
|
before: "start",
|
||||||
|
name: name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
(error, res) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(res);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// add track list to playlist
|
||||||
|
async function addTracks(uri, tracks) {
|
||||||
|
return await new Promise((resolve, reject) => {
|
||||||
|
Spicetify.BridgeAPI.cosmosJSON(
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
uri: `sp://core-playlist/v1/playlist/${uri}`,
|
||||||
|
body: {
|
||||||
|
operation: "add",
|
||||||
|
uris: tracks,
|
||||||
|
after: "end"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
(error, res) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(res);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})();
|
3087
.config/spicetify/Extensions/fullScreen.js
Normal file
3087
.config/spicetify/Extensions/fullScreen.js
Normal file
File diff suppressed because it is too large
Load diff
125
.config/spicetify/Extensions/genre.js
Normal file
125
.config/spicetify/Extensions/genre.js
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
// <reference path="./globals.d.ts" />
|
||||||
|
|
||||||
|
(function Genre() {
|
||||||
|
const { CosmosAsync, Player } = Spicetify;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch genre from artist
|
||||||
|
*
|
||||||
|
* @param artistURI {string}
|
||||||
|
* @return {Promise<Array>}
|
||||||
|
*/
|
||||||
|
const fetchGenres = async (artistURI) => {
|
||||||
|
const res = await CosmosAsync.get(
|
||||||
|
`https://api.spotify.com/v1/artists/${artistURI}`
|
||||||
|
);
|
||||||
|
// noinspection JSUnresolvedVariable
|
||||||
|
return res.genres.slice(0, 3) // Only keep the first 3 genres
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch playlist from The Sound of Spotify for a given genre
|
||||||
|
* @param {String} genre
|
||||||
|
* @return {String|null}
|
||||||
|
*/
|
||||||
|
const fetchSoundOfSpotifyPlaylist = async (genre) => {
|
||||||
|
const query = encodeURIComponent(`The Sound of ${genre}`);
|
||||||
|
// Check localStorage for playlist
|
||||||
|
const cached = localStorage.getItem(`everynoise:${query}`);
|
||||||
|
if (cached !== null) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for playlist and check results for the everynoise account
|
||||||
|
const re = new RegExp(`^the sound of ${genre.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}$`, 'i');
|
||||||
|
const res = await CosmosAsync.get(`https://api.spotify.com/v1/search?q=${query}&type=playlist`)
|
||||||
|
for (const item of res.playlists.items) {
|
||||||
|
if (item.owner.id === "thesoundsofspotify" && re.test(item.name)) {
|
||||||
|
localStorage.setItem(`everynoise:${genre}`, item.uri);
|
||||||
|
return item.uri
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Store the current playback id
|
||||||
|
let playback = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @type {Node}
|
||||||
|
*/
|
||||||
|
let genreContainer = null;
|
||||||
|
|
||||||
|
let infoContainer = document.querySelector('div.main-trackInfo-container');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove genre injection in the UI
|
||||||
|
*/
|
||||||
|
const cleanInjection = () => {
|
||||||
|
if (genreContainer !== null) {
|
||||||
|
try {
|
||||||
|
infoContainer.removeChild(genreContainer);
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject genres to UI
|
||||||
|
*/
|
||||||
|
const inject = () => {
|
||||||
|
Player.addEventListener('onprogress', async () => {
|
||||||
|
if (Player.data.track.metadata.hasOwnProperty('artist_uri')) {
|
||||||
|
// If the registered song isn't the same as the one currently being played then fetch genres
|
||||||
|
if (playback !== Player.data.playback_id) {
|
||||||
|
// Save the new track
|
||||||
|
playback = Player.data.playback_id;
|
||||||
|
const id = Player.data.track.metadata.artist_uri.split(':')[2];
|
||||||
|
const genres = await fetchGenres(id);
|
||||||
|
|
||||||
|
cleanInjection();
|
||||||
|
|
||||||
|
genreContainer = document.createElement('div');
|
||||||
|
// noinspection JSUndefinedPropertyAssignment
|
||||||
|
genreContainer.className = 'main-trackInfo-genres ellipsis-one-line main-type-finale';
|
||||||
|
// noinspection JSUnresolvedVariable
|
||||||
|
genreContainer.style.color = 'var(--spice-extratext)';
|
||||||
|
|
||||||
|
for (const i in genres) {
|
||||||
|
let element;
|
||||||
|
const uri = await fetchSoundOfSpotifyPlaylist(genres[i]);
|
||||||
|
if (uri !== null) {
|
||||||
|
element = document.createElement('a');
|
||||||
|
element.innerHTML = genres[i];
|
||||||
|
element.href = uri;
|
||||||
|
} else {
|
||||||
|
element = document.createElement('span');
|
||||||
|
}
|
||||||
|
element.innerHTML = genres[i];
|
||||||
|
element.style.fontSize ="11px";
|
||||||
|
genreContainer.appendChild(element);
|
||||||
|
if (i < genres.length-1) {
|
||||||
|
const separator = document.createElement('span');
|
||||||
|
separator.innerHTML = ', ';
|
||||||
|
genreContainer.appendChild(separator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
infoContainer = document.querySelector('div.main-trackInfo-container');
|
||||||
|
if(!infoContainer) cleanInjection();
|
||||||
|
infoContainer.appendChild(genreContainer);
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cleanInjection();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!CosmosAsync) {
|
||||||
|
setTimeout(Genre, 500);
|
||||||
|
} else {
|
||||||
|
inject();
|
||||||
|
}
|
||||||
|
})();
|
5
.config/spicetify/Extensions/hidePodcasts.js
Normal file
5
.config/spicetify/Extensions/hidePodcasts.js
Normal file
File diff suppressed because one or more lines are too long
127
.config/spicetify/Extensions/historyShortcut.js
Normal file
127
.config/spicetify/Extensions/historyShortcut.js
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
// NAME: History Shortcut
|
||||||
|
// AUTHOR: einzigartigerName
|
||||||
|
// DESCRIPTION: Adds a Shortcut to your Listening History to the Sidebar
|
||||||
|
|
||||||
|
(function HistoryShortcut() {
|
||||||
|
|
||||||
|
const { CosmosAPI, Player, LocalStorage, PlaybackControl, ContextMenu, URI } = Spicetify
|
||||||
|
if (!(CosmosAPI && Player && LocalStorage && PlaybackControl && ContextMenu && URI)) {
|
||||||
|
setTimeout(HistoryShortcut, 300)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const ITEM_LABEL = "History"
|
||||||
|
|
||||||
|
const HISTORY_DIV_CLASS = "SidebarListItem"
|
||||||
|
const HISTORY_DIV_CLASS_ACTIVE = "SidebarListItem SidebarListItem--is-active"
|
||||||
|
|
||||||
|
const HISTORY_ANKER_CLASS = "SidebarListItemLink SidebarListItemLink--tall spoticon-time-24"
|
||||||
|
const HISTORY_ANKER_CLASS_ACTIVE = "SidebarListItemLink SidebarListItemLink--is-highlighted SidebarListItemLink--tall spoticon-time-24"
|
||||||
|
|
||||||
|
let historyItem = createHistoyItem()
|
||||||
|
// Get Sidebar Lists
|
||||||
|
var topicList = document.querySelector("#view-navigation-bar > div > div.LeftSidebar__section > div > ul")
|
||||||
|
if (topicList) {
|
||||||
|
// Add to first in list
|
||||||
|
// On default layout this would be the Home/Browse/Radio List
|
||||||
|
topicList.appendChild(historyItem.div)
|
||||||
|
} else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const toCheckMutate = document.getElementById('view-content');
|
||||||
|
const config = { attributes: true, childList: true, subtree: true };
|
||||||
|
|
||||||
|
let observerCallback = function(_, _) {
|
||||||
|
appQueue = document.getElementById("app-queue")
|
||||||
|
if (!appQueue){ return }
|
||||||
|
|
||||||
|
if (appQueue.getAttribute("class") === "active"
|
||||||
|
&& appQueue.getAttribute("data-app-uri") === "spotify:app:queue:history"
|
||||||
|
) {
|
||||||
|
onClickHistory()
|
||||||
|
} else {
|
||||||
|
onLeaveHistory()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let observer = new MutationObserver(observerCallback)
|
||||||
|
observer.observe(toCheckMutate, config)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Deactivate Active Status for History Item
|
||||||
|
function onLeaveHistory() {
|
||||||
|
historyItem.div.setAttribute("class",HISTORY_DIV_CLASS)
|
||||||
|
historyItem.anker.setAttribute("class", HISTORY_ANKER_CLASS)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Activate Active Status for History Item
|
||||||
|
function onClickHistory() {
|
||||||
|
historyItem.div.setAttribute("class", HISTORY_DIV_CLASS_ACTIVE)
|
||||||
|
historyItem.anker.setAttribute("class", HISTORY_ANKER_CLASS_ACTIVE)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the List Item
|
||||||
|
function createHistoyItem() {
|
||||||
|
/* List Item
|
||||||
|
* <li class="SidebarListItem">
|
||||||
|
*/
|
||||||
|
let listItem = document.createElement("li")
|
||||||
|
listItem.setAttribute("class", HISTORY_DIV_CLASS)
|
||||||
|
|
||||||
|
/* Outer Div Element
|
||||||
|
* <div class="DropTarget SidebarListItem__drop-target DropTarget--tracks DropTarget--albums DropTarget--artists DropTarget--playlists">
|
||||||
|
*/
|
||||||
|
let outer = document.createElement("div")
|
||||||
|
outer.setAttribute("class", "DropTarget SidebarListItem__drop-target")
|
||||||
|
|
||||||
|
/* Middle Div Element
|
||||||
|
* <div class="SidebarListItem__inner">
|
||||||
|
*/
|
||||||
|
let inner = document.createElement("div")
|
||||||
|
inner.setAttribute("class", "SidebarListItem__inner")
|
||||||
|
|
||||||
|
/* Link Div Element
|
||||||
|
* <div class="SidebarListItem__link">
|
||||||
|
*/
|
||||||
|
let link = document.createElement("div")
|
||||||
|
link.setAttribute("class", "SidebarListItem__link")
|
||||||
|
|
||||||
|
/* Anker
|
||||||
|
* <a class="SidebarListItemLink SidebarListItemLink--tall spoticon-time-24"
|
||||||
|
* draggable="false"
|
||||||
|
* href="spotify:app:queue:history"
|
||||||
|
* data-sidebar-list-item-uri="spotify:app:queue:history"
|
||||||
|
* data-ta-id="sidebar-list-item-link">
|
||||||
|
*/
|
||||||
|
anker = document.createElement("a")
|
||||||
|
anker.setAttribute("class", HISTORY_ANKER_CLASS)
|
||||||
|
anker.setAttribute("draggable", "false")
|
||||||
|
anker.setAttribute("href", "spotify:app:queue:history")
|
||||||
|
anker.setAttribute("data-sidebar-list-item-uri", "spotify:app:queue:history")
|
||||||
|
anker.setAttribute("data-ta-id", "sidebar-list-item-link")
|
||||||
|
|
||||||
|
/* Item Text
|
||||||
|
* <span class="SidebarListItem__label"
|
||||||
|
* dir="auto">
|
||||||
|
* History
|
||||||
|
* </span>
|
||||||
|
*/
|
||||||
|
span = document.createElement("span")
|
||||||
|
span.setAttribute("class", "SidebarListItem__label")
|
||||||
|
span.setAttribute("dir", "auto")
|
||||||
|
span.textContent = ITEM_LABEL
|
||||||
|
|
||||||
|
|
||||||
|
anker.appendChild(span)
|
||||||
|
link.appendChild(anker)
|
||||||
|
inner.appendChild(link)
|
||||||
|
outer.appendChild(inner)
|
||||||
|
listItem.appendChild(outer)
|
||||||
|
|
||||||
|
listItem.addEventListener("click", onClickHistory)
|
||||||
|
|
||||||
|
return {div: listItem, anker: anker}
|
||||||
|
}
|
||||||
|
})();
|
532
.config/spicetify/Extensions/keyboardShortcutMy.js
Normal file
532
.config/spicetify/Extensions/keyboardShortcutMy.js
Normal file
|
@ -0,0 +1,532 @@
|
||||||
|
//@ts-check
|
||||||
|
|
||||||
|
// NAME: Keyboard Shortcut
|
||||||
|
// AUTHOR: dax
|
||||||
|
// DESCRIPTION: Register a few more keybinds to support keyboard-driven navigation in Spotify client.
|
||||||
|
|
||||||
|
/// <reference path="../spicetify-cli/globals.d.ts" />
|
||||||
|
|
||||||
|
(function KeyboardShortcutMy() {
|
||||||
|
if (!Spicetify.Keyboard) {
|
||||||
|
setTimeout(KeyboardShortcutMy, 1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SCROLL_STEP = 50;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register your own keybind with function `registerBind`
|
||||||
|
*
|
||||||
|
* Syntax:
|
||||||
|
* registerBind(keyName, ctrl, shift, alt, callback)
|
||||||
|
*
|
||||||
|
* ctrl, shift and alt are boolean, true or false
|
||||||
|
*
|
||||||
|
* Valid keyName:
|
||||||
|
* - BACKSPACE - C - Y - F3
|
||||||
|
* - TAB - D - Z - F4
|
||||||
|
* - ENTER - E - WINDOW_LEFT - F5
|
||||||
|
* - SHIFT - F - WINDOW_RIGHT - F6
|
||||||
|
* - CTRL - G - SELECT - F7
|
||||||
|
* - ALT - H - NUMPAD_0 - F8
|
||||||
|
* - PAUSE/BREAK - I - NUMPAD_1 - F9
|
||||||
|
* - CAPS - J - NUMPAD_2 - F10
|
||||||
|
* - ESCAPE - K - NUMPAD_3 - F11
|
||||||
|
* - SPACE - L - NUMPAD_4 - F12
|
||||||
|
* - PAGE_UP - M - NUMPAD_5 - NUM_LOCK
|
||||||
|
* - PAGE_DOWN - N - NUMPAD_6 - SCROLL_LOCK
|
||||||
|
* - END - O - NUMPAD_7 - ;
|
||||||
|
* - HOME - P - NUMPAD_8 - =
|
||||||
|
* - ARROW_LEFT - Q - NUMPAD_9 - ,
|
||||||
|
* - ARROW_UP - R - MULTIPLY - -
|
||||||
|
* - ARROW_RIGHT - S - ADD - /
|
||||||
|
* - ARROW_DOWN - T - SUBTRACT - `
|
||||||
|
* - INSERT - U - DECIMAL_POINT - [
|
||||||
|
* - DELETE - V - DIVIDE - \
|
||||||
|
* - A - W - F1 - ]
|
||||||
|
* - B - X - F2 - "
|
||||||
|
*
|
||||||
|
* Use one of keyName as a string. If key that you want isn't in that list,
|
||||||
|
* you can also put its keycode number in keyName as a number.
|
||||||
|
*
|
||||||
|
* callback is name of function you want your shortcut to bind to. It also
|
||||||
|
* returns one KeyboardEvent parameter.
|
||||||
|
*
|
||||||
|
* Following are my default keybinds, use them as examples.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//My Personal Binds----------------------------------------------
|
||||||
|
|
||||||
|
// Seek to progress percent of song
|
||||||
|
registerBind("NUMPAD_0", false, false, false, ()=>Spicetify.Player.seek(0));
|
||||||
|
registerBind("NUMPAD_1", false, false, false, ()=>Spicetify.Player.seek(.1));
|
||||||
|
registerBind("NUMPAD_2", false, false, false, ()=>Spicetify.Player.seek(.2));
|
||||||
|
registerBind("NUMPAD_3", false, false, false, ()=>Spicetify.Player.seek(.3));
|
||||||
|
registerBind("NUMPAD_4", false, false, false, ()=>Spicetify.Player.seek(.4));
|
||||||
|
registerBind("NUMPAD_5", false, false, false, ()=>Spicetify.Player.seek(.5));
|
||||||
|
registerBind("NUMPAD_6", false, false, false, ()=>Spicetify.Player.seek(.6));
|
||||||
|
registerBind("NUMPAD_7", false, false, false, ()=>Spicetify.Player.seek(.7));
|
||||||
|
registerBind("NUMPAD_8", false, false, false, ()=>Spicetify.Player.seek(.8));
|
||||||
|
registerBind("NUMPAD_9", false, false, false, ()=>Spicetify.Player.seek(.9));
|
||||||
|
|
||||||
|
|
||||||
|
// Q to open Queue page
|
||||||
|
registerBind("Q", false, false, false, clickQueueButton);
|
||||||
|
|
||||||
|
// C to open current playing context, L to open Lyrics, H to open Home Tab , Y to Open the Ypur Library, S to open the Lyrics Plus Custom App
|
||||||
|
registerBind("C", false, false, false, openContext)
|
||||||
|
registerBind("L", false, false, false, toggleLyrics);
|
||||||
|
registerBind("H", false, false, false, openHome);
|
||||||
|
registerBind("Y", false, false, false, openLibrary);
|
||||||
|
registerBind("S", false, false, false, openLyrics);
|
||||||
|
|
||||||
|
// Arrow keys to change volume
|
||||||
|
registerBind("ARROW_DOWN", false, false, false, decreaseVolume);
|
||||||
|
registerBind("ARROW_UP" , false, false, false, increaseVolume);
|
||||||
|
|
||||||
|
// Arrow keys to seek track
|
||||||
|
registerBind("ARROW_RIGHT", false, false, false, seekForward);
|
||||||
|
registerBind("ARROW_LEFT", false, false, false, seekBack);
|
||||||
|
|
||||||
|
|
||||||
|
function sleep (time) {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, time));
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickQueueButton() {
|
||||||
|
document.querySelector('.control-button-wrapper>button[Aria-label="Queue"]').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
function openContext(){
|
||||||
|
big = document.querySelector("#main > div > div.Root__top-container > nav > div.main-navBar-navBar > div:nth-child(3) > div > div > a > div")
|
||||||
|
small = document.querySelector("#main > div > div.Root__top-container > div.Root__now-playing-bar > footer > div > div.main-nowPlayingBar-left > div > div.main-coverSlotCollapsed-container > div > a > div")
|
||||||
|
if(big)
|
||||||
|
big.click();
|
||||||
|
else
|
||||||
|
small.click()
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleLyrics() {
|
||||||
|
document.querySelector('button[title="Popup Lyrics"]').click()
|
||||||
|
}
|
||||||
|
function openHome(){
|
||||||
|
ele = document.querySelector(`.main-navBar-navBar a[href="/"]`)
|
||||||
|
if(ele)
|
||||||
|
ele.click();
|
||||||
|
}
|
||||||
|
function openLyrics(){
|
||||||
|
ele = document.querySelector(`.main-navBar-navBar a[href="/lyrics-plus"]`)
|
||||||
|
if(ele)
|
||||||
|
ele.click();
|
||||||
|
}
|
||||||
|
function openLibrary(){
|
||||||
|
ele = document.querySelector(`.main-navBar-navBar a[href="/collection"]`)
|
||||||
|
if(ele)
|
||||||
|
ele.click();
|
||||||
|
}
|
||||||
|
function seekForward(){
|
||||||
|
Spicetify.Player.skipForward(5000)
|
||||||
|
}
|
||||||
|
function seekBack(){
|
||||||
|
Spicetify.Player.skipBack(5000)
|
||||||
|
}
|
||||||
|
async function decreaseVolume(){
|
||||||
|
if(!document.querySelector(".main-trackList-selected")){
|
||||||
|
if(Spicetify.Platform?.PlaybackAPI === undefined) Spicetify.Player?.origin?.setVolume(getVolume() - 0.05)
|
||||||
|
else await Spicetify.Platform.PlaybackAPI.setVolume(getVolume() - 0.05)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function increaseVolume(){
|
||||||
|
if(!document.querySelector(".main-trackList-selected")){
|
||||||
|
if(Spicetify.Platform?.PlaybackAPI === undefined) Spicetify.Player?.origin?.setVolume(getVolume() + 0.05)
|
||||||
|
else await Spicetify.Platform.PlaybackAPI.setVolume(getVolume() + 0.05)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getVolume(){
|
||||||
|
return (Spicetify.Player?.origin?._volume?._volume ?? Spicetify.Platform?.PlaybackAPI?._volume)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Ctrl + Tab and Ctrl + Shift + Tab to switch sidebar items
|
||||||
|
registerBind("TAB", true, false, false, rotateSidebarDown);
|
||||||
|
registerBind("TAB", true, true, false, rotateSidebarUp);
|
||||||
|
|
||||||
|
// Ctrl + Q to open Queue page
|
||||||
|
// registerBind("Q", true, false, false, clickQueueButton);
|
||||||
|
|
||||||
|
// Shift + H and Shift + L to go back and forward page
|
||||||
|
registerBind("H", false, true, false, clickNavigatingBackButton);
|
||||||
|
registerBind("L", false, true, false, clickNavigatingForwardButton);
|
||||||
|
|
||||||
|
// PageUp, PageDown to focus on iframe app before scrolling
|
||||||
|
registerBind("PAGE_UP", false, true, false, focusOnApp);
|
||||||
|
registerBind("PAGE_DOWN", false, true, false, focusOnApp);
|
||||||
|
|
||||||
|
// J and K to vertically scroll app
|
||||||
|
registerBind("J", false, false, false, appScrollDown);
|
||||||
|
registerBind("K", false, false, false, appScrollUp);
|
||||||
|
|
||||||
|
// G and Shift + G to scroll to top and to bottom
|
||||||
|
registerBind("G", false, false, false, appScrollTop);
|
||||||
|
registerBind("G", false, true, false, appScrollBottom);
|
||||||
|
|
||||||
|
// M to Like/Unlike track
|
||||||
|
registerBind("M", false, false, false, Spicetify.Player.toggleHeart);
|
||||||
|
|
||||||
|
// Forward Slash to open search page
|
||||||
|
registerBind("/", false, false, false, openSearchPage);
|
||||||
|
|
||||||
|
// A to activate Link Follow function
|
||||||
|
const vim = new VimBind();
|
||||||
|
registerBind("A", false, false, false, vim.activate.bind(vim));
|
||||||
|
|
||||||
|
// Esc to cancel Link Follow
|
||||||
|
vim.setCancelKey("ESCAPE")
|
||||||
|
vim.setCancelKey("Z")
|
||||||
|
|
||||||
|
function rotateSidebarDown() {
|
||||||
|
rotateSidebar(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
function rotateSidebarUp() {
|
||||||
|
rotateSidebar(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// function clickQueueButton() {
|
||||||
|
// document.querySelector(".control-button-wrapper .spoticon-queue-16").click();
|
||||||
|
// }
|
||||||
|
|
||||||
|
function clickNavigatingBackButton() {
|
||||||
|
document.querySelector(".main-topBar-historyButtons .main-topBar-back").click();
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickNavigatingForwardButton() {
|
||||||
|
document.querySelector(".main-topBar-historyButtons .main-topBar-forward").click();
|
||||||
|
}
|
||||||
|
|
||||||
|
function appScrollDown() {
|
||||||
|
const app = focusOnApp();
|
||||||
|
if (app) {
|
||||||
|
app.scrollBy(0, SCROLL_STEP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function appScrollUp() {
|
||||||
|
const app = focusOnApp();
|
||||||
|
if (app) {
|
||||||
|
app.scrollBy(0, -SCROLL_STEP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function appScrollBottom() {
|
||||||
|
const app = focusOnApp();
|
||||||
|
app.scroll(0, app.scrollHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
function appScrollTop() {
|
||||||
|
const app = focusOnApp();
|
||||||
|
app.scroll(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {KeyboardEvent} event
|
||||||
|
*/
|
||||||
|
function openSearchPage(event) {
|
||||||
|
const searchInput = document.querySelector(".main-topBar-topbarContentWrapper input");
|
||||||
|
if (searchInput) {
|
||||||
|
searchInput.focus();
|
||||||
|
} else {
|
||||||
|
const sidebarItem = document.querySelector(`.main-navBar-navBar a[href="/search"]`);
|
||||||
|
if (sidebarItem) {
|
||||||
|
sidebarItem.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Spicetify.Keyboard.ValidKey} keyName
|
||||||
|
* @param {boolean} ctrl
|
||||||
|
* @param {boolean} shift
|
||||||
|
* @param {boolean} alt
|
||||||
|
* @param {(event: KeyboardEvent) => void} callback
|
||||||
|
*/
|
||||||
|
function registerBind(keyName, ctrl, shift, alt, callback) {
|
||||||
|
const key = Spicetify.Keyboard.KEYS[keyName];
|
||||||
|
|
||||||
|
Spicetify.Keyboard.registerShortcut(
|
||||||
|
{
|
||||||
|
key,
|
||||||
|
ctrl,
|
||||||
|
shift,
|
||||||
|
alt,
|
||||||
|
},
|
||||||
|
(event) => {
|
||||||
|
if (!vim.isActive) {
|
||||||
|
callback(event);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function focusOnApp() {
|
||||||
|
return document.querySelector("main .os-viewport");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
function findActiveIndex(allItems) {
|
||||||
|
const active = document.querySelector(
|
||||||
|
".main-navBar-navBarLinkActive, .main-collectionLinkButton-selected, .main-rootlist-rootlistItemLinkActive"
|
||||||
|
);
|
||||||
|
if (!active) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = 0;
|
||||||
|
for (const item of allItems) {
|
||||||
|
if (item === active) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {1 | -1} direction
|
||||||
|
*/
|
||||||
|
function rotateSidebar(direction) {
|
||||||
|
const allItems = document.querySelectorAll(
|
||||||
|
".main-navBar-navBarLink, .main-collectionLinkButton-collectionLinkButton, .main-rootlist-rootlistItemLink"
|
||||||
|
);
|
||||||
|
const maxIndex = allItems.length - 1;
|
||||||
|
let index = findActiveIndex(allItems) + direction;
|
||||||
|
|
||||||
|
if (index < 0) index = maxIndex;
|
||||||
|
else if (index > maxIndex) index = 0;
|
||||||
|
|
||||||
|
let toClick = allItems[index];
|
||||||
|
if (!toClick.hasAttribute("href")) {
|
||||||
|
toClick = toClick.querySelector(".main-rootlist-rootlistItemLink");
|
||||||
|
}
|
||||||
|
|
||||||
|
toClick.click();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
function VimBind() {
|
||||||
|
const elementQuery = ["[href]", "button", "td.tl-play", "td.tl-number", "tr.TableRow"].join(",");
|
||||||
|
|
||||||
|
const keyList = "qwertasdfgzxcvyuiophjklbnm".split("");
|
||||||
|
|
||||||
|
const lastKeyIndex = keyList.length - 1;
|
||||||
|
|
||||||
|
this.isActive = false;
|
||||||
|
|
||||||
|
const vimOverlay = document.createElement("div");
|
||||||
|
vimOverlay.id = "vim-overlay";
|
||||||
|
vimOverlay.style.zIndex = "9999";
|
||||||
|
vimOverlay.style.position = "absolute";
|
||||||
|
vimOverlay.style.width = "100%";
|
||||||
|
vimOverlay.style.height = "100%";
|
||||||
|
vimOverlay.style.display = "none";
|
||||||
|
vimOverlay.innerHTML = `<style>
|
||||||
|
.vim-key {
|
||||||
|
position: fixed;
|
||||||
|
padding: 3px 6px;
|
||||||
|
background-color: black;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: solid 2px white;
|
||||||
|
color: white;
|
||||||
|
text-transform: lowercase;
|
||||||
|
line-height: normal;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
</style>`;
|
||||||
|
document.body.append(vimOverlay);
|
||||||
|
|
||||||
|
const mousetrap = new Spicetify.Mousetrap(document);
|
||||||
|
mousetrap.bind(keyList, listenToKeys.bind(this), "keypress");
|
||||||
|
// Pause mousetrap event emitter
|
||||||
|
const orgStopCallback = mousetrap.stopCallback;
|
||||||
|
mousetrap.stopCallback = () => true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {KeyboardEvent} event
|
||||||
|
*/
|
||||||
|
this.activate = function (event) {
|
||||||
|
vimOverlay.style.display = "block";
|
||||||
|
|
||||||
|
const vimkey = getVims();
|
||||||
|
if (vimkey.length > 0) {
|
||||||
|
vimkey.forEach((e) => e.remove());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let firstKey = 0;
|
||||||
|
let secondKey = 0;
|
||||||
|
|
||||||
|
getLinks().forEach((e) => {
|
||||||
|
if (e.style.display === "none" || e.style.visibility === "hidden" || e.style.opacity === "0") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bound = e.getBoundingClientRect();
|
||||||
|
let owner = document.body;
|
||||||
|
|
||||||
|
let top = bound.top;
|
||||||
|
let left = bound.left;
|
||||||
|
|
||||||
|
if (
|
||||||
|
bound.bottom > owner.clientHeight ||
|
||||||
|
bound.left > owner.clientWidth ||
|
||||||
|
bound.right < 0 ||
|
||||||
|
bound.top < 0 ||
|
||||||
|
bound.width === 0 ||
|
||||||
|
bound.height === 0
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vimOverlay.append(createKey(e, keyList[firstKey] + keyList[secondKey], top, left));
|
||||||
|
|
||||||
|
secondKey++;
|
||||||
|
if (secondKey > lastKeyIndex) {
|
||||||
|
secondKey = 0;
|
||||||
|
firstKey++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.isActive = true;
|
||||||
|
setTimeout(() => (mousetrap.stopCallback = orgStopCallback.bind(mousetrap)), 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {KeyboardEvent} event
|
||||||
|
*/
|
||||||
|
this.deactivate = function (event) {
|
||||||
|
mousetrap.stopCallback = () => true;
|
||||||
|
this.isActive = false;
|
||||||
|
vimOverlay.style.display = "none";
|
||||||
|
getVims().forEach((e) => e.remove());
|
||||||
|
};
|
||||||
|
|
||||||
|
function getLinks() {
|
||||||
|
const elements = Array.from(document.querySelectorAll(elementQuery));
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getVims() {
|
||||||
|
return Array.from(vimOverlay.getElementsByClassName("vim-key"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {KeyboardEvent} event
|
||||||
|
*/
|
||||||
|
function listenToKeys(event) {
|
||||||
|
if (!this.isActive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const vimkey = getVims();
|
||||||
|
|
||||||
|
if (vimkey.length === 0) {
|
||||||
|
this.deactivate(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const div of vimkey) {
|
||||||
|
const text = div.innerText.toLowerCase();
|
||||||
|
if (text[0] !== event.key) {
|
||||||
|
div.remove();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newText = text.slice(1);
|
||||||
|
if (newText.length === 0) {
|
||||||
|
click(div.target);
|
||||||
|
this.deactivate(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.innerText = newText;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vimOverlay.childNodes.length === 1) {
|
||||||
|
this.deactivate(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function click(element) {
|
||||||
|
if (element.hasAttribute("href") || element.tagName === "BUTTON") {
|
||||||
|
element.click();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const findButton = element.querySelector(`button[data-ta-id="play-button"]`) || element.querySelector(`button[data-button="play"]`);
|
||||||
|
if (findButton) {
|
||||||
|
findButton.click();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
alert("Let me know where you found this button, please. I can't click this for you without that information.");
|
||||||
|
return;
|
||||||
|
// TableCell case where play button is hidden
|
||||||
|
// Index number is in first column
|
||||||
|
const index = parseInt(element.firstChild.innerText) - 1;
|
||||||
|
const context = getContextUri();
|
||||||
|
if (index >= 0 && context) {
|
||||||
|
console.log(index);
|
||||||
|
console.log(context);
|
||||||
|
|
||||||
|
//Spicetify.PlaybackControl.playFromResolver(context, { index }, () => {});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createKey(target, key, top, left) {
|
||||||
|
const div = document.createElement("span");
|
||||||
|
div.classList.add("vim-key");
|
||||||
|
div.innerText = key;
|
||||||
|
div.style.top = top + "px";
|
||||||
|
div.style.left = left + "px";
|
||||||
|
div.target = target;
|
||||||
|
return div;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContextUri() {
|
||||||
|
const username = __spotify.username;
|
||||||
|
const activeApp = localStorage.getItem(username + ":activeApp");
|
||||||
|
if (activeApp) {
|
||||||
|
try {
|
||||||
|
return JSON.parse(activeApp).uri.replace("app:", "");
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Spicetify.Keyboard.ValidKey} key
|
||||||
|
*/
|
||||||
|
this.setCancelKey = function (key) {
|
||||||
|
mousetrap.bind(Spicetify.Keyboard.KEYS[key], this.deactivate.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
3
.config/spicetify/Extensions/playlistIcons.js
Normal file
3
.config/spicetify/Extensions/playlistIcons.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
var playlistDicons=(()=>{var s=Object.create,o=Object.defineProperty,c=Object.getOwnPropertyDescriptor,p=Object.getOwnPropertyNames,d=Object.getPrototypeOf,m=Object.prototype.hasOwnProperty,e=(e=>"undefined"!=typeof require?require:"undefined"!=typeof Proxy?new Proxy(e,{get:(e,t)=>("undefined"!=typeof require?require:e)[t]}):e)(function(e){if("react"===e)return Spicetify.React;if("react-dom"===e)return Spicetify.ReactDOM;if("undefined"!=typeof require)return require.apply(this,arguments);throw new Error('Dynamic require of "'+e+'" is not supported')}),t=(e,t,i)=>{i=null!=e?s(d(e)):{};var a=!t&&e&&e.__esModule?i:o(i,"default",{value:e,enumerable:!0}),n=e,l=void 0,r=void 0;if(n&&"object"==typeof n||"function"==typeof n)for(let e of p(n))m.call(a,e)||e===l||o(a,e,{get:()=>n[e],enumerable:!(r=c(n,e))||r.enumerable});return a},u=t(e("react")),y=t(e("react-dom"));var i=t(e("react"));function g(){return i.default.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",height:"24px",viewBox:"0 0 24 24",width:"24px",fill:"#FFFFFF"},i.default.createElement("path",{d:"M0 0h24v24H0V0z",fill:"none"}),i.default.createElement("path",{d:"M9.17 6l2 2H20v10H4V6h5.17M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"}))}var f=new Map;async function r(o){const e=await new Promise(t=>{const i=setInterval(()=>{var e=document.querySelectorAll("#spicetify-playlist-list li a");0<e.length&&(clearInterval(i),t(Array.from(e)))},100)});e.forEach(e=>{var t,i;const a=e.href.split("/").at(-1);var n=e.href.split("/").at(-2),l=f.get(a);if(null!=(t=e.parentElement)&&t.classList.add("playlist-item"),l)null!=(t=e.parentElement)&&t.prepend(l);else switch(n){case"playlist":var r=o.find(e=>e.id===a),r=function(e){const t=document.createElement(e?"img":"div");return t.classList.add("playlist-item__img"),e?t.setAttribute("src",e):t.classList.add("no-icon"),t}((null==(r=null==r?void 0:r.images[0])?void 0:r.url)||"");null!=(i=e.parentElement)&&i.prepend(r),f.set(a,r);break;case"folder":{const s=document.createElement("div");s.classList.add("playlist-item__img","folder"),y.default.render(u.default.createElement(g,null),s),null!=(i=e.parentElement)&&i.prepend(s),f.set(a,s);break}default:console.warn("[playlist-icons] playlist list anchor type not recognized: "+n)}})}var v="playlist-icons_big";var a=async function(){for(var e,a;null==Spicetify||!Spicetify.Platform||null==Spicetify||!Spicetify.CosmosAsync;)await new Promise(e=>setTimeout(e,100));const t=null!=(e=JSON.parse(localStorage.getItem(v)))&&e,i=await async function e(t){t=await Spicetify.CosmosAsync.get(t);return[...t.items,...t.next?await e(t.next):[]]}("https://api.spotify.com/v1/me/playlists?limit=50"),n=(a="#spicetify-playlist-list",await new Promise(t=>{const i=setInterval(()=>{var e=document.querySelector(a);e&&(clearInterval(i),t(e))},100)})),l=new MutationObserver(async()=>{l.disconnect(),await r(i),l.observe(n,{childList:!0,subtree:!0})});await r(i),l.observe(n,{childList:!0,subtree:!0}),t&&n.classList.add("big-icons"),new Spicetify.Menu.Item("Big playlist icons",t,e=>{e.setState(!e.isEnabled),localStorage.setItem(v,JSON.stringify(!t)),n.classList.toggle("big-icons")}).register()};(async()=>{await a()})()})();(async()=>{var e;document.getElementById("playlistDicons")||((e=document.createElement("style")).id="playlistDicons",e.textContent=String.raw`
|
||||||
|
:root{---playlist-img-spacing:6px}.playlist-item{padding-top:0;padding-bottom:0;align-items:center}.playlist-item__img{width:1.5em;height:1.5em;border-radius:2px;margin-right:12px;filter:brightness(85%)}.playlist-item__img.folder{background-color:var(--spice-tab-active);display:flex;align-items:center;justify-content:center}.playlist-item__img.folder svg{width:1.1em;height:1.1em}.playlist-item__img.no-icon{background-color:var(--spice-tab-active);height:1.5em}.playlist-item:hover .playlist-item__img{transition:.2s ease-out;filter:brightness(100%)}.big-icons .playlist-item{padding-top:var(---playlist-img-spacing);padding-bottom:var(---playlist-img-spacing)}.big-icons .playlist-item__img{border-radius:4px;width:2em;height:2em}.big-icons .playlist-item__img.folder{padding:4px}.big-icons .playlist-item__img.folder svg{width:1.5em;height:1.5em}.big-icons>div{contain:unset}
|
||||||
|
`.trim(),document.head.appendChild(e))})();
|
1306
.config/spicetify/Extensions/sortByPlayCount.js
Normal file
1306
.config/spicetify/Extensions/sortByPlayCount.js
Normal file
File diff suppressed because it is too large
Load diff
32
.config/spicetify/Extensions/volumePercentage.js
Normal file
32
.config/spicetify/Extensions/volumePercentage.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
// NAME: Add Volume Percentage
|
||||||
|
// AUTHOR: daksh2k
|
||||||
|
// DESCRIPTION: Add the Volume Percentage to the Volume Bar
|
||||||
|
|
||||||
|
/// <reference path="../globals.d.ts" />
|
||||||
|
|
||||||
|
(function addVolumep() {
|
||||||
|
const volumeBar = document.querySelector(".volume-bar");
|
||||||
|
if (!(volumeBar && Spicetify.Player)) {
|
||||||
|
setTimeout(addVolumep, 200);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const ele = document.createElement("span");
|
||||||
|
ele.classList.add("volume-percent");
|
||||||
|
ele.setAttribute("style", "font-size: 14px; padding-left: 10px; min-width: 45px;");
|
||||||
|
|
||||||
|
volumeBar.append(ele);
|
||||||
|
// @ts-ignore
|
||||||
|
volumeBar.style.flex = "0 1 180px";
|
||||||
|
|
||||||
|
updatePercentage();
|
||||||
|
function updatePercentage() {
|
||||||
|
const currVolume = Math.round((Spicetify.Player?.origin?._volume?._volume ?? Spicetify.Platform?.PlaybackAPI?._volume) * 100);
|
||||||
|
ele.innerText = currVolume == -100 ? `` : `${currVolume}%`;
|
||||||
|
// @ts-ignore
|
||||||
|
document.querySelector(".main-connectBar-connectBar")?.style.setProperty("--triangle-position", "229px");
|
||||||
|
}
|
||||||
|
if (Spicetify.Platform?.PlaybackAPI === undefined) Spicetify.Player.origin._events.addListener("volume", updatePercentage);
|
||||||
|
else Spicetify.Platform.PlaybackAPI._events.addListener("volume", updatePercentage);
|
||||||
|
})();
|
96
.config/spicetify/Extensions/wikify.js
Normal file
96
.config/spicetify/Extensions/wikify.js
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
//@ts-check
|
||||||
|
|
||||||
|
// NAME: Wikify
|
||||||
|
// AUTHOR: CharlieS1103
|
||||||
|
// DESCRIPTION: View an artists wikipedia page to learn more about them
|
||||||
|
|
||||||
|
/// <reference path="../../spicetify-cli/globals.d.ts" />
|
||||||
|
(function WikiFy() {
|
||||||
|
if (!document.body.classList.contains('wikify-injected')) {
|
||||||
|
var styleSheet = document.createElement("style")
|
||||||
|
|
||||||
|
styleSheet.innerHTML =
|
||||||
|
`body > generic-modal > div > div {
|
||||||
|
background-color: beige !important;
|
||||||
|
color: black !important;
|
||||||
|
} `
|
||||||
|
document.body.appendChild(styleSheet)
|
||||||
|
document.body.classList.add('wikify-injected');
|
||||||
|
}
|
||||||
|
const {
|
||||||
|
CosmosAsync,
|
||||||
|
URI
|
||||||
|
} = Spicetify;
|
||||||
|
if (!(CosmosAsync && URI)) {
|
||||||
|
setTimeout(WikiFy, 10);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const lang = Spicetify.Locale._locale;
|
||||||
|
const buttontxt = "View Wiki"
|
||||||
|
//Watch for when the song is changed
|
||||||
|
|
||||||
|
function error() {
|
||||||
|
Spicetify.PopupModal.display({
|
||||||
|
title: "Error",
|
||||||
|
content: "Selected artist does not have a WikiPedia page, Sorry."
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getWikiText(uris) {
|
||||||
|
|
||||||
|
const rawUri = uris[0];
|
||||||
|
const uri = rawUri.split(":")[2]
|
||||||
|
const artistName = await CosmosAsync.get(`https://api.spotify.com/v1/artists/${uri}`)
|
||||||
|
const artistNameTrimmed = (artistName.name).replace(/\s/g, "%20");
|
||||||
|
|
||||||
|
if (artistName != null) {
|
||||||
|
try {
|
||||||
|
const wikiInfo = await CosmosAsync.get(`https://${lang}.wikipedia.org/w/api.php?action=query&format=json&prop=extracts%7Cdescription&titles=${artistNameTrimmed}`)
|
||||||
|
//TODO: option to choose local language or english / english fallback? / subcontextmenu to choose?
|
||||||
|
//https://en.wikipedia.org/w/api.php?action=query&format=json&uselang=en&list=search&srsearch=${artistNameTrimmed}
|
||||||
|
|
||||||
|
const wikiInfoArr = wikiInfo.query.pages
|
||||||
|
const page = Object.values(wikiInfoArr)[0];
|
||||||
|
if (page != null || page != undefined) {
|
||||||
|
const pageText = page.extract.replace(/<!--[\s\S]*?-->/g, '');
|
||||||
|
if (pageText != "\n") {
|
||||||
|
Spicetify.PopupModal.display({
|
||||||
|
title: "WikiFy",
|
||||||
|
content: page.extract
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
error();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
error();
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Spicetify.PopupModal.display({
|
||||||
|
title: "Error",
|
||||||
|
content: "Request failed",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function shouldDisplayContextMenu(uris) {
|
||||||
|
if (uris.length > 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const uri = uris[0];
|
||||||
|
const uriObj = Spicetify.URI.fromString(uri);
|
||||||
|
if (uriObj.type === Spicetify.URI.Type.TRACK || uriObj.type === Spicetify.URI.Type.ARTIST) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cntxMenu = new Spicetify.ContextMenu.Item(
|
||||||
|
buttontxt,
|
||||||
|
getWikiText,
|
||||||
|
shouldDisplayContextMenu,
|
||||||
|
);
|
||||||
|
|
||||||
|
cntxMenu.register();
|
||||||
|
|
||||||
|
})();
|
406
.config/spicetify/Themes/Comfy/color.ini
Normal file
406
.config/spicetify/Themes/Comfy/color.ini
Normal file
|
@ -0,0 +1,406 @@
|
||||||
|
[Comfy]
|
||||||
|
text = FFFFFF
|
||||||
|
subtext = B9BBBE
|
||||||
|
main = 23283D
|
||||||
|
main-transition = 1E2233
|
||||||
|
highlight = 45495b
|
||||||
|
highlight-elevated = 32364a
|
||||||
|
sidebar = 1E2233
|
||||||
|
player = 101320
|
||||||
|
card = 191F2E
|
||||||
|
shadow = 1E2233
|
||||||
|
selected-row = F1F1F1
|
||||||
|
button = 7289DA
|
||||||
|
button-active = 5C6FB1
|
||||||
|
button-disabled = 4B588C
|
||||||
|
tab-active = 1E2233
|
||||||
|
notification = 7289DA
|
||||||
|
notification-error = d25050
|
||||||
|
misc = 000000
|
||||||
|
play-button = 7289da
|
||||||
|
play-button-active = 869adf
|
||||||
|
progress-fg = 1ed760
|
||||||
|
progress-bg = 7289da
|
||||||
|
heart = d25050
|
||||||
|
liked-left = 3a62f5
|
||||||
|
liked-right = c4efd9
|
||||||
|
pagelink-active = 5c6eb1
|
||||||
|
radio-btn-active = 7289DA
|
||||||
|
|
||||||
|
[Nord]
|
||||||
|
text = B2BCCC
|
||||||
|
subtext = B2BCCC
|
||||||
|
main = 2E3440
|
||||||
|
main-transition = 262B35
|
||||||
|
highlight = 50555f
|
||||||
|
highlight-elevated = 3d424d
|
||||||
|
sidebar = 262B35
|
||||||
|
player = 363d4c
|
||||||
|
card = 363d4c
|
||||||
|
shadow = 1d2128
|
||||||
|
button = 8A99AF
|
||||||
|
button-active = 718CAD
|
||||||
|
button-disabled = 434C5E
|
||||||
|
tab-active = 363d4c
|
||||||
|
notification = 363d4c
|
||||||
|
notification-error = A9555E
|
||||||
|
misc = FFFFFF
|
||||||
|
play-button = 8A99AF
|
||||||
|
play-button-active = 718CAD
|
||||||
|
progress-fg = 8A99AF
|
||||||
|
progress-bg = 4b566a
|
||||||
|
heart = 718CAD
|
||||||
|
liked-left = 262B35
|
||||||
|
liked-right = B2BCCC
|
||||||
|
pagelink-active = b7c1d5
|
||||||
|
radio-btn-active = 363d4c
|
||||||
|
|
||||||
|
[Lunar]
|
||||||
|
text = f3f3f3
|
||||||
|
subtext = cecece
|
||||||
|
main = 161616
|
||||||
|
main-transition = 101010
|
||||||
|
highlight = 2a2a2a
|
||||||
|
highlight-elevated = 232323
|
||||||
|
sidebar = 202020
|
||||||
|
player = 202020
|
||||||
|
card = 202020
|
||||||
|
shadow = 252525
|
||||||
|
selected-row = cecece
|
||||||
|
button = 3281ea
|
||||||
|
button-active = 0284e8
|
||||||
|
button-disabled = 303030
|
||||||
|
tab-active = ebbcba
|
||||||
|
notification = 3281ea
|
||||||
|
notification-error = b10c0c
|
||||||
|
misc = 252525
|
||||||
|
play-button = ebbcba
|
||||||
|
play-button-active = eba9a7
|
||||||
|
progress-fg = 025ca1
|
||||||
|
progress-bg = 202020
|
||||||
|
heart = ebbcba
|
||||||
|
liked-left = 3a62f5
|
||||||
|
liked-right = c4efd9
|
||||||
|
pagelink-active = ffffff
|
||||||
|
radio-btn-active = 0284e8
|
||||||
|
|
||||||
|
[catppuccin-dark]
|
||||||
|
text = cad3f5
|
||||||
|
subtext = b8c0e0
|
||||||
|
main = 181926
|
||||||
|
main-transition = 181926
|
||||||
|
highlight = 333645
|
||||||
|
highlight-elevated = 232533
|
||||||
|
sidebar = 24273a
|
||||||
|
player = 24273a
|
||||||
|
card = 494d64
|
||||||
|
shadow = 5b6078
|
||||||
|
selected-row = b8c0e0
|
||||||
|
button = 8aadf4
|
||||||
|
button-active = 7dc4e4
|
||||||
|
button-disabled = 494d64
|
||||||
|
tab-active = ed8796
|
||||||
|
notification = 8aadf4
|
||||||
|
notification-error = ed8796
|
||||||
|
misc = 5b6078
|
||||||
|
play-button = f5bde6
|
||||||
|
play-button-active = f0c6c6
|
||||||
|
progress-fg = 91d7e3
|
||||||
|
progress-bg = 494d64
|
||||||
|
heart = f5a97f
|
||||||
|
liked-left = a6da95
|
||||||
|
liked-right = b7bdf8
|
||||||
|
pagelink-active = ffffff
|
||||||
|
radio-btn-active = 7dc4e4
|
||||||
|
|
||||||
|
[catppuccin-light]
|
||||||
|
text = cad3f5
|
||||||
|
subtext = b8c0e0
|
||||||
|
main = 494d64
|
||||||
|
main-transition = 181926
|
||||||
|
highlight = 5c6179
|
||||||
|
highlight-elevated = 545a71
|
||||||
|
sidebar = 24273a
|
||||||
|
player = 24273a
|
||||||
|
card = 494d64
|
||||||
|
shadow = 5b6078
|
||||||
|
selected-row = b8c0e0
|
||||||
|
button = 8aadf4
|
||||||
|
button-active = 7dc4e4
|
||||||
|
button-disabled = 494d64
|
||||||
|
tab-active = ed8796
|
||||||
|
notification = 8aadf4
|
||||||
|
notification-error = ed8796
|
||||||
|
misc = 5b6078
|
||||||
|
play-button = f5bde6
|
||||||
|
play-button-active = f0c6c6
|
||||||
|
progress-fg = 91d7e3
|
||||||
|
progress-bg = 494d64
|
||||||
|
heart = f5a97f
|
||||||
|
liked-left = a6da95
|
||||||
|
liked-right = b7bdf8
|
||||||
|
pagelink-active = ffffff
|
||||||
|
radio-btn-active = 7dc4e4
|
||||||
|
|
||||||
|
[Mono]
|
||||||
|
text = FFFFFF
|
||||||
|
subtext = B9BBBE
|
||||||
|
main = 171717
|
||||||
|
main-transition = FFFFFF
|
||||||
|
highlight = 3b3b3b
|
||||||
|
highlight-elevated = 262626
|
||||||
|
sidebar = 101010
|
||||||
|
player = 101010
|
||||||
|
card = 343434
|
||||||
|
shadow = 595858
|
||||||
|
selected-row = F1F1F1
|
||||||
|
button = FFFFFF
|
||||||
|
button-active = c5c5c5
|
||||||
|
button-disabled = 4a4949
|
||||||
|
tab-active = 303030
|
||||||
|
notification = 101010
|
||||||
|
notification-error = d25050
|
||||||
|
misc = 000000
|
||||||
|
play-button = FFFFFF
|
||||||
|
play-button-active = FFFFFF
|
||||||
|
progress-fg = FFFFFF
|
||||||
|
progress-bg = 343434
|
||||||
|
heart = FFFFFF
|
||||||
|
liked-left = 000000
|
||||||
|
liked-right = ffffff
|
||||||
|
pagelink-active = 787878
|
||||||
|
radio-btn-active = 737373
|
||||||
|
|
||||||
|
[Deep]
|
||||||
|
text = 4f9a87
|
||||||
|
subtext = 406560
|
||||||
|
button-text = 4f9a87
|
||||||
|
main = 040614
|
||||||
|
main-transition = 0F111A
|
||||||
|
highlight = 0f1f28
|
||||||
|
highlight-elevated = 09111d
|
||||||
|
sidebar = 0F111A
|
||||||
|
player = 0F111A
|
||||||
|
subbutton-text = 040614
|
||||||
|
card = 0f1118
|
||||||
|
shadow = 0f1118
|
||||||
|
selected-row = 4f9a87
|
||||||
|
sub-button = 4f9a87
|
||||||
|
button = 106165
|
||||||
|
button-active = 4f9a87
|
||||||
|
button-disabled = 0C1C19
|
||||||
|
tab-active = 0a1527
|
||||||
|
notification = 051024
|
||||||
|
notification-error = 051024
|
||||||
|
playback-bar = 4f9a87
|
||||||
|
misc = 406560
|
||||||
|
play-button = 106165
|
||||||
|
play-button-active = 4f9a87
|
||||||
|
progress-fg = 4f9a87
|
||||||
|
progress-bg = 106165
|
||||||
|
heart = d25050
|
||||||
|
liked-left = 3a62f5
|
||||||
|
liked-right = c4efd9
|
||||||
|
pagelink-active = 4f9a87
|
||||||
|
radio-btn-active = 4f9a87
|
||||||
|
|
||||||
|
[Sunset]
|
||||||
|
text = ffce3f
|
||||||
|
subtext = fef3bb
|
||||||
|
main = 171717
|
||||||
|
main-transition = 000000
|
||||||
|
highlight = 3d3c32
|
||||||
|
highlight-elevated = 272722
|
||||||
|
sidebar = 101010
|
||||||
|
player = 101010
|
||||||
|
card = cc9756
|
||||||
|
shadow = e3b47b
|
||||||
|
selected-row = fef3bb
|
||||||
|
button = ffce3f
|
||||||
|
button-active = bf9b30
|
||||||
|
button-disabled = 4a4949
|
||||||
|
tab-active = 303030
|
||||||
|
notification = ffffff
|
||||||
|
notification-error = d25050
|
||||||
|
misc = 000000
|
||||||
|
play-button = ffce3f
|
||||||
|
play-button-active = fc9e3a
|
||||||
|
progress-fg = ff8300
|
||||||
|
progress-bg = 343434
|
||||||
|
heart = ff8300
|
||||||
|
liked-left = 000000
|
||||||
|
liked-right = ffffff
|
||||||
|
pagelink-active = fef3bb
|
||||||
|
radio-btn-active = fef3bb
|
||||||
|
|
||||||
|
[Neon]
|
||||||
|
text = 588bae
|
||||||
|
subtext = eaffff
|
||||||
|
main = 171717
|
||||||
|
main-transition = 000000
|
||||||
|
highlight = 3b3b3b
|
||||||
|
highlight-elevated = 262626
|
||||||
|
sidebar = 101010
|
||||||
|
player = 101010
|
||||||
|
card = 7fa1b5
|
||||||
|
shadow = a9c9db
|
||||||
|
selected-row = F1F1F1
|
||||||
|
button = 588bae
|
||||||
|
button-active = 3b5d75
|
||||||
|
button-disabled = 4a4949
|
||||||
|
tab-active = 303030
|
||||||
|
notification = FFFFFF
|
||||||
|
notification-error = d25050
|
||||||
|
misc = 000000
|
||||||
|
play-button = 588bae
|
||||||
|
play-button-active = 5085ab
|
||||||
|
progress-fg = 00afdb
|
||||||
|
progress-bg = 343434
|
||||||
|
heart = 00afdb
|
||||||
|
liked-left = 000000
|
||||||
|
liked-right = ffffff
|
||||||
|
pagelink-active = bbe7fe
|
||||||
|
radio-btn-active = eaffff
|
||||||
|
|
||||||
|
[Forest]
|
||||||
|
text = B2C5B3
|
||||||
|
subtext = d5ddde
|
||||||
|
main = 171717
|
||||||
|
main-transition = 000000
|
||||||
|
highlight = 3b3b3b
|
||||||
|
highlight-elevated = 262626
|
||||||
|
sidebar = 101010
|
||||||
|
player = 101010
|
||||||
|
card = 5c6e59
|
||||||
|
shadow = 3c5148
|
||||||
|
selected-row = F1F1F1
|
||||||
|
button = B2C5B3
|
||||||
|
button-active = F1F1F1
|
||||||
|
button-disabled = 4a4949
|
||||||
|
tab-active = 303030
|
||||||
|
notification = FFFFFF
|
||||||
|
notification-error = d25050
|
||||||
|
misc = 000000
|
||||||
|
play-button = 3c5148
|
||||||
|
play-button-active = 43705d
|
||||||
|
progress-fg = 3c5148
|
||||||
|
progress-bg = 343434
|
||||||
|
heart = 3c5148
|
||||||
|
liked-left = 000000
|
||||||
|
liked-right = ffffff
|
||||||
|
pagelink-active = 3c5148
|
||||||
|
radio-btn-active = 737373
|
||||||
|
|
||||||
|
[Sakura]
|
||||||
|
text = fcb4ca
|
||||||
|
subtext = ffdcdc
|
||||||
|
main = 171717
|
||||||
|
main-transition = 000000
|
||||||
|
highlight = 3d3838
|
||||||
|
highlight-elevated = 272525
|
||||||
|
sidebar = 101010
|
||||||
|
player = 101010
|
||||||
|
card = d68ba2
|
||||||
|
shadow = fcb4ca
|
||||||
|
selected-row = ffdcdc
|
||||||
|
button = fcb4ca
|
||||||
|
button-active = d48aa0
|
||||||
|
button-disabled = 4a4949
|
||||||
|
tab-active = 303030
|
||||||
|
notification = FFFFFF
|
||||||
|
notification-error = d25050
|
||||||
|
misc = 000000
|
||||||
|
play-button = f42c38
|
||||||
|
play-button-active = ba182b
|
||||||
|
progress-fg = Cfeefa
|
||||||
|
progress-bg = 343434
|
||||||
|
heart = f25477
|
||||||
|
liked-left = 000000
|
||||||
|
liked-right = ffffff
|
||||||
|
pagelink-active = f5bcdb
|
||||||
|
radio-btn-active = ffdcdc
|
||||||
|
|
||||||
|
[Vaporwave]
|
||||||
|
text = 01CDFE
|
||||||
|
subtext = eaffff
|
||||||
|
main = 171717
|
||||||
|
main-transition = 000000
|
||||||
|
highlight = 3b3b3b
|
||||||
|
highlight-elevated = 262626
|
||||||
|
sidebar = 101010
|
||||||
|
player = 101010
|
||||||
|
card = 007f9e
|
||||||
|
shadow = 2ec2e6
|
||||||
|
selected-row = F1F1F1
|
||||||
|
button = 01CDFE
|
||||||
|
button-active = 118ba8
|
||||||
|
button-disabled = 4a4949
|
||||||
|
tab-active = 303030
|
||||||
|
notification = FFFFFF
|
||||||
|
notification-error = d25050
|
||||||
|
misc = 000000
|
||||||
|
play-button = ffd300
|
||||||
|
play-button-active = e3c01b
|
||||||
|
progress-fg = f706cf
|
||||||
|
progress-bg = 343434
|
||||||
|
heart = f706cf
|
||||||
|
liked-left = 000000
|
||||||
|
liked-right = ffffff
|
||||||
|
pagelink-active = c0d6fa
|
||||||
|
radio-btn-active = eaffff
|
||||||
|
|
||||||
|
[Velvet]
|
||||||
|
text = AD434E
|
||||||
|
subtext = 762F37
|
||||||
|
main = 1E1E1E
|
||||||
|
main-transition = 161616
|
||||||
|
highlight = 322324
|
||||||
|
highlight-elevated = 272021
|
||||||
|
sidebar = 161616
|
||||||
|
player = 080808
|
||||||
|
card = 0F0F0F
|
||||||
|
shadow = 161616
|
||||||
|
selected-row = 973B45
|
||||||
|
button = 6B2B32
|
||||||
|
button-active = 552328
|
||||||
|
button-disabled = 262626
|
||||||
|
tab-active = 161616
|
||||||
|
notification = 6B2B32
|
||||||
|
notification-error = 60272D
|
||||||
|
misc = 000000
|
||||||
|
play-button = 552328
|
||||||
|
play-button-active = 6B2B32
|
||||||
|
progress-fg = 81333B
|
||||||
|
progress-bg = A23F49
|
||||||
|
heart = 60272D
|
||||||
|
liked-left = 2D2D2D
|
||||||
|
liked-right = 8C3740
|
||||||
|
pagelink-active = 4A1F23
|
||||||
|
radio-btn-active = 6B2B32
|
||||||
|
|
||||||
|
[wal16]
|
||||||
|
text = ${xrdb:color15:FFFFFF}
|
||||||
|
subtext = ${xrdb:color6:B9BBBE}
|
||||||
|
main = ${xrdb:color0:23283D}
|
||||||
|
main-transition = ${xrdb:color0:000000}
|
||||||
|
sidebar = ${xrdb:color8:1E2233}
|
||||||
|
player = ${xrdb:color4:101320}
|
||||||
|
card = ${xrdb:color8:191F2E}
|
||||||
|
shadow = ${xrdb:color0:1E2233}
|
||||||
|
selected-row = ${xrdb:color15:F1F1F1}
|
||||||
|
button = ${xrdb:color6:7289DA}
|
||||||
|
button-active = ${xrdb:color14:5C6FB1}
|
||||||
|
button-disabled = ${xrdb:color8:4B588C}
|
||||||
|
tab-active = ${xrdb:color9:1E2233}
|
||||||
|
notification = FFFFFF
|
||||||
|
notification-error = d25050
|
||||||
|
misc = ${xrdb:color0:000000}
|
||||||
|
play-button = ${xrdb:color11:5C6FB1}
|
||||||
|
play-button-active = ${xrdb:color3:7289DA}
|
||||||
|
progress-fg = ${xrdb:color10:1ed760}
|
||||||
|
progress-bg = ${xrdb:color0:f1f1f1}
|
||||||
|
heart = ${xrdb:color10:d25050}
|
||||||
|
liked-left = ${xrdb:color10:3a62f5}
|
||||||
|
liked-right = ${xrdb:color11:c4efd9}
|
||||||
|
pagelink-active = ${xrdb:color13:5c6eb1}
|
||||||
|
radio-btn-active = ${xrdb:color13:7289DA}
|
9
.config/spicetify/Themes/Comfy/theme.js
Normal file
9
.config/spicetify/Themes/Comfy/theme.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
(() => {
|
||||||
|
const themeScript = document.createElement("SCRIPT");
|
||||||
|
themeScript.setAttribute("type", "text/javascript");
|
||||||
|
themeScript.setAttribute(
|
||||||
|
"src",
|
||||||
|
"https://comfy-themes.github.io/Spicetify/Comfy/theme.script.js"
|
||||||
|
);
|
||||||
|
document.head.appendChild(themeScript);
|
||||||
|
})();
|
1
.config/spicetify/Themes/Comfy/user.css
Normal file
1
.config/spicetify/Themes/Comfy/user.css
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@import url("https://comfy-themes.github.io/Spicetify/Comfy/app.css");
|
32
.config/spicetify/config-xpui.ini
Normal file
32
.config/spicetify/config-xpui.ini
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
[Preprocesses]
|
||||||
|
disable_ui_logging = 1
|
||||||
|
remove_rtl_rule = 1
|
||||||
|
expose_apis = 1
|
||||||
|
disable_upgrade_check = 1
|
||||||
|
disable_sentry = 1
|
||||||
|
|
||||||
|
[AdditionalOptions]
|
||||||
|
sidebar_config = 1
|
||||||
|
home_config = 1
|
||||||
|
experimental_features = 1
|
||||||
|
extensions = adblock.js|hidePodcasts.js|historyShortcut.js|copyPlaylist.js|wikify.js|fullScreen.js|volumePercentage.js|bookmark.js|loopyLoop.js|keyboardShortcutMy.js|genre.js|playlistIcons.js|catppuccin-macchiato.js
|
||||||
|
custom_apps = lyrics-plus|marketplace
|
||||||
|
|
||||||
|
[Patch]
|
||||||
|
|
||||||
|
[Setting]
|
||||||
|
spotify_path = /opt/spotify
|
||||||
|
color_scheme = Comfy
|
||||||
|
overwrite_assets = 1
|
||||||
|
spotify_launch_flags =
|
||||||
|
check_spicetify_upgrade = 0
|
||||||
|
prefs_path = ~/.config/spotify/prefs
|
||||||
|
current_theme = Comfy
|
||||||
|
inject_css = 1
|
||||||
|
replace_colors = 1
|
||||||
|
inject_theme_js = 1
|
||||||
|
|
||||||
|
; DO NOT CHANGE!
|
||||||
|
[Backup]
|
||||||
|
version = 1.2.13.661.ga588f749
|
||||||
|
with = Dev
|
Loading…
Add table
Reference in a new issue