feat(Turntable): add heart button and song preview, refactor the "rotate turntable" feature and other js code

Happy 1024~
This commit is contained in:
Grason Chan 2021-10-24 01:28:57 +08:00
parent 4916222621
commit 7acdeaa0a5
2 changed files with 205 additions and 49 deletions

View File

@ -1,7 +1,8 @@
window.addEventListener("load", rotateTurntable = () => { window.addEventListener("load", rotateTurntable = () => {
const SpicetifyOrigin = Spicetify.Player.origin;
const fadBtn = document.querySelector(".main-topBar-button[title='Full App Display']"); const fadBtn = document.querySelector(".main-topBar-button[title='Full App Display']");
if (!Spicetify.Player.origin || !fadBtn) { if (!SpicetifyOrigin?._state || !fadBtn) {
setTimeout(rotateTurntable, 250); setTimeout(rotateTurntable, 250);
return; return;
} }
@ -14,43 +15,136 @@ window.addEventListener("load", rotateTurntable = () => {
`; `;
adModalStyle.innerHTML = STYLE_FOR_AD_MODAL; adModalStyle.innerHTML = STYLE_FOR_AD_MODAL;
let playState, clickedFadBtn; const fadHeartContainer = document.createElement("div");
const fadHeart = document.createElement("button");
const fadHeartSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
fadHeartContainer.classList.add("fad-heart-container");
fadHeart.classList.add("fad-heart");
fadHeartSvg.setAttribute("width", "16");
fadHeartSvg.setAttribute("height", "16");
fadHeartSvg.setAttribute("viewBox", "0 0 16 16");
fadHeart.appendChild(fadHeartSvg);
fadHeartContainer.appendChild(fadHeart);
function handleRotate(fromEvent) { const songPreviewContainer = document.createElement("div");
const previousSong = document.createElement("button");
const nextSong = document.createElement("button");
songPreviewContainer.classList.add("song-preview");
songPreviewContainer.append(previousSong, nextSong);
let isPlaying, clickedFadBtn;
function handleRotate(eventType) {
const fadArt = document.querySelector("#fad-art-image"); const fadArt = document.querySelector("#fad-art-image");
if (!fromEvent && Spicetify.Player.isPlaying() || fromEvent && !playState) { if (
if (fadArt) fadArt.style.animationPlayState = "running"; eventType == "load" && !SpicetifyOrigin._state.isPaused
playState = true; ||
eventType == "playpause" && !isPlaying
||
!eventType && isPlaying
) {
fadArt?.style.setProperty("animation-play-state", "running");
if (eventType) isPlaying = true;
} else { } else {
if (fadArt) fadArt.style.animationPlayState = "paused"; fadArt?.style.setProperty("animation-play-state", "paused");
playState = false; if (eventType) isPlaying = false;
} }
} }
function handleFadDblclick() { function handleFadBtn(event) {
event.stopPropagation();
}
function handleFadControl() {
const fadControlsBtns = document.querySelectorAll("#fad-controls button"); const fadControlsBtns = document.querySelectorAll("#fad-controls button");
for (const fadControl of fadControlsBtns) { for (const fadControl of fadControlsBtns) {
fadControl.addEventListener("dblclick", event => event.stopPropagation()); fadControl.addEventListener("dblclick", handleFadBtn);
} }
} }
function handleFadHeart(fromEvent) {
const isFadHeartContainer = document.querySelector(".fad-heart-container");
const stateItem = SpicetifyOrigin._state.item;
if (stateItem.isLocal || stateItem.type == "ad") {
isFadHeartContainer?.remove();
return;
}
const fadFg = document.querySelector("#fad-foreground");
const fadHeartState = Spicetify.Player.getHeart();
if (!fromEvent && fadFg && !isFadHeartContainer) fadFg.appendChild(fadHeartContainer);
if (!fromEvent && fadHeartState || fromEvent && !fadHeartState) {
fadHeartSvg.innerHTML = Spicetify.SVGIcons["heart-active"];
fadHeart.classList.add("checked");
} else {
fadHeartSvg.innerHTML = Spicetify.SVGIcons.heart;
fadHeart.classList.remove("checked");
}
if (fromEvent) Spicetify.Player.toggleHeart();
}
function handleTracksNamePreview() {
const prevTracks = Spicetify.Queue.prevTracks;
const nextTracks = Spicetify.Queue.nextTracks;
// let prevTracksIndexRefer = 1;
// let nextTracksIndexRefer = 0;
// while (
// prevTracks[prevTracks.length - prevTracksIndexRefer].metadata.hidden
// ||
// prevTracks[prevTracks.length - prevTracksIndexRefer].provider == "ad"
// ) ++prevTracksIndexRefer;
// previousSong.innerHTML = `< ${prevTracks[prevTracks.length - prevTracksIndexRefer].metadata.title}`;
// while (
// nextTracks[nextTracksIndexRefer].metadata.hidden
// ||
// nextTracks[nextTracksIndexRefer].provider == "ad"
// ) ++nextTracksIndexRefer;
// nextSong.innerHTML = `${nextTracks[nextTracksIndexRefer].metadata.title} >`;
trackCondition = element => !element.contextTrack.metadata.hidden && element.provider != "ad";
const prevTrack = prevTracks.slice().reverse().find(trackCondition);
previousSong.innerHTML = `< ${prevTrack.contextTrack.metadata.title}`;
const nextTrack = nextTracks.find(trackCondition);
nextSong.innerHTML = `${nextTrack.contextTrack.metadata.title} >`;
}
function handleConfigSwitch() { function handleConfigSwitch() {
document.querySelector("generic-modal").remove(); const fullAppDisplay = document.querySelector("#full-app-display");
const fadFg = document.querySelector("#fad-foreground");
const genericModal = document.querySelector("generic-modal");
const stateItem = SpicetifyOrigin._state.item;
if (!stateItem.isLocal && stateItem.type != "ad") fadFg.appendChild(fadHeartContainer);
fullAppDisplay.appendChild(songPreviewContainer);
genericModal.remove();
handleRotate(); handleRotate();
handleFadDblclick(); handleFadControl();
} }
function handleBackdrop(fullAppDisplay, setBlurBackdropBtn) { function handleBackdrop(fullAppDisplay, setBlurBackdropBtn) {
if (!+localStorage.getItem("enableBlurFad")) { if (!+localStorage.getItem("enableBlurFad")) {
fullAppDisplay.setAttribute("data-is-blur-fad", "true"); fullAppDisplay.dataset.isBlurFad = "true";
setBlurBackdropBtn.classList.remove("disabled"); setBlurBackdropBtn.classList.remove("disabled");
localStorage.setItem("enableBlurFad", "1"); localStorage.setItem("enableBlurFad", "1");
} else { } else {
fullAppDisplay.setAttribute("data-is-blur-fad", "false"); fullAppDisplay.dataset.isBlurFad = "false";
setBlurBackdropBtn.classList.add("disabled"); setBlurBackdropBtn.classList.add("disabled");
localStorage.setItem("enableBlurFad", "0"); localStorage.setItem("enableBlurFad", "0");
@ -74,9 +168,9 @@ window.addEventListener("load", rotateTurntable = () => {
</div> </div>
</div> </div>
`; `;
settingRowContainer.innerHTML = settingRow; settingRowContainer.innerHTML = settingRow;
configContainer.insertBefore(settingRowContainer, settingRowReferenceNode); configContainer.insertBefore(settingRowContainer, settingRowReferenceNode);
const configSwitchBtns = document.querySelectorAll("#popup-config-container button.switch"); const configSwitchBtns = document.querySelectorAll("#popup-config-container button.switch");
const setBlurBackdropBtn = document.querySelector("[data-blur-fad]"); const setBlurBackdropBtn = document.querySelector("[data-blur-fad]");
@ -87,58 +181,71 @@ window.addEventListener("load", rotateTurntable = () => {
setBlurBackdropBtn.addEventListener("click", () => handleBackdrop(fullAppDisplay, setBlurBackdropBtn)); setBlurBackdropBtn.addEventListener("click", () => handleBackdrop(fullAppDisplay, setBlurBackdropBtn));
} }
function handleMainInterface() { function handleMainInterface(fromActive, topbarContentFadeIn) {
const mainInterface = document.querySelector("#main"); const mainInterface = document.querySelector("#main");
const mainPlayBtn = document.querySelector(".main-playButton-PlayButton"); const mainPlayBtn = document.querySelector(".main-playButton-PlayButton");
const mainTopbarTitle = document.querySelector(".main-entityHeader-topbarTitle"); const mainTopbarTitle = document.querySelector(".main-entityHeader-topbarTitle");
const billboard = document.querySelector("#view-billboard-ad"); const billboard = document.querySelector("#view-billboard-ad");
mainInterface.style.display = "block"; if (fromActive) {
if (billboard) billboard.closest(".ReactModalPortal").remove(); if (!topbarContentFadeIn) {
adModalStyle.remove(); mainPlayBtn?.style.setProperty("opacity", "0", "important");
mainTopbarTitle?.style.setProperty("opacity", "0", "important");
}
setTimeout(() => { mainInterface.style.display = "none";
mainPlayBtn.style.removeProperty("opacity"); document.body.append(adModalStyle);
if (mainTopbarTitle) mainTopbarTitle.style.removeProperty("opacity"); } else {
}, 250); mainInterface.style.display = "block";
billboard?.closest(".ReactModalPortal").remove();
adModalStyle.remove();
setTimeout(() => {
mainPlayBtn?.style.removeProperty("opacity");
mainTopbarTitle?.style.removeProperty("opacity");
}, 250);
}
} }
handleRotate(); handleRotate("load");
Spicetify.Player.addEventListener("onplaypause", () => handleRotate(true)); Spicetify.Player.addEventListener("onplaypause", () => handleRotate("playpause"));
Spicetify.Player.addEventListener("songchange", () => {
setTimeout(() => {
handleFadHeart();
handleTracksNamePreview();
}, 500);
});
fadHeart.addEventListener("click", () => handleFadHeart(true));
previousSong.addEventListener("click", () => SpicetifyOrigin.skipToPrevious());
nextSong.addEventListener("click", () => SpicetifyOrigin.skipToNext());
fadHeart.addEventListener("dblclick", handleFadBtn);
previousSong.addEventListener("dblclick", handleFadBtn);
nextSong.addEventListener("dblclick", handleFadBtn);
fadBtn.addEventListener("click", () => { fadBtn.addEventListener("click", () => {
const mainInterface = document.querySelector("#main");
const mainPlayBtn = document.querySelector(".main-playButton-PlayButton");
const mainTopbarTitle = document.querySelector(".main-entityHeader-topbarTitle");
const topbarContentFadeIn = document.querySelector(".main-entityHeader-topbarContentFadeIn"); const topbarContentFadeIn = document.querySelector(".main-entityHeader-topbarContentFadeIn");
const fullAppDisplay = document.querySelector("#full-app-display"); const fullAppDisplay = document.querySelector("#full-app-display");
const fadArt = document.querySelector("#fad-art-image");
if (!clickedFadBtn) { if (!clickedFadBtn) {
if (+localStorage.getItem("enableBlurFad")) fullAppDisplay.setAttribute("data-is-blur-fad", "true"); if (+localStorage.getItem("enableBlurFad")) fullAppDisplay.dataset.isBlurFad = "true";
fullAppDisplay.appendChild(songPreviewContainer);
// if (!songPreviewContainer.textContent.length) handleTracksNamePreview();
handleFadControl();
fullAppDisplay.addEventListener("contextmenu", () => handleContextMenu(fullAppDisplay), { once: true });
fullAppDisplay.addEventListener("dblclick", () => handleMainInterface());
clickedFadBtn = true; clickedFadBtn = true;
} }
playState handleMainInterface("active", topbarContentFadeIn);
? fadArt.style.animationPlayState = "running" handleFadHeart();
: fadArt.style.animationPlayState = "paused"; handleTracksNamePreview();
handleRotate();
handleFadDblclick();
if (!topbarContentFadeIn) {
mainPlayBtn.style.setProperty("opacity", "0", "important");
if (mainTopbarTitle) mainTopbarTitle.style.setProperty("opacity", "0", "important");
}
mainInterface.style.display = "none";
document.body.append(adModalStyle);
fullAppDisplay.addEventListener("contextmenu", () => {
if (!document.querySelector("[data-blur-fad]")) handleContextMenu(fullAppDisplay);
});
fullAppDisplay.addEventListener("dblclick", handleMainInterface);
}); });
}); });

View File

@ -321,6 +321,51 @@
} }
/* Full App Display - heart */
.fad-heart-container {
width: 40px;
height: 40px;
display: flex;
justify-content: center;
align-items: center
}
.fad-heart {
width: 16px;
height: 16px;
padding: unset !important
}
.fad-heart svg {
fill: #ccc
}
.fad-heart svg:hover,
.fad-heart.checked svg {
fill: var(--spotify-main-color)
}
/* Full App Display - song preview */
.song-preview {
width: 100%;
padding: 0 10%;
position: absolute;
bottom: 20px;
display: flex;
justify-content: space-between;
}
.song-preview > button {
font-size: 14px;
color: #ccc !important
}
.song-preview > button:hover {
color: #fff !important
}
/* Responsive */ /* Responsive */
@media (max-width: 908px) { @media (max-width: 908px) {
#fad-foreground { #fad-foreground {
@ -337,6 +382,10 @@
#fad-foreground { #fad-foreground {
transform: scale(1.2) transform: scale(1.2)
} }
.song-preview > span {
font-size: 16px
}
} }