mirror of
https://github.com/meowarex/TidaLuna-Plugins.git
synced 2026-06-18 03:43:10 +10:00
Improve HideUI & Flush controls
This commit is contained in:
@@ -319,30 +319,30 @@ const toggleRadiantLyrics = function (): void {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Create buttons
|
// Create buttons
|
||||||
let resyncLocked = false;
|
let flushLocked = false;
|
||||||
const unlockResync = (): void => {
|
const unlockFlush = (): void => {
|
||||||
resyncLocked = false;
|
flushLocked = false;
|
||||||
const btn = document.querySelector(".resync-lyrics-button") as HTMLButtonElement;
|
const btn = document.querySelector(".flush-lyrics-button") as HTMLButtonElement;
|
||||||
if (btn) {
|
if (btn) {
|
||||||
btn.disabled = false;
|
btn.disabled = false;
|
||||||
btn.style.opacity = "";
|
btn.style.opacity = "";
|
||||||
btn.style.cursor = "";
|
btn.style.cursor = "";
|
||||||
btn.setAttribute("title", "Resync Lyrics");
|
btn.setAttribute("title", "Flush Lyrics");
|
||||||
btn.setAttribute("aria-label", "Resync Lyrics");
|
btn.setAttribute("aria-label", "Flush Lyrics");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const lockResync = (): void => {
|
const lockFlush = (): void => {
|
||||||
resyncLocked = true;
|
flushLocked = true;
|
||||||
const btn = document.querySelector(".resync-lyrics-button") as HTMLButtonElement;
|
const btn = document.querySelector(".flush-lyrics-button") as HTMLButtonElement;
|
||||||
if (btn) {
|
if (btn) {
|
||||||
btn.disabled = true;
|
btn.disabled = true;
|
||||||
btn.style.opacity = "0.3";
|
btn.style.opacity = "0.3";
|
||||||
btn.style.cursor = "not-allowed";
|
btn.style.cursor = "not-allowed";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const disableResyncNoLyrics = (): void => {
|
const disableFlushNoLyrics = (): void => {
|
||||||
resyncLocked = true;
|
flushLocked = true;
|
||||||
const btn = document.querySelector(".resync-lyrics-button") as HTMLButtonElement;
|
const btn = document.querySelector(".flush-lyrics-button") as HTMLButtonElement;
|
||||||
if (btn) {
|
if (btn) {
|
||||||
btn.disabled = true;
|
btn.disabled = true;
|
||||||
btn.style.opacity = "0.3";
|
btn.style.opacity = "0.3";
|
||||||
@@ -352,16 +352,16 @@ const disableResyncNoLyrics = (): void => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const resyncLyrics = async (): Promise<void> => {
|
const flushLyrics = async (): Promise<void> => {
|
||||||
if (resyncLocked) return;
|
if (flushLocked) return;
|
||||||
|
|
||||||
const trackInfo = await getTrackInfo();
|
const trackInfo = await getTrackInfo();
|
||||||
if (!trackInfo) {
|
if (!trackInfo) {
|
||||||
trace.msg.err("Resync: could not get track info");
|
trace.msg.err("Flush: could not get track info");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
lockResync();
|
lockFlush();
|
||||||
|
|
||||||
let params = `?title=${encodeURIComponent(trackInfo.title)}&artist=${encodeURIComponent(trackInfo.artist)}`;
|
let params = `?title=${encodeURIComponent(trackInfo.title)}&artist=${encodeURIComponent(trackInfo.artist)}`;
|
||||||
if (trackInfo.isrc) params += `&isrc=${encodeURIComponent(trackInfo.isrc)}`;
|
if (trackInfo.isrc) params += `&isrc=${encodeURIComponent(trackInfo.isrc)}`;
|
||||||
@@ -370,18 +370,18 @@ const resyncLyrics = async (): Promise<void> => {
|
|||||||
const url = `https://api.atomix.one/rl-api${params}`;
|
const url = `https://api.atomix.one/rl-api${params}`;
|
||||||
try {
|
try {
|
||||||
const clientIP = await getPublicIPv4();
|
const clientIP = await getPublicIPv4();
|
||||||
const resyncHeaders: Record<string, string> = {
|
const flushHeaders: Record<string, string> = {
|
||||||
"P-Access-Token-Id": "58hy4s86",
|
"P-Access-Token-Id": "58hy4s86",
|
||||||
"P-Access-Token": "xjehy2lfg5h5mjwotoxrcqugam",
|
"P-Access-Token": "xjehy2lfg5h5mjwotoxrcqugam",
|
||||||
};
|
};
|
||||||
resyncHeaders["x-client-ip"] = clientIP ?? "null";
|
flushHeaders["x-client-ip"] = clientIP ?? "null";
|
||||||
const res = await fetch(url, { headers: resyncHeaders });
|
const res = await fetch(url, { headers: flushHeaders });
|
||||||
if (res.status === 404) {
|
if (res.status === 404) {
|
||||||
toast("No lyrics found for this track");
|
toast("No lyrics found for this track");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
toastErr(`Resync failed (${res.status})`);
|
toastErr(`Flush failed (${res.status})`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const data = (await res.json()) as LyricsApiResponse & { _flush?: string };
|
const data = (await res.json()) as LyricsApiResponse & { _flush?: string };
|
||||||
@@ -391,7 +391,7 @@ const resyncLyrics = async (): Promise<void> => {
|
|||||||
if (flush) {
|
if (flush) {
|
||||||
toast(flush);
|
toast(flush);
|
||||||
} else {
|
} else {
|
||||||
toast("Lyrics resynced");
|
toast("Lyrics flushed");
|
||||||
}
|
}
|
||||||
if (needsReload || !flush) {
|
if (needsReload || !flush) {
|
||||||
cachedLyricsKey = null;
|
cachedLyricsKey = null;
|
||||||
@@ -399,34 +399,28 @@ const resyncLyrics = async (): Promise<void> => {
|
|||||||
onTrackChange();
|
onTrackChange();
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
toastErr(`Resync error: ${err instanceof Error ? err.message : String(err)}`);
|
toastErr(`Flush error: ${err instanceof Error ? err.message : String(err)}`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const createResyncButton = function (): void {
|
const createFlushButton = function (): void {
|
||||||
safeTimeout(
|
|
||||||
unloads,
|
|
||||||
() => {
|
|
||||||
const closeButton = document.querySelector(
|
const closeButton = document.querySelector(
|
||||||
'[data-test="new-now-playing-close"]',
|
'[data-test="new-now-playing-close"]',
|
||||||
) as HTMLButtonElement;
|
) as HTMLButtonElement;
|
||||||
if (!closeButton || !closeButton.parentElement) {
|
if (!closeButton?.parentElement) return;
|
||||||
safeTimeout(unloads, () => createResyncButton(), 1000);
|
if (document.querySelector(".flush-lyrics-button")) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (document.querySelector(".resync-lyrics-button")) return;
|
|
||||||
const buttonContainer = closeButton.parentElement;
|
const buttonContainer = closeButton.parentElement;
|
||||||
|
|
||||||
const resyncButton = closeButton.cloneNode(false) as HTMLButtonElement;
|
const flushButton = closeButton.cloneNode(false) as HTMLButtonElement;
|
||||||
resyncButton.className = closeButton.className;
|
flushButton.className = closeButton.className;
|
||||||
resyncButton.classList.add("resync-lyrics-button");
|
flushButton.classList.add("flush-lyrics-button");
|
||||||
resyncButton.removeAttribute("data-test");
|
flushButton.removeAttribute("data-test");
|
||||||
resyncButton.setAttribute("type", "button");
|
flushButton.setAttribute("type", "button");
|
||||||
resyncButton.setAttribute("aria-label", "Resync Lyrics");
|
flushButton.setAttribute("aria-label", "Flush Lyrics");
|
||||||
resyncButton.setAttribute("title", "Resync Lyrics");
|
flushButton.setAttribute("title", "Flush Lyrics");
|
||||||
resyncButton.disabled = true;
|
flushButton.disabled = true;
|
||||||
resyncButton.style.opacity = "0.3";
|
flushButton.style.opacity = "0.3";
|
||||||
resyncButton.style.cursor = "not-allowed";
|
flushButton.style.cursor = "not-allowed";
|
||||||
|
|
||||||
const iconSpan = closeButton.querySelector("span");
|
const iconSpan = closeButton.querySelector("span");
|
||||||
const iconSvg = closeButton.querySelector("svg");
|
const iconSvg = closeButton.querySelector("svg");
|
||||||
@@ -440,32 +434,23 @@ const createResyncButton = function (): void {
|
|||||||
useEl.setAttribute("href", "#general__lyrics-sync");
|
useEl.setAttribute("href", "#general__lyrics-sync");
|
||||||
svgEl.appendChild(useEl);
|
svgEl.appendChild(useEl);
|
||||||
spanWrapper.appendChild(svgEl);
|
spanWrapper.appendChild(svgEl);
|
||||||
resyncButton.appendChild(spanWrapper);
|
flushButton.appendChild(spanWrapper);
|
||||||
|
|
||||||
resyncButton.onclick = () => resyncLyrics();
|
flushButton.onclick = () => flushLyrics();
|
||||||
|
|
||||||
const hideBtn = buttonContainer.querySelector(".hide-ui-button");
|
const hideBtn = buttonContainer.querySelector(".hide-ui-button");
|
||||||
buttonContainer.insertBefore(
|
buttonContainer.insertBefore(
|
||||||
resyncButton,
|
flushButton,
|
||||||
hideBtn ?? closeButton,
|
hideBtn ?? closeButton,
|
||||||
);
|
);
|
||||||
},
|
|
||||||
1000,
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const createHideUIButton = function (): void {
|
const createHideUIButton = function (): void {
|
||||||
safeTimeout(
|
|
||||||
unloads,
|
|
||||||
() => {
|
|
||||||
if (!settings.hideUIEnabled) return;
|
if (!settings.hideUIEnabled) return;
|
||||||
const closeButton = document.querySelector(
|
const closeButton = document.querySelector(
|
||||||
'[data-test="new-now-playing-close"]',
|
'[data-test="new-now-playing-close"]',
|
||||||
) as HTMLButtonElement;
|
) as HTMLButtonElement;
|
||||||
if (!closeButton || !closeButton.parentElement) {
|
if (!closeButton?.parentElement) return;
|
||||||
safeTimeout(unloads, () => createHideUIButton(), 1000);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (document.querySelector(".hide-ui-button")) return;
|
if (document.querySelector(".hide-ui-button")) return;
|
||||||
const buttonContainer = closeButton.parentElement;
|
const buttonContainer = closeButton.parentElement;
|
||||||
|
|
||||||
@@ -490,9 +475,6 @@ const createHideUIButton = function (): void {
|
|||||||
|
|
||||||
hideUIButton.onclick = toggleRadiantLyrics;
|
hideUIButton.onclick = toggleRadiantLyrics;
|
||||||
buttonContainer.insertBefore(hideUIButton, closeButton);
|
buttonContainer.insertBefore(hideUIButton, closeButton);
|
||||||
},
|
|
||||||
1000,
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// MARKER: Background Rendering
|
// MARKER: Background Rendering
|
||||||
@@ -1024,7 +1006,7 @@ unloads.add(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clean up action buttons
|
// Clean up action buttons
|
||||||
for (const sel of [".hide-ui-button", ".resync-lyrics-button"]) {
|
for (const sel of [".hide-ui-button", ".flush-lyrics-button"]) {
|
||||||
const btn = document.querySelector(sel);
|
const btn = document.querySelector(sel);
|
||||||
if (btn?.parentNode) btn.parentNode.removeChild(btn);
|
if (btn?.parentNode) btn.parentNode.removeChild(btn);
|
||||||
}
|
}
|
||||||
@@ -3931,7 +3913,7 @@ const startTickLoop = (): void => {
|
|||||||
// Called by track change or style toggle
|
// Called by track change or style toggle
|
||||||
const onTrackChange = async (): Promise<void> => {
|
const onTrackChange = async (): Promise<void> => {
|
||||||
teardown();
|
teardown();
|
||||||
lockResync();
|
lockFlush();
|
||||||
|
|
||||||
const runId = ++trackChangeRunSeq;
|
const runId = ++trackChangeRunSeq;
|
||||||
isTrackChangeRunning = true;
|
isTrackChangeRunning = true;
|
||||||
@@ -3957,7 +3939,7 @@ const onTrackChange = async (): Promise<void> => {
|
|||||||
if (token !== trackChangeToken) return;
|
if (token !== trackChangeToken) return;
|
||||||
if (!response) {
|
if (!response) {
|
||||||
trace.log("RL API: no API lyrics available, falling back to TIDAL lines");
|
trace.log("RL API: no API lyrics available, falling back to TIDAL lines");
|
||||||
disableResyncNoLyrics();
|
disableFlushNoLyrics();
|
||||||
const tidalTexts = getTidalLines();
|
const tidalTexts = getTidalLines();
|
||||||
const romanized = settings.romanizeLyrics
|
const romanized = settings.romanizeLyrics
|
||||||
? await romanizeLines(tidalTexts)
|
? await romanizeLines(tidalTexts)
|
||||||
@@ -4003,7 +3985,7 @@ const onTrackChange = async (): Promise<void> => {
|
|||||||
`[RL-Syllable] Loaded "${trackInfo.title}" by "${trackInfo.artist}" — ${response.data.length} lines`,
|
`[RL-Syllable] Loaded "${trackInfo.title}" by "${trackInfo.artist}" — ${response.data.length} lines`,
|
||||||
);
|
);
|
||||||
|
|
||||||
unlockResync();
|
unlockFlush();
|
||||||
lyricsMode = response.type === "Word" ? "word" : "line-api";
|
lyricsMode = response.type === "Word" ? "word" : "line-api";
|
||||||
if (token !== trackChangeToken) return;
|
if (token !== trackChangeToken) return;
|
||||||
lyricsData =
|
lyricsData =
|
||||||
@@ -4197,15 +4179,15 @@ const setupTrackChangeListener = (): void => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function setupHeaderObserver(): void {
|
function setupHeaderObserver(): void {
|
||||||
const existing = document.querySelector('[data-test="header"]');
|
const injectButtons = () => {
|
||||||
if (existing) {
|
if (!document.querySelector(".flush-lyrics-button")) createFlushButton();
|
||||||
if (!document.querySelector(".resync-lyrics-button")) createResyncButton();
|
|
||||||
if (!document.querySelector(".hide-ui-button")) createHideUIButton();
|
if (!document.querySelector(".hide-ui-button")) createHideUIButton();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (document.querySelector('[data-test="new-now-playing-close"]')) {
|
||||||
|
injectButtons();
|
||||||
}
|
}
|
||||||
observe<HTMLElement>(unloads, '[data-test="header"]', () => {
|
observe<HTMLElement>(unloads, '[data-test="new-now-playing-close"]', injectButtons);
|
||||||
if (!document.querySelector(".resync-lyrics-button")) createResyncButton();
|
|
||||||
if (!document.querySelector(".hide-ui-button")) createHideUIButton();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply seeker color on track change
|
// Apply seeker color on track change
|
||||||
|
|||||||
Reference in New Issue
Block a user