From 7acdeaa0a56945f31c8daeb59c0e0cfc8ee47ac4 Mon Sep 17 00:00:00 2001 From: Grason Chan Date: Sun, 24 Oct 2021 01:28:57 +0800 Subject: [PATCH] feat(Turntable): add heart button and song preview, refactor the "rotate turntable" feature and other js code Happy 1024~ --- Turntable/rotateTurntable.js | 205 ++++++++++++++++++++++++++--------- Turntable/user.css | 49 +++++++++ 2 files changed, 205 insertions(+), 49 deletions(-) diff --git a/Turntable/rotateTurntable.js b/Turntable/rotateTurntable.js index 78c57fd..4c8c8c5 100644 --- a/Turntable/rotateTurntable.js +++ b/Turntable/rotateTurntable.js @@ -1,7 +1,8 @@ window.addEventListener("load", rotateTurntable = () => { + const SpicetifyOrigin = Spicetify.Player.origin; const fadBtn = document.querySelector(".main-topBar-button[title='Full App Display']"); - if (!Spicetify.Player.origin || !fadBtn) { + if (!SpicetifyOrigin?._state || !fadBtn) { setTimeout(rotateTurntable, 250); return; } @@ -14,43 +15,136 @@ window.addEventListener("load", rotateTurntable = () => { `; 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"); - if (!fromEvent && Spicetify.Player.isPlaying() || fromEvent && !playState) { - if (fadArt) fadArt.style.animationPlayState = "running"; - playState = true; + if ( + eventType == "load" && !SpicetifyOrigin._state.isPaused + || + eventType == "playpause" && !isPlaying + || + !eventType && isPlaying + ) { + fadArt?.style.setProperty("animation-play-state", "running"); + if (eventType) isPlaying = true; } else { - if (fadArt) fadArt.style.animationPlayState = "paused"; - playState = false; + fadArt?.style.setProperty("animation-play-state", "paused"); + if (eventType) isPlaying = false; } } - function handleFadDblclick() { + function handleFadBtn(event) { + event.stopPropagation(); + } + + function handleFadControl() { const fadControlsBtns = document.querySelectorAll("#fad-controls button"); 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() { - 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(); - handleFadDblclick(); + handleFadControl(); } function handleBackdrop(fullAppDisplay, setBlurBackdropBtn) { if (!+localStorage.getItem("enableBlurFad")) { - fullAppDisplay.setAttribute("data-is-blur-fad", "true"); + fullAppDisplay.dataset.isBlurFad = "true"; setBlurBackdropBtn.classList.remove("disabled"); localStorage.setItem("enableBlurFad", "1"); } else { - fullAppDisplay.setAttribute("data-is-blur-fad", "false"); + fullAppDisplay.dataset.isBlurFad = "false"; setBlurBackdropBtn.classList.add("disabled"); localStorage.setItem("enableBlurFad", "0"); @@ -74,9 +168,9 @@ window.addEventListener("load", rotateTurntable = () => { `; - settingRowContainer.innerHTML = settingRow; configContainer.insertBefore(settingRowContainer, settingRowReferenceNode); + const configSwitchBtns = document.querySelectorAll("#popup-config-container button.switch"); const setBlurBackdropBtn = document.querySelector("[data-blur-fad]"); @@ -87,58 +181,71 @@ window.addEventListener("load", rotateTurntable = () => { setBlurBackdropBtn.addEventListener("click", () => handleBackdrop(fullAppDisplay, setBlurBackdropBtn)); } - function handleMainInterface() { + function handleMainInterface(fromActive, topbarContentFadeIn) { const mainInterface = document.querySelector("#main"); const mainPlayBtn = document.querySelector(".main-playButton-PlayButton"); const mainTopbarTitle = document.querySelector(".main-entityHeader-topbarTitle"); const billboard = document.querySelector("#view-billboard-ad"); - mainInterface.style.display = "block"; - if (billboard) billboard.closest(".ReactModalPortal").remove(); - adModalStyle.remove(); + if (fromActive) { + if (!topbarContentFadeIn) { + mainPlayBtn?.style.setProperty("opacity", "0", "important"); + mainTopbarTitle?.style.setProperty("opacity", "0", "important"); + } - setTimeout(() => { - mainPlayBtn.style.removeProperty("opacity"); - if (mainTopbarTitle) mainTopbarTitle.style.removeProperty("opacity"); - }, 250); + mainInterface.style.display = "none"; + document.body.append(adModalStyle); + } else { + 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", () => { - 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 fullAppDisplay = document.querySelector("#full-app-display"); - const fadArt = document.querySelector("#fad-art-image"); 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; } - playState - ? fadArt.style.animationPlayState = "running" - : fadArt.style.animationPlayState = "paused"; - - 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); + handleMainInterface("active", topbarContentFadeIn); + handleFadHeart(); + handleTracksNamePreview(); + handleRotate(); }); }); diff --git a/Turntable/user.css b/Turntable/user.css index 5da5ee0..eaea6cc 100644 --- a/Turntable/user.css +++ b/Turntable/user.css @@ -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 */ @media (max-width: 908px) { #fad-foreground { @@ -337,6 +382,10 @@ #fad-foreground { transform: scale(1.2) } + + .song-preview > span { + font-size: 16px + } }