diff --git a/lib/Caches/ExtendedTrackItem.ts b/lib/Caches/ExtendedTrackItem.ts index e281f211..fc5d08c1 100644 --- a/lib/Caches/ExtendedTrackItem.ts +++ b/lib/Caches/ExtendedTrackItem.ts @@ -25,12 +25,16 @@ export class ExtendedTrackItem { if (trackId === undefined) return undefined; return this._cache[trackId] ?? (this._cache[trackId] = new this(trackId)); } - public async isrcs(): Promise { - const trackItem = this.trackItem(); - if (trackItem?.isrc !== undefined) return [trackItem.isrc]; + public async isrcs(): Promise | undefined> { + let isrcs = []; const recording = await this.recording(); - if (recording?.isrcs !== undefined) return recording.isrcs; + if (recording?.isrcs) isrcs.push(...recording.isrcs); + + const trackItem = this.trackItem(); + if (trackItem?.isrc) isrcs.push(trackItem.isrc); + + return new Set(isrcs); } public trackItem(): TrackItem | undefined { if (this._trackItem !== undefined) return this._trackItem; diff --git a/plugins/RealMAX/src/index.ts b/plugins/RealMAX/src/index.ts index 96ab5ed3..16497bf5 100644 --- a/plugins/RealMAX/src/index.ts +++ b/plugins/RealMAX/src/index.ts @@ -2,11 +2,10 @@ import { ItemId, TrackItem } from "neptune-types/tidal"; import { TrackItemCache } from "../../../lib/Caches/TrackItemCache"; import { fetchIsrcIterable } from "../../../lib/tidalDevApi/isrc"; import { actions, intercept, store } from "@neptune"; -import { PlaybackContext } from "../../../lib/AudioQualityTypes"; import { ExtendedTrackItem } from "../../../lib/Caches/ExtendedTrackItem"; import { Resource } from "../../../lib/tidalDevApi/types/ISRC"; -import { interceptPromise } from "../../../lib/intercept/interceptPromise"; import { debounce } from "../../../lib/debounce"; +import { messageInfo } from "../../../lib/messageLogging"; const hasHiRes = (trackItem: TrackItem) => { const tags = trackItem.mediaMetadata?.tags; @@ -15,23 +14,23 @@ const hasHiRes = (trackItem: TrackItem) => { }; class MaxTrack { - private static readonly _idMap: Record> = {}; - public static async fastCacheMaxId(itemId: ItemId): Promise { - if (itemId === undefined) return undefined; + private static readonly _idMap: Record> = {}; + public static async fastCacheMaxId(itemId: ItemId): Promise { + if (itemId === undefined) return false; return MaxTrack._idMap[itemId]; } - public static async getMaxId(itemId: ItemId | undefined): Promise { - if (itemId === undefined) return undefined; + public static async getMaxId(itemId: ItemId | undefined): Promise { + if (itemId === undefined) return false; const idMapping = MaxTrack._idMap[itemId]; if (idMapping !== undefined) return idMapping; const extTrackItem = await ExtendedTrackItem.get(itemId); const trackItem = extTrackItem?.trackItem(); - if (trackItem !== undefined && hasHiRes(trackItem)) return undefined; + if (trackItem !== undefined && hasHiRes(trackItem)) return false; const isrcs = await extTrackItem?.isrcs(); - if (isrcs === undefined) return (this._idMap[itemId] = Promise.resolve(undefined)); + if (isrcs === undefined) return (this._idMap[itemId] = Promise.resolve(false)); return (this._idMap[itemId] = (async () => { for (const isrc of isrcs) { @@ -44,25 +43,33 @@ class MaxTrack { } } } - return undefined; + return false; })()); } } -// export const onUnload = intercept( -// "playbackControls/TIME_UPDATE", -// debounce(async () => { -// const { elements, currentIndex } = store.getState().playQueue; -// const queueId = elements[currentIndex]?.mediaItemId; +export const onUnload = intercept( + "playbackControls/MEDIA_PRODUCT_TRANSITION", + debounce(async () => { + const { elements, currentIndex } = store.getState().playQueue; + const queueId = elements[currentIndex]?.mediaItemId; + const nextQueueId = elements[currentIndex + 1]?.mediaItemId; -// const maxItem = await MaxTrack.getMaxId(queueId); -// if (maxItem !== undefined) { -// actions.playQueue.clearActiveItems(); -// await interceptPromise(() => actions.content.fetchAndPlayMediaItem({ itemId: maxItem?.id!, itemType: "track", sourceContext: { type: "user" } }), ["playbackControls/MEDIA_PRODUCT_TRANSITION"], []); -// const mediaItemIds = elements.slice(currentIndex + 1).map(({ mediaItemId }) => mediaItemId); -// actions.playQueue.addMediaItemsToQueue({ mediaItemIds, position: "next", options: { overwritePlayQueue: true }, sourceContext: { type: "user" } }); -// } -// // Preload next -// await MaxTrack.getMaxId(elements[currentIndex + 1]?.mediaItemId); -// }, 125) -// ); + const maxItem = await MaxTrack.getMaxId(queueId); + if (maxItem === false) return; + if (maxItem.id !== undefined && nextQueueId !== maxItem.id) { + if (TrackItemCache.get(maxItem.id) === undefined) { + // Force load + const currentPage = window.location.pathname; + actions.router.replace(`/album/${maxItem.album!.id}`); + setTimeout(() => actions.router.replace(currentPage), 50); + } + messageInfo(`Found Max quality for ${maxItem.title}! Adding to queue and skipping...`); + actions.playQueue.addNext({ mediaItemIds: [maxItem.id], context: { type: "user" } }); + actions.playQueue.moveNext(); + } + // Preload next two + MaxTrack.getMaxId(elements[currentIndex + 1]?.mediaItemId); + MaxTrack.getMaxId(elements[currentIndex + 2]?.mediaItemId); + }, 125) +);