generated from uwu/neptune-template
-
-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TidalTags - Fix showTags setting & organize modules
- Loading branch information
Showing
8 changed files
with
190 additions
and
163 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { store } from "@neptune"; | ||
import { TrackItem, MediaItem } from "neptune-types/tidal"; | ||
|
||
export class TrackItemCache { | ||
private static readonly _cache: Map<string, TrackItem> = new Map<string, TrackItem>(); | ||
public static get(trackId: string) { | ||
let mediaItem = TrackItemCache._cache.get(trackId); | ||
if (mediaItem !== undefined) return mediaItem; | ||
const mediaItems: Record<number, MediaItem> = store.getState().content.mediaItems; | ||
for (const itemId in mediaItems) { | ||
const item = mediaItems[itemId]?.item; | ||
if (item?.contentType !== "track") continue; | ||
TrackItemCache._cache.set(itemId, item); | ||
} | ||
mediaItem = TrackItemCache._cache.get(trackId); | ||
if (mediaItem !== undefined) return mediaItem; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export const isElement = (node: Node | undefined): node is Element => node?.nodeType === Node.ELEMENT_NODE; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import { lookupItemQuality, QualityMeta, QualityTag, sortQualityTags } from "../../../lib/AudioQualityTypes"; | ||
import { isElement } from "./lib/isElement"; | ||
|
||
// @ts-expect-error Remove this when types are available | ||
import { storage } from "@plugin"; | ||
import { TrackInfoCache } from "./lib/TrackInfoCache"; | ||
import { TrackItem } from "neptune-types/tidal"; | ||
|
||
const setColumn = (trackRow: Element, name: string, sourceSelector: string, content: HTMLElement, beforeSelector?: string | Element) => { | ||
let column = trackRow.querySelector<HTMLElement>(`div[data-test="${name}"]`); | ||
if (column !== null) return; | ||
|
||
const sourceColumn = trackRow.querySelector<HTMLElement>(sourceSelector); | ||
if (sourceColumn === null) return; | ||
|
||
column = sourceColumn?.cloneNode(true); | ||
if (isElement(column)) { | ||
column.setAttribute("data-test", name); | ||
column.innerHTML = ""; | ||
column.appendChild(content); | ||
return sourceColumn.parentElement!.insertBefore(column, beforeSelector instanceof Element ? beforeSelector : beforeSelector ? trackRow.querySelector(beforeSelector) : sourceColumn); | ||
} | ||
}; | ||
|
||
const ensureColumnHeader = (trackList: Element, name: string, sourceSelector: string, beforeSelector?: string | Element) => { | ||
let columnHeader = trackList.querySelector<HTMLElement>(`span[data-test="${name}"][role="columnheader"]`); | ||
if (columnHeader !== null) return; | ||
|
||
const sourceColumn = trackList.querySelector(sourceSelector); | ||
if (!(sourceColumn instanceof HTMLElement)) return; | ||
|
||
columnHeader = sourceColumn.cloneNode(true); | ||
if ((columnHeader.firstChild?.childNodes?.length ?? -1) > 1) columnHeader.firstChild?.lastChild?.remove(); | ||
columnHeader.setAttribute("data-test", name); | ||
columnHeader.firstChild!.firstChild!.textContent = name; | ||
|
||
return sourceColumn.parentElement!.insertBefore(columnHeader, beforeSelector instanceof Element ? beforeSelector : beforeSelector ? trackList.querySelector(beforeSelector) : sourceColumn); | ||
}; | ||
|
||
export const setInfoColumnHeaders = () => { | ||
for (const trackList of document.querySelectorAll(`div[aria-label="Tracklist"]`)) { | ||
const bitDepthColumn = ensureColumnHeader(trackList, "Depth", `span[class^="timeColumn--"][role="columnheader"]`, `span[class^="timeColumn--"][role="columnheader"]`); | ||
bitDepthColumn?.style.setProperty("min-width", "40px"); | ||
const sampleRateColumn = ensureColumnHeader(trackList, "Sample Rate", `span[class^="timeColumn--"][role="columnheader"]`, bitDepthColumn); | ||
sampleRateColumn?.style.setProperty("min-width", "110px"); | ||
const bitrateColumn = ensureColumnHeader(trackList, "Bitrate", `span[class^="timeColumn--"][role="columnheader"]`, sampleRateColumn); | ||
bitrateColumn?.style.setProperty("min-width", "100px"); | ||
} | ||
}; | ||
|
||
export const setInfoColumns = (trackRow: Element, trackId: string, trackItem: TrackItem) => { | ||
const qualityTag = sortQualityTags(<QualityTag[]>trackItem.mediaMetadata?.tags)[0] ?? "LOW"; | ||
|
||
const audioQuality = lookupItemQuality(qualityTag, trackItem.audioQuality); | ||
if (audioQuality === undefined) return; | ||
|
||
const bitDepthContent = document.createElement("span"); | ||
|
||
const bitDepthColumn = setColumn(trackRow, "Depth", `div[data-test="duration"]`, bitDepthContent, `div[data-test="duration"]`); | ||
bitDepthColumn?.style.setProperty("min-width", "40px"); | ||
|
||
const sampleRateContent = document.createElement("span"); | ||
|
||
const sampleRateColumn = setColumn(trackRow, "Sample Rate", `div[data-test="duration"]`, sampleRateContent, bitDepthColumn); | ||
sampleRateColumn?.style.setProperty("min-width", "110px"); | ||
|
||
const bitrateContent = document.createElement("span"); | ||
|
||
const bitrateColumn = setColumn(trackRow, "Bitrate", `div[data-test="duration"]`, bitrateContent, sampleRateColumn); | ||
bitrateColumn?.style.setProperty("min-width", "100px"); | ||
|
||
if (storage.infoColumnColors) { | ||
const qualityColor = QualityMeta[qualityTag]?.color ?? ""; | ||
bitDepthContent.style.color = qualityColor; | ||
sampleRateContent.style.color = qualityColor; | ||
bitrateContent.style.color = qualityColor; | ||
} | ||
|
||
TrackInfoCache.register(trackId, audioQuality, async (trackInfoP) => { | ||
const trackInfo = await trackInfoP; | ||
if (!!trackInfo?.sampleRate) sampleRateContent.textContent = `${trackInfo.sampleRate / 1000}kHz`; | ||
if (!!trackInfo?.bitDepth) bitDepthContent.textContent = `${trackInfo.bitDepth}bit`; | ||
if (!!trackInfo?.bitrate) bitrateContent.textContent = `${Math.floor(trackInfo.bitrate / 1000)}kbps`; | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// @ts-expect-error Remove this when types are available | ||
import { storage } from "@plugin"; | ||
|
||
import { AudioQuality, QualityMeta, QualityTag } from "../../../lib/AudioQualityTypes"; | ||
import type { TrackItem } from "neptune-types/tidal"; | ||
|
||
export const setQualityTags = (trackRow: Element, trackId: string, mediaItem: TrackItem) => { | ||
let trackTags = mediaItem.mediaMetadata?.tags; | ||
if (trackTags === undefined) return; | ||
|
||
const isLowQuality = mediaItem.audioQuality === AudioQuality.Low || mediaItem.audioQuality === AudioQuality.Lowest; | ||
if (trackTags.length === 1 && trackTags[0] === QualityTag.High && !isLowQuality) return; | ||
|
||
const trackTitle = trackRow.querySelector<HTMLElement>(`[data-test="table-row-title"]`); | ||
if (trackTitle === null) return; | ||
|
||
const span = trackTitle.querySelector(".quality-tag-container") ?? document.createElement("span"); | ||
if (span.getAttribute("track-id") === trackId) return; | ||
|
||
span.className = "quality-tag-container"; | ||
span.setAttribute("track-id", trackId); | ||
|
||
if (isLowQuality) { | ||
const tagElement = document.createElement("span"); | ||
tagElement.className = "quality-tag"; | ||
tagElement.textContent = QualityMeta["LOW"].textContent; | ||
tagElement.style.color = QualityMeta["LOW"].color; | ||
span.appendChild(tagElement); | ||
} | ||
|
||
for (const tag of trackTags) { | ||
if (tag === QualityTag.High) continue; | ||
if (!storage.showAtmosQuality && tag === QualityTag.DolbyAtmos) continue; | ||
|
||
const data = QualityMeta[tag]; | ||
if (data === undefined) continue; | ||
|
||
const tagElement = document.createElement("span"); | ||
tagElement.className = "quality-tag"; | ||
tagElement.textContent = data.textContent; | ||
tagElement.style.color = data.color; | ||
span.appendChild(tagElement); | ||
} | ||
|
||
trackTitle.appendChild(span); | ||
}; |
Oops, something went wrong.