diff --git a/Extensions/popupLyrics.js b/Extensions/popupLyrics.js
index abde9ec914..74f42b552a 100644
--- a/Extensions/popupLyrics.js
+++ b/Extensions/popupLyrics.js
@@ -25,6 +25,8 @@ if (!navigator.serviceWorker) {
PopupLyrics();
}
+let CACHE = {};
+
function PopupLyrics() {
const { Player, CosmosAsync, LocalStorage, ContextMenu } = Spicetify;
@@ -324,7 +326,7 @@ function PopupLyrics() {
musixmatch: {
on: boolLocalStorage("popup-lyrics:services:musixmatch:on"),
call: LyricProviders.fetchMusixmatch,
- desc: `Fully compatible with Spotify. Requires a token that can be retrieved from the official Musixmatch app. Follow instructions on Spicetify Docs.`,
+ desc: "Fully compatible with Spotify. Requires a token that can be retrieved from the official Musixmatch app. If you have problems with retrieving lyrics, try refreshing the token by clicking Refresh Token
button.",
token: LocalStorage.get("popup-lyrics:services:musixmatch:token") || "2005218b74f939209bda92cb633c7380612e14cb7fe92dcd6a780f",
},
spotify: {
@@ -421,9 +423,11 @@ function PopupLyrics() {
let sharedData = {};
- Player.addEventListener("songchange", updateTrack);
+ Player.addEventListener("songchange", () => {
+ updateTrack();
+ });
- async function updateTrack() {
+ async function updateTrack(refresh = false) {
if (!lyricVideoIsOpen) {
return;
}
@@ -443,20 +447,26 @@ function PopupLyrics() {
uri: Player.data.item.uri,
};
- for (const name of userConfigs.servicesOrder) {
- const service = userConfigs.services[name];
- if (!service.on) continue;
- sharedData = { lyrics: [] };
+ if (CACHE?.[info.uri]?.lyrics?.length && !refresh) {
+ sharedData = CACHE[info.uri];
+ } else {
+ for (const name of userConfigs.servicesOrder) {
+ const service = userConfigs.services[name];
+ if (!service.on) continue;
+ sharedData = { lyrics: [] };
+
+ try {
+ const data = await service.call(info);
+ console.log(data);
+ sharedData = data;
+ CACHE[info.uri] = sharedData;
- try {
- const data = await service.call(info);
- console.log(data);
- sharedData = data;
- if (!sharedData.error) {
- return;
+ if (!sharedData.error) {
+ return;
+ }
+ } catch (err) {
+ sharedData = { error: "No lyrics" };
}
- } catch (err) {
- sharedData = { error: "No lyrics" };
}
}
}
@@ -815,11 +825,20 @@ function PopupLyrics() {
function openConfig(event) {
event.preventDefault();
- if (!configContainer) {
+
+ // Reset on reopen
+ if (configContainer) {
+ resetTokenButton(configContainer);
+ } else {
configContainer = document.createElement("div");
configContainer.id = "popup-config-container";
const style = document.createElement("style");
style.innerHTML = `
+.setting-row {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
.setting-row::after {
content: "";
display: table;
@@ -831,13 +850,16 @@ function PopupLyrics() {
align-items: center;
}
.setting-row .col.description {
- float: left;
padding-right: 15px;
cursor: default;
+ width: 50%;
}
.setting-row .col.action {
- float: right;
- text-align: right;
+ justify-content: flex-end;
+ width: 50%;
+}
+.popup-config-col-margin {
+ margin-top: 10px;
}
button.switch {
align-items: center;
@@ -859,6 +881,27 @@ button.switch.small {
height: 22px;
padding: 6px;
}
+button.btn {
+ font-weight: 700;
+ display: block;
+ background-color: rgba(var(--spice-rgb-shadow), .7);
+ border-radius: 500px;
+ transition-duration: 33ms;
+ transition-property: background-color, border-color, color, box-shadow, filter, transform;
+ padding-inline: 15px;
+ border: 1px solid #727272;
+ color: var(--spice-text);
+ min-block-size: 32px;
+ cursor: pointer;
+}
+button.btn:hover {
+ transform: scale(1.04);
+ border-color: var(--spice-text);
+}
+button.btn:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+}
#popup-config-container select {
color: var(--spice-text);
background: rgba(var(--spice-rgb-shadow), .7);
@@ -945,6 +988,13 @@ button.switch.small {
userConfigs.delay = Number(state);
LocalStorage.set("popup-lyrics:delay", state);
});
+ const clearCache = descriptiveElement(
+ createButton("Clear Memory Cache", "Clear Memory Cache", () => {
+ CACHE = {};
+ updateTrack();
+ }),
+ "Loaded lyrics are cached in memory for faster reloading. Press this button to clear the cached lyrics from memory without restarting Spotify."
+ );
const serviceHeader = document.createElement("h2");
serviceHeader.innerText = "Services";
@@ -975,7 +1025,7 @@ button.switch.small {
const id = el.dataset.id;
userConfigs.services[id].on = state;
LocalStorage.set(`popup-lyrics:services:${id}:on`, state);
- updateTrack();
+ updateTrack(true);
}
function posCallback(el, dir) {
@@ -990,23 +1040,28 @@ button.switch.small {
LocalStorage.set("popup-lyrics:services-order", JSON.stringify(userConfigs.servicesOrder));
stackServiceElements();
- updateTrack();
- }
-
- function tokenChangeCallback(el, inputEl) {
- const newVal = inputEl.value;
- const id = el.dataset.id;
- userConfigs.services[id].token = newVal;
- LocalStorage.set(`popup-lyrics:services:${id}:token`, newVal);
- updateTrack();
+ updateTrack(true);
}
for (const name of userConfigs.servicesOrder) {
- userConfigs.services[name].element = createServiceOption(name, userConfigs.services[name], switchCallback, posCallback, tokenChangeCallback);
+ userConfigs.services[name].element = createServiceOption(name, userConfigs.services[name], switchCallback, posCallback);
}
stackServiceElements();
- configContainer.append(style, optionHeader, smooth, center, cover, blurSize, fontSize, ratio, delay, serviceHeader, serviceContainer);
+ configContainer.append(
+ style,
+ optionHeader,
+ smooth,
+ center,
+ cover,
+ blurSize,
+ fontSize,
+ ratio,
+ delay,
+ clearCache,
+ serviceHeader,
+ serviceContainer
+ );
}
Spicetify.PopupModal.display({
title: "Popup Lyrics",
@@ -1084,8 +1139,125 @@ button.switch.small {
return container;
}
+ // if name is null, the element can be used without a description.
+ function createButton(name, defaultValue, callback) {
+ let container;
+
+ if (name) {
+ container = document.createElement("div");
+ container.innerHTML = `
+