Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Dribbblish): add ylx support #953

Merged
merged 1 commit into from
Jun 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
282 changes: 109 additions & 173 deletions Dribbblish/theme.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,3 @@
// 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");
}
}
};

// register drib menu item
DribbblishShared.configMenu.register();
DribbblishShared.configMenu.addItem(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)) {
Expand All @@ -35,102 +7,22 @@ function waitForElement(els, func, timeout = 100) {
}
}

waitForElement([
`ul[tabindex="0"]`,
`ul[tabindex="0"] .GlueDropTarget--playlists.GlueDropTarget--folders`
], ([root, firstItem]) => {
const listElem = firstItem.parentElement;
root.classList.add("dribs-playlist-list");

/** Replace Playlist name with their pictures */
function loadPlaylistImage() {
for (const item of listElem.children) {
let link = item.querySelector("a");
if (!link) continue;

let [_, app, uid ] = link.pathname.split("/");
let uri;
if (app === "playlist") {
uri = `spotify:playlist:${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);
}
img.src = base64 || "https://cdn.jsdelivr.net/gh/spicetify/spicetify-themes@master/Dribbblish/images/tracklist-row-song-fallback.svg";
continue;
}

Spicetify.CosmosAsync.get(
`sp://core-playlist/v1/playlist/${uri}/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 || "https://cdn.jsdelivr.net/gh/spicetify/spicetify-themes@master/Dribbblish/images/tracklist-row-song-fallback.svg";
});
}
}

DribbblishShared.loadPlaylistImage = loadPlaylistImage;
loadPlaylistImage();

new MutationObserver(loadPlaylistImage)
.observe(listElem, {childList: true});
});

// back shadow
waitForElement([".Root__top-container"], ([topContainer]) => {
const shadow = document.createElement("div");
shadow.id = "dribbblish-back-shadow";
topContainer.prepend(shadow);
});

// allow resizing of the navbar
waitForElement([
".Root__nav-bar .LayoutResizer__input, .Root__nav-bar .LayoutResizer__resize-bar 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();
});

