diff --git a/CustomApps/lyrics-plus/OptionsMenu.js b/CustomApps/lyrics-plus/OptionsMenu.js index e571302acd..11f27f097d 100644 --- a/CustomApps/lyrics-plus/OptionsMenu.js +++ b/CustomApps/lyrics-plus/OptionsMenu.js @@ -293,7 +293,7 @@ const AdjustmentsMenu = react.memo(({ mode }) => { onChange: (name, value) => { CONFIG.visual[name] = value; localStorage.setItem(`${APP_NAME}:visual:${name}`, value); - name === "delay" && localStorage.setItem(`lyrics-delay:${Spicetify.Player.data.track.uri}`, value); + name === "delay" && localStorage.setItem(`lyrics-delay:${Spicetify.Player.data.item.uri}`, value); lyricContainerUpdate && lyricContainerUpdate(); } }) diff --git a/CustomApps/lyrics-plus/Utils.js b/CustomApps/lyrics-plus/Utils.js index 9c07885fae..7b95f8de5b 100644 --- a/CustomApps/lyrics-plus/Utils.js +++ b/CustomApps/lyrics-plus/Utils.js @@ -261,7 +261,7 @@ class Utils { if (isKaraoke) { if (!lyricContent.endsWith(">")) { // For some reason there are a variety of formats for karaoke lyrics, Wikipedia is also inconsisent in their examples - const endTime = lines[i + 1]?.match(syncedTimestamp)?.[1] || this.formatTime(Number(Spicetify.Player.data.track.metadata.duration)); + const endTime = lines[i + 1]?.match(syncedTimestamp)?.[1] || this.formatTime(Number(Spicetify.Player.data.item.metadata.duration)); lyricContent += `<${endTime}>`; } const karaokeLine = parseKaraokeLine(lyricContent, time); diff --git a/CustomApps/lyrics-plus/index.js b/CustomApps/lyrics-plus/index.js index 51f014f89c..a3a50a1cb8 100644 --- a/CustomApps/lyrics-plus/index.js +++ b/CustomApps/lyrics-plus/index.js @@ -435,7 +435,7 @@ class LyricsContainer extends react.Component { } resetDelay() { - CONFIG.visual.delay = Number(localStorage.getItem(`lyrics-delay:${Spicetify.Player.data.track.uri}`)) || 0; + CONFIG.visual.delay = Number(localStorage.getItem(`lyrics-delay:${Spicetify.Player.data.item.uri}`)) || 0; } async onVersionChange(items, index) { @@ -552,8 +552,8 @@ class LyricsContainer extends react.Component { if (Spicetify.Player?.data?.track) { this.state.explicitMode = this.state.lockMode; - this.currentTrackUri = Spicetify.Player.data.track.uri; - this.fetchLyrics(Spicetify.Player.data.track, this.state.explicitMode); + this.currentTrackUri = Spicetify.Player.data.item.uri; + this.fetchLyrics(Spicetify.Player.data.item, this.state.explicitMode); } this.updateVisualOnConfigChange(); @@ -891,7 +891,7 @@ class LyricsContainer extends react.Component { const mode = CONFIG.modes.findIndex(a => a === label); if (mode !== this.state.mode) { this.setState({ explicitMode: mode }); - this.state.provider !== "local" && this.fetchLyrics(Player.data.track, mode); + this.state.provider !== "local" && this.fetchLyrics(Player.data.item, mode); } }, lockCallback: label => { @@ -900,7 +900,7 @@ class LyricsContainer extends react.Component { mode = -1; } this.setState({ explicitMode: mode, lockMode: mode }); - this.fetchLyrics(Player.data.track, mode); + this.fetchLyrics(Player.data.item, mode); CONFIG.locked = mode; localStorage.setItem("lyrics-plus:lock-mode", mode); } diff --git a/Extensions/autoSkipExplicit.js b/Extensions/autoSkipExplicit.js index f114872496..5956976bf5 100644 --- a/Extensions/autoSkipExplicit.js +++ b/Extensions/autoSkipExplicit.js @@ -23,7 +23,7 @@ const data = Spicetify.Player.data || Spicetify.Queue; if (!data) return; - const isExplicit = data.track.metadata.is_explicit; + const isExplicit = data.item.metadata.is_explicit; if (isExplicit === "true") { Spicetify.Player.next(); } diff --git a/Extensions/autoSkipVideo.js b/Extensions/autoSkipVideo.js index 91ec7ff810..cfef89070d 100644 --- a/Extensions/autoSkipVideo.js +++ b/Extensions/autoSkipVideo.js @@ -9,7 +9,7 @@ const data = Spicetify.Player.data || Spicetify.Queue; if (!data) return; - const meta = data.track.metadata; + const meta = data.item.metadata; // Ads are also video media type so I need to exclude them out. if (meta["media.type"] === "video" && meta.is_advertisement !== "true") { Spicetify.Player.next(); diff --git a/Extensions/bookmark.js b/Extensions/bookmark.js index 264a4e520c..130eb31200 100644 --- a/Extensions/bookmark.js +++ b/Extensions/bookmark.js @@ -276,18 +276,18 @@ function getTrackMeta() { const meta = { - title: Player.data.track.metadata.title, - imageUrl: Player.data.track.metadata.image_url + title: Player.data.item.metadata.title, + imageUrl: Player.data.item.metadata.image_url }; - meta.uri = Player.data.track.uri; + meta.uri = Player.data.item.uri; if (URI.isEpisode(meta.uri)) { - meta.description = Player.data.track.metadata.album_title; + meta.description = Player.data.item.metadata.album_title; } else { - meta.description = Player.data.track.metadata.artist_name; + meta.description = Player.data.item.metadata.artist_name; } const contextUri = URI.fromString(Spicetify.Player.data.context_uri); if (contextUri && (contextUri.type === URI.Type.PLAYLIST || contextUri.type === URI.Type.PLAYLIST_V2 || contextUri.type === URI.Type.ALBUM)) { - meta.context = `/${contextUri.toURLPath()}?uid=${Player.data.track.uid}`; + meta.context = `/${contextUri.toURLPath()}?uid=${Player.data.item.uid}`; } return meta; diff --git a/Extensions/fullAppDisplay.js b/Extensions/fullAppDisplay.js index aea95a0222..b41e1c7e98 100644 --- a/Extensions/fullAppDisplay.js +++ b/Extensions/fullAppDisplay.js @@ -378,7 +378,7 @@ body.video-full-screen.video-full-screen--hide-ui { } async fetchInfo() { - const meta = Spicetify.Player.data.track.metadata; + const meta = Spicetify.Player.data.item.metadata; // prepare title let rawTitle = meta.title; diff --git a/Extensions/popupLyrics.js b/Extensions/popupLyrics.js index e736812cb1..9ea12c71c5 100644 --- a/Extensions/popupLyrics.js +++ b/Extensions/popupLyrics.js @@ -396,9 +396,9 @@ function PopupLyrics() { return; } - const meta = Player.data.track.metadata; + const meta = Player.data.item.metadata; - if (!Spicetify.URI.isTrack(Player.data.track.uri) && !Spicetify.URI.isLocalTrack(Player.data.track.uri)) { + if (!Spicetify.URI.isTrack(Player.data.item.uri) && !Spicetify.URI.isLocalTrack(Player.data.item.uri)) { return; } @@ -408,7 +408,7 @@ function PopupLyrics() { album: meta.album_title, artist: meta.artist_name, title: meta.title, - uri: Player.data.track.uri + uri: Player.data.item.uri }; for (let name of userConfigs.servicesOrder) { diff --git a/Extensions/shuffle+.js b/Extensions/shuffle+.js index 49538f2baf..a392a6430a 100755 --- a/Extensions/shuffle+.js +++ b/Extensions/shuffle+.js @@ -463,26 +463,15 @@ await Spicetify.Platform.PlayerAPI.clearQueue(); - await Spicetify.CosmosAsync.put("sp://player/v2/main/queue", { - queue_revision: Spicetify.Queue?.queueRevision, - next_tracks: list.map(uri => ({ + Spicetify.Platform.PlayerAPI.addToQueue( + list.map(uri => ({ uri, provider: "context", metadata: { is_queued: "false" } - })), - prev_tracks: Spicetify.Queue?.prevTracks - }); - - if (context) { - await Spicetify.CosmosAsync.post("sp://player/v2/main/update", { - context: { - uri: context, - url: "context://" + context - } - }); - } + })) + ); Spicetify.Player.next(); diff --git a/Extensions/trashbin.js b/Extensions/trashbin.js index c038774f58..e6f0d00597 100644 --- a/Extensions/trashbin.js +++ b/Extensions/trashbin.js @@ -185,7 +185,7 @@ THROW_TEXT, trashbinIcon, self => { - const uri = Spicetify.Player.data.track.uri; + const uri = Spicetify.Player.data.item.uri; const uriObj = Spicetify.URI.fromString(uri); const type = uriObj.type; @@ -215,8 +215,8 @@ putDataLocal(); refreshEventListeners(trashbinStatus); setWidgetState( - trashSongList[Spicetify.Player.data.track.uri], - Spicetify.URI.fromString(Spicetify.Player.data.track.uri).type !== Spicetify.URI.Type.TRACK + trashSongList[Spicetify.Player.data.item.uri], + Spicetify.URI.fromString(Spicetify.Player.data.item.uri).type !== Spicetify.URI.Type.TRACK ); function refreshEventListeners(state) { @@ -243,8 +243,8 @@ const data = Spicetify.Player.data || Spicetify.Queue; if (!data) return; - const isBanned = trashSongList[data.track.uri]; - setWidgetState(isBanned, Spicetify.URI.fromString(data.track.uri).type !== Spicetify.URI.Type.TRACK); + const isBanned = trashSongList[data.item.uri]; + setWidgetState(isBanned, Spicetify.URI.fromString(data.item.uri).type !== Spicetify.URI.Type.TRACK); if (userHitBack) { userHitBack = false; @@ -257,7 +257,7 @@ } let uriIndex = 0; - let artistUri = data.track.metadata["artist_uri"]; + let artistUri = data.item.metadata["artist_uri"]; while (artistUri) { if (trashArtistList[artistUri]) { @@ -266,7 +266,7 @@ } uriIndex++; - artistUri = data.track.metadata["artist_uri:" + uriIndex]; + artistUri = data.item.metadata["artist_uri:" + uriIndex]; } } @@ -277,7 +277,7 @@ * @returns {boolean} */ function shouldSkipCurrentTrack(uri, type) { - const curTrack = Spicetify.Player.data.track; + const curTrack = Spicetify.Player.data.item; if (type === Spicetify.URI.Type.TRACK) { if (uri === curTrack.uri) { return true; diff --git a/Extensions/webnowplaying.js b/Extensions/webnowplaying.js index 68df5a9c1c..88f08aff9c 100644 --- a/Extensions/webnowplaying.js +++ b/Extensions/webnowplaying.js @@ -43,18 +43,20 @@ class WNPReduxWebSocket { constructor() { this.init(); - Spicetify.CosmosAsync.sub("sp://player/v2/main", this.updateSpicetifyInfo.bind(this)); + + Spicetify.Player.addEventListener("songchange", ({ data }) => this.updateSpicetifyInfo(data)); + Spicetify.Player.addEventListener("onplaypause", ({ data }) => this.updateSpicetifyInfo(data)); } updateSpicetifyInfo(data) { - if (!data?.track?.metadata) return; - const meta = data.track.metadata; + if (!data?.item?.metadata) return; + const meta = data.item.metadata; this.spicetifyInfo.title = meta.title; this.spicetifyInfo.album = meta.album_title; this.spicetifyInfo.duration = timeInSecondsToString(Math.round(parseInt(meta.duration) / 1000)); - this.spicetifyInfo.state = !data.is_paused ? "PLAYING" : "PAUSED"; - this.spicetifyInfo.repeat = data.options.repeating_track ? "ONE" : data.options.repeating_context ? "ALL" : "NONE"; - this.spicetifyInfo.shuffle = data.options.shuffling_context; + this.spicetifyInfo.state = !data.isPaused ? "PLAYING" : "PAUSED"; + this.spicetifyInfo.repeat = data.repeat === 2 ? "ONE" : data.repeat === 1 ? "ALL" : "NONE"; + this.spicetifyInfo.shuffle = data.shuffle; this.spicetifyInfo.artist = meta.artist_name; let artistCount = 1; while (meta["artist_name:" + artistCount]) { @@ -63,7 +65,7 @@ class WNPReduxWebSocket { } if (!this.spicetifyInfo.artist) this.spicetifyInfo.artist = meta.album_title; // Podcast - Spicetify.Platform.LibraryAPI.contains(data.track.uri).then(([added]) => (this.spicetifyInfo.rating = added ? 5 : 0)); + Spicetify.Platform.LibraryAPI.contains(data.item.uri).then(([added]) => (this.spicetifyInfo.rating = added ? 5 : 0)); const cover = meta.image_xlarge_url; if (cover?.indexOf("localfile") === -1) this.spicetifyInfo.cover = "https://i.scdn.co/image/" + cover.substring(cover.lastIndexOf(":") + 1); diff --git a/jsHelper/spicetifyWrapper.js b/jsHelper/spicetifyWrapper.js index 4c089e2340..173b83adb9 100644 --- a/jsHelper/spicetifyWrapper.js +++ b/jsHelper/spicetifyWrapper.js @@ -581,30 +581,37 @@ window.Spicetify = { }; setInterval(() => { - playerState.current = Spicetify.Platform.PlayerAPI._state; + if ( + objectsAreEqual(Spicetify.Platform.PlayerAPI._state, playerState.cache) || + (!Spicetify.Platform.PlayerAPI._state.item && !Spicetify.Player.data) + ) + return; - if (!objectsAreEqual(playerState.current, playerState.cache)) { - Spicetify.Player.data = Spicetify.Platform.PlayerAPI._state; + if (!Spicetify.Platform.PlayerAPI._state.item) { + Spicetify.Player.data = null; + return; + } - // compatibility - // TODO: remove in next few releases - Spicetify.Player.data["track"] = Spicetify.Player.data.item; - playerState.current = Spicetify.Player.data; + playerState.current = Spicetify.Platform.PlayerAPI._state; + Spicetify.Player.data = playerState.current; - if (playerState.cache?.item.uri !== playerState.current.item.uri) { - const event = new Event("songchange"); - event.data = playerState.current; - Spicetify.Player.dispatchEvent(event); - } + // for compatibility reasons + // TODO: remove in the future + Spicetify.Player.data["track"] = Spicetify.Player.data.item; - if (playerState.cache?.isPaused !== playerState.current.isPaused) { - const event = new Event("onplaypause"); - event.data = playerState.current; - Spicetify.Player.dispatchEvent(event); - } + if (playerState.cache?.item.uri !== playerState.current?.item?.uri) { + const event = new Event("songchange"); + event.data = Spicetify.Player.data; + Spicetify.Player.dispatchEvent(event); + } - playerState.cache = playerState.current; + if (playerState.cache?.isPaused !== playerState.current?.isPaused) { + const event = new Event("onplaypause"); + event.data = Spicetify.Player.data; + Spicetify.Player.dispatchEvent(event); } + + playerState.cache = playerState.current; }, 100); setInterval(() => { @@ -622,7 +629,7 @@ window.Spicetify = { })(); Spicetify.getAudioData = async uri => { - uri = uri || Spicetify.Player.data.track.uri; + uri = uri || Spicetify.Player.data.item.uri; const uriObj = Spicetify.URI.from?.(uri) ?? Spicetify.URI.fromString?.(uri); if (!uriObj || (uriObj.Type || uriObj.type) !== Spicetify.URI.Type.TRACK) { throw "URI is invalid.";