Changed up redundant code, and fixed the pause bug
The issue with the 5 min pause bug was that the pause function was not properly resetting the state of the artwork, So it would say its not playing, while showing the artwork as if it was playing.
And the redundant code was just a few lines that were repeated in multiple places, so I consolidated them into a single function to improve maintainability.
Who made Javascript? Why is it so hard. 😭
This commit is contained in:
112
content.js
112
content.js
@ -9,6 +9,12 @@ const defaultArtwork = "https://placehold.co/150/1E1F22/FFF?text=Nothing%20playi
|
|||||||
const pausedTimeout = 300000; // 5 minutes
|
const pausedTimeout = 300000; // 5 minutes
|
||||||
const metadataFetchInterval = 1000; // 1 second
|
const metadataFetchInterval = 1000; // 1 second
|
||||||
|
|
||||||
|
// Cache for artwork base64 by URL
|
||||||
|
const artworkBase64Cache = {
|
||||||
|
lastArtworkUrl: null,
|
||||||
|
lastArtworkBase64: null
|
||||||
|
};
|
||||||
|
|
||||||
async function imageUrlToBase64(url) {
|
async function imageUrlToBase64(url) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
@ -25,63 +31,72 @@ async function imageUrlToBase64(url) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache for artwork base64 by URL
|
|
||||||
const artworkBase64Cache = {
|
|
||||||
lastArtworkUrl: null,
|
|
||||||
lastArtworkBase64: null
|
|
||||||
};
|
|
||||||
|
|
||||||
async function getNowPlayingData() {
|
async function getNowPlayingData() {
|
||||||
const audio = document.querySelector('audio#apple-music-player');
|
const audio = document.querySelector('audio#apple-music-player');
|
||||||
|
|
||||||
// From PreMiD Apple Music Presence
|
// From PreMiD Apple Music Presence
|
||||||
const video = document.querySelector('apple-music-video-player')?.shadowRoot
|
const video = document.querySelector('apple-music-video-player')?.shadowRoot
|
||||||
?.querySelector('amp-window-takeover > .container > amp-video-player-internal')
|
?.querySelector('amp-window-takeover > .container > amp-video-player-internal')?.shadowRoot
|
||||||
?.shadowRoot?.querySelector('amp-video-player')?.shadowRoot
|
?.querySelector('amp-video-player')?.shadowRoot
|
||||||
?.querySelector('div#video-container')?.querySelector('video#apple-music-video-player');
|
?.querySelector('div#video-container > video#apple-music-video-player');
|
||||||
|
|
||||||
const media = video || audio;
|
const media = video || audio;
|
||||||
|
const timestampInput = document.querySelector('amp-lcd.lcd.lcd__music')?.shadowRoot
|
||||||
|
?.querySelector('input#playback-progress[aria-valuenow][aria-valuemax]');
|
||||||
|
|
||||||
|
const defaultArtworkBase64 = await imageUrlToBase64(defaultArtwork);
|
||||||
|
|
||||||
if (!media) {
|
if (!media) {
|
||||||
pauseStartTime = null;
|
pauseStartTime = null;
|
||||||
return {
|
return {
|
||||||
details: "Nothing playing",
|
details: "Nothing playing",
|
||||||
state: "",
|
state: "",
|
||||||
image: defaultArtwork,
|
paused: true,
|
||||||
paused: true
|
artworkBase64: defaultArtworkBase64
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// From PreMiD Apple Music Presence
|
|
||||||
const timestampInput = document.querySelector('amp-lcd.lcd.lcd__music')?.shadowRoot
|
|
||||||
?.querySelector('input#playback-progress[aria-valuenow][aria-valuemax]');
|
|
||||||
|
|
||||||
const paused = media.paused || media.readyState <= 2;
|
const paused = media.paused || media.readyState <= 2;
|
||||||
const metadata = navigator.mediaSession?.metadata || {};
|
const metadata = navigator.mediaSession?.metadata || {};
|
||||||
const title = metadata.title || media.title || "Unknown Title";
|
const title = metadata.title || media.title || "Unknown Title";
|
||||||
const album = metadata.album || "Unknown Album";
|
|
||||||
const artist = metadata.artist || "Unknown Artist";
|
const artist = metadata.artist || "Unknown Artist";
|
||||||
|
const album = metadata.album || "Unknown Album";
|
||||||
const artworkSrc = Array.isArray(metadata.artwork) && metadata.artwork[0]?.src
|
const artworkSrc = Array.isArray(metadata.artwork) && metadata.artwork[0]?.src
|
||||||
? metadata.artwork[0].src
|
? metadata.artwork[0].src
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
|
let artworkBase64 = null;
|
||||||
const largeImageKey = artworkSrc?.replace(/\d+x\d+[a-z]*/i, '150x150bb'); // More robust for Apple Music artwork URLs
|
const largeImageKey = artworkSrc?.replace(/\d+x\d+[a-z]*/i, '150x150bb'); // More robust for Apple Music artwork URLs
|
||||||
|
|
||||||
let artworkBase64 = null;
|
if (largeImageKey) {
|
||||||
if (artworkSrc) {
|
if (artworkBase64Cache.lastArtworkUrl !== largeImageKey) {
|
||||||
if (artworkBase64Cache.lastArtworkUrl === largeImageKey && artworkBase64Cache.lastArtworkBase64) {
|
|
||||||
artworkBase64 = artworkBase64Cache.lastArtworkBase64;
|
|
||||||
} else {
|
|
||||||
artworkBase64 = await imageUrlToBase64(largeImageKey);
|
artworkBase64 = await imageUrlToBase64(largeImageKey);
|
||||||
artworkBase64Cache.lastArtworkUrl = largeImageKey;
|
artworkBase64Cache.lastArtworkUrl = largeImageKey;
|
||||||
artworkBase64Cache.lastArtworkBase64 = artworkBase64;
|
artworkBase64Cache.lastArtworkBase64 = artworkBase64;
|
||||||
|
} else {
|
||||||
|
artworkBase64 = artworkBase64Cache.lastArtworkBase64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentTime = timestampInput ? Number(timestampInput.getAttribute('aria-valuenow')) : (media.currentTime || 0);
|
if (paused) {
|
||||||
const duration = timestampInput ? Number(timestampInput.getAttribute('aria-valuemax')) : (media.duration || 0);
|
pauseStartTime ??= Date.now();
|
||||||
|
if (Date.now() - pauseStartTime >= pausedTimeout) {
|
||||||
|
return {
|
||||||
|
details: "Nothing playing",
|
||||||
|
state: "",
|
||||||
|
paused: true,
|
||||||
|
artworkBase64: defaultArtworkBase64
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pauseStartTime = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentTime = timestampInput ? Number(timestampInput.getAttribute('aria-valuenow')) : media.currentTime || 0;
|
||||||
|
const duration = timestampInput ? Number(timestampInput.getAttribute('aria-valuemax')) : media.duration || 0;
|
||||||
const nowUnix = Math.floor(Date.now() / metadataFetchInterval);
|
const nowUnix = Math.floor(Date.now() / metadataFetchInterval);
|
||||||
const commonData = {
|
|
||||||
|
return {
|
||||||
details: title,
|
details: title,
|
||||||
state: artist,
|
state: artist,
|
||||||
album,
|
album,
|
||||||
@ -89,23 +104,7 @@ async function getNowPlayingData() {
|
|||||||
currentTime,
|
currentTime,
|
||||||
startTimestamp: nowUnix - Math.floor(currentTime),
|
startTimestamp: nowUnix - Math.floor(currentTime),
|
||||||
endTimestamp: nowUnix + Math.floor(Math.max(0, duration - currentTime)),
|
endTimestamp: nowUnix + Math.floor(Math.max(0, duration - currentTime)),
|
||||||
duration
|
duration,
|
||||||
};
|
|
||||||
|
|
||||||
if (paused) {
|
|
||||||
if (!pauseStartTime) pauseStartTime = Date.now();
|
|
||||||
if (Date.now() - pauseStartTime >= pausedTimeout) {
|
|
||||||
return {
|
|
||||||
details: "Not playing",
|
|
||||||
image: defaultArtwork,
|
|
||||||
state: "",
|
|
||||||
paused: true
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...commonData,
|
|
||||||
artworkBase64
|
artworkBase64
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -129,11 +128,7 @@ async function sendNowPlaying() {
|
|||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'Authorization': `Bearer ${token}`
|
'Authorization': `Bearer ${token}`
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({ ...noArtData, details, state })
|
||||||
...noArtData,
|
|
||||||
details,
|
|
||||||
state
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
console.log('Now playing data sent:', details, '-', state);
|
console.log('Now playing data sent:', details, '-', state);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -142,11 +137,7 @@ async function sendNowPlaying() {
|
|||||||
|
|
||||||
// Only send artwork when song changes
|
// Only send artwork when song changes
|
||||||
const currentTrackKey = `${details} - ${state}`;
|
const currentTrackKey = `${details} - ${state}`;
|
||||||
if (
|
if (artworkEndpoint && artworkBase64 && currentTrackKey !== lastSentArtworkKey) {
|
||||||
artworkEndpoint &&
|
|
||||||
artworkBase64 &&
|
|
||||||
currentTrackKey !== lastSentArtworkKey
|
|
||||||
) {
|
|
||||||
try {
|
try {
|
||||||
await fetch(artworkEndpoint, {
|
await fetch(artworkEndpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@ -181,27 +172,24 @@ function safeCall(fn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
function startNowPlayingLoop() {
|
function startNowPlayingLoop() {
|
||||||
if (window._nowPlayingIntervalSet) return;
|
if (!window._nowPlayingIntervalSet) {
|
||||||
|
|
||||||
window._nowPlayingIntervalSet = true;
|
window._nowPlayingIntervalSet = true;
|
||||||
|
|
||||||
intervalId = setInterval(() => safeCall(sendNowPlaying), metadataFetchInterval);
|
intervalId = setInterval(() => safeCall(sendNowPlaying), metadataFetchInterval);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!window._nowPlayingExtensionLogged) {
|
if (!window._nowPlayingExtensionLogged) {
|
||||||
console.log('Apple Music Now Playing Extension made by Sophia Atkinson with help from PreMiD contributors');
|
console.log('Apple Music Now Playing Extension made by Sophia Atkinson with help from PreMiD contributors');
|
||||||
window._nowPlayingExtensionLogged = true;
|
window._nowPlayingExtensionLogged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof chrome !== "undefined" && chrome.storage && chrome.storage.sync) {
|
if (chrome?.storage?.sync) {
|
||||||
chrome.storage.sync.get(['endpoint', 'artworkEndpoint', 'token'], (result) => {
|
chrome.storage.sync.get(['endpoint', 'artworkEndpoint', 'token'], result => {
|
||||||
if (chrome.runtime.lastError) {
|
if (chrome.runtime.lastError) {
|
||||||
console.error("Failed to load settings:", chrome.runtime.lastError.message);
|
console.error("Failed to load settings:", chrome.runtime.lastError.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
({ endpoint, artworkEndpoint, token } = result);
|
||||||
endpoint = result.endpoint;
|
|
||||||
artworkEndpoint = result.artworkEndpoint;
|
|
||||||
token = result.token;
|
|
||||||
|
|
||||||
if (!endpoint || !token) {
|
if (!endpoint || !token) {
|
||||||
console.error("No endpoint/token configured.");
|
console.error("No endpoint/token configured.");
|
||||||
@ -224,9 +212,7 @@ new MutationObserver(() => {
|
|||||||
window._nowPlayingIntervalSet = false;
|
window._nowPlayingIntervalSet = false;
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (!window._nowPlayingIntervalSet) {
|
if (!window._nowPlayingIntervalSet) startNowPlayingLoop();
|
||||||
startNowPlayingLoop();
|
|
||||||
}
|
|
||||||
}, metadataFetchInterval);
|
}, metadataFetchInterval);
|
||||||
}
|
}
|
||||||
}).observe(document, { subtree: true, childList: true });
|
}).observe(document, { subtree: true, childList: true });
|
||||||
|
Reference in New Issue
Block a user