// allow resizing of the buddy feed
waitForElement([".Root__right-sidebar .LayoutResizer__input, .Root__right-sidebar .LayoutResizer__resize-bar input"], ([resizer]) => {
const observer = new MutationObserver(updateVariable);
observer.observe(resizer, { attributes: true, attributeFilter: ["value"] });
function updateVariable() {
let value = resizer.value;
if (value == 280) {
value = 72;
document.documentElement.classList.add("buddyFeed-hide-text");
} else {
document.documentElement.classList.remove("buddyFeed-hide-text");
}
// check if element has two children
const mainNav = topContainer.querySelector(".main-navBar-mainNav");
if (mainNav && mainNav.childElementCount === 1) {
document.documentElement.classList.add("legacy-nav");
legacy();
}
updateVariable();
});

// add fade effect on playlist/folder list
waitForElement([".main-navBar-navBar .os-viewport.os-viewport-native-scrollbars-invisible"], ([scrollNode]) => {
waitForElement([".main-navBar-mainNav .os-viewport.os-viewport-native-scrollbars-invisible"], ([scrollNode]) => {
scrollNode.setAttribute("fade", "bottom");
scrollNode.addEventListener("scroll", () => {
if (scrollNode.scrollTop == 0) {
Expand All @@ -143,26 +35,6 @@ waitForElement([".main-navBar-navBar .os-viewport.os-viewport-native-scrollbars-
});
});

// improve styles at smaller sizes
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");
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() {
// dynamic playback time tooltip
const progBar = document.querySelector(".playback-bar");
Expand All @@ -177,33 +49,106 @@ waitForElement([".Root__main-view .os-resize-observer-host"], ([resizeHost]) =>
tooltip.className = "prog-tooltip";
progBar.append(tooltip);

const progKnob = progBar.querySelector(".progress-bar__slider");

function updateProgTime({ 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";
if (curWidth < ttWidth + 12) {
tooltip.style.left = "12px";
} else if (curWidth > maxWidth - ttWidth - 12) {
tooltip.style.left = String(maxWidth - ttWidth * 2 - 12) + "px";
} else {
tooltip.style.left = String(offsetX - ttWidth) + "px";
tooltip.style.left = String(curWidth - ttWidth) + "px";
}
tooltip.innerText = Spicetify.Player.formatTime(e) + " / " +
Spicetify.Player.formatTime(Spicetify.Player.getDuration());
tooltip.innerText = Spicetify.Player.formatTime(e) + " / " + Spicetify.Player.formatTime(Spicetify.Player.getDuration());
}
Spicetify.Player.addEventListener("onprogress", updateProgTime);
updateProgTime({ data: Spicetify.Player.getProgress() });
})();

Spicetify.CosmosAsync.sub("sp://connect/v1", (state) => {
const isExternal = state.devices.some(a => a.is_active);
if (isExternal) {
root.classList.add("is-connectBarVisible");
} else {
root.classList.remove("is-connectBarVisible");
// LEGACY NAVBAR ONLY

function legacy() {
if (!Spicetify.Platform) {
setTimeout(legacy, 300);
return;
}

let DribbblishShared = {};

// allow resizing of the navbar
waitForElement([".Root__nav-bar .LayoutResizer__resize-bar"], ([resizer]) => {
console.log(resizer);
const observer = new MutationObserver(updateVariable);
observer.observe(resizer, { attributes: true, attributeFilter: ["class"] });
function updateVariable() {
if (resizer.classList.contains("LayoutResizer__resize-bar-east")) {
document.documentElement.style.setProperty("--left-sidebar-width", "72px");
document.documentElement.classList.add("left-sidebar-collapsed");
} else {
document.documentElement.classList.remove("left-sidebar-collapsed");
}
}
updateVariable();
});

// add fade effect on playlist/folder list
waitForElement([".main-navBar-navBar .os-viewport.os-viewport-native-scrollbars-invisible"], ([scrollNode]) => {
scrollNode.setAttribute("fade", "bottom");
scrollNode.addEventListener("scroll", () => {
if (scrollNode.scrollTop == 0) {
scrollNode.setAttribute("fade", "bottom");
} else if (scrollNode.scrollHeight - scrollNode.clientHeight - scrollNode.scrollTop == 0) {
scrollNode.setAttribute("fade", "top");
} else {
scrollNode.setAttribute("fade", "full");
}
});
});

waitForElement([`ul[tabindex="0"]`, `ul[tabindex="0"] .GlueDropTarget--playlists.GlueDropTarget--folders`], ([root, firstItem]) => {
const listElem = firstItem.parentElement;
root.classList.add("dribs-playlist-list");

/** Replace Playlist name with their pictures */
function loadPlaylistImage() {
for (const item of listElem.children) {
let link = item.querySelector("a");
if (!link) continue;

let [_, app, uid] = link.pathname.split("/");
let uri;
if (app === "playlist") {
uri = `spotify:playlist:${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);
}
img.src = base64 || "https://cdn.jsdelivr.net/gh/spicetify/spicetify-themes@master/Dribbblish/images/tracklist-row-song-fallback.svg";
continue;
}

Spicetify.CosmosAsync.get(`sp://core-playlist/v1/playlist/${uri}/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 || "https://cdn.jsdelivr.net/gh/spicetify/spicetify-themes@master/Dribbblish/images/tracklist-row-song-fallback.svg";
});
}
}

DribbblishShared.loadPlaylistImage = loadPlaylistImage;
loadPlaylistImage();

new MutationObserver(loadPlaylistImage).observe(listElem, { childList: true });
});

// filepicker for custom folder images
Expand All @@ -213,54 +158,45 @@ waitForElement([".Root__main-view .os-resize-observer-host"], ([resizeHost]) =>
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.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 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
);
localStorage.setItem("dribbblish:folder-image:" + id, result);
} catch {
Spicetify.showNotification("File too large");
}
DribbblishShared.loadPlaylistImage?.call();
}
};
reader.readAsDataURL(file);
}
};

// context menu items for custom folder images
new Spicetify.ContextMenu.Item("Remove folder image",
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",
"x"
).register();
new Spicetify.ContextMenu.Item("Choose folder image",
new Spicetify.ContextMenu.Item(
"Choose folder image",
([uri]) => {
filePickerInput.uri = uri;
filePickerForm.reset();
filePickerInput.click();
},
([uri]) => Spicetify.URI.isFolder(uri),
"edit",
"edit"
).register();
})();
}
Loading
Loading