mirror of
https://github.com/trafficlunar/jellyfin-spicetify.git
synced 2026-06-13 10:54:52 +00:00
feat: sync volume icons
This commit is contained in:
parent
2cdc4a92d4
commit
43eb8ff31f
1 changed files with 65 additions and 24 deletions
|
|
@ -27,6 +27,13 @@ const BITRATE_MAP: Record<string, string> = {
|
|||
low: "128000",
|
||||
};
|
||||
|
||||
const VOLUME_ICONS: Record<string, string> = {
|
||||
high: `<path d="M9.741.85a.75.75 0 0 1 .375.65v13a.75.75 0 0 1-1.125.65l-6.925-4a3.64 3.64 0 0 1-1.33-4.967 3.64 3.64 0 0 1 1.33-1.332l6.925-4a.75.75 0 0 1 .75 0zm-6.924 5.3a2.14 2.14 0 0 0 0 3.7l5.8 3.35V2.8zm8.683 4.29V5.56a2.75 2.75 0 0 1 0 4.88"></path><path d="M11.5 13.614a5.752 5.752 0 0 0 0-11.228v1.55a4.252 4.252 0 0 1 0 8.127z"></path>`,
|
||||
medium: `<path d="M9.741.85a.75.75 0 0 1 .375.65v13a.75.75 0 0 1-1.125.65l-6.925-4a3.64 3.64 0 0 1-1.33-4.967 3.64 3.64 0 0 1 1.33-1.332l6.925-4a.75.75 0 0 1 .75 0zm-6.924 5.3a2.14 2.14 0 0 0 0 3.7l5.8 3.35V2.8zm8.683 6.087a4.502 4.502 0 0 0 0-8.474v1.65a3 3 0 0 1 0 5.175z"></path>`,
|
||||
low: `<path d="M9.741.85a.75.75 0 0 1 .375.65v13a.75.75 0 0 1-1.125.65l-6.925-4a3.64 3.64 0 0 1-1.33-4.967 3.64 3.64 0 0 1 1.33-1.332l6.925-4a.75.75 0 0 1 .75 0zm-6.924 5.3a2.14 2.14 0 0 0 0 3.7l5.8 3.35V2.8zm8.683 4.29V5.56a2.75 2.75 0 0 1 0 4.88"></path>`,
|
||||
muted: `<path d="M13.86 5.47a.75.75 0 0 0-1.061 0l-1.47 1.47-1.47-1.47A.75.75 0 0 0 8.8 6.53L10.269 8l-1.47 1.47a.75.75 0 1 0 1.06 1.06l1.47-1.47 1.47 1.47a.75.75 0 0 0 1.06-1.06L12.39 8l1.47-1.47a.75.75 0 0 0 0-1.06"></path><path d="M10.116 1.5A.75.75 0 0 0 8.991.85l-6.925 4a3.64 3.64 0 0 0-1.33 4.967 3.64 3.64 0 0 0 1.33 1.332l6.925 4a.75.75 0 0 0 1.125-.649v-1.906a4.7 4.7 0 0 1-1.5-.694v1.3L2.817 9.852a2.14 2.14 0 0 1-.781-2.92c.187-.324.456-.594.78-.782l5.8-3.35v1.3c.45-.313.956-.55 1.5-.694z"></path>`,
|
||||
};
|
||||
|
||||
// Stop Jellfin audio
|
||||
export function stop() {
|
||||
hijackActive.set(false);
|
||||
|
|
@ -117,7 +124,7 @@ export function registerEvents() {
|
|||
|
||||
const results = new Fuse(list, {
|
||||
keys: ["name", "artists"],
|
||||
threshold: 0.7,
|
||||
threshold: 0.75,
|
||||
}).search(`${trackName} ${artists}`);
|
||||
|
||||
console.debug(`[Jellyfin]: Query is "${trackName} ${artists}"`);
|
||||
|
|
@ -188,6 +195,7 @@ export function registerEvents() {
|
|||
oldTime = event.data;
|
||||
});
|
||||
|
||||
const volumeIcon: SVGElement | null = document.querySelector(".volume-bar__icon-button > span > svg");
|
||||
const volumeSlider: HTMLDivElement | null = document.querySelector(".volume-bar__slider-container > div > div");
|
||||
const volumeSliderInput: HTMLInputElement | null = document.querySelector(".volume-bar__slider-container > div > label > input");
|
||||
|
||||
|
|
@ -203,6 +211,7 @@ export function registerEvents() {
|
|||
audio.volume = Math.pow(currentVolume, 3) * 0.425;
|
||||
if (volumeSlider) volumeSlider.style.setProperty("--progress-bar-transform", `${currentVolume * 100}%`);
|
||||
if (volumeSliderInput) volumeSliderInput.value = currentVolume.toString();
|
||||
if (volumeIcon) volumeIcon.innerHTML = VOLUME_ICONS[getExpectedVolumeIcon()];
|
||||
return;
|
||||
}
|
||||
return Reflect.apply(target, thisArg, args);
|
||||
|
|
@ -210,31 +219,63 @@ export function registerEvents() {
|
|||
});
|
||||
|
||||
// Spotify tries to set the volume on the slider to 0 when hijacked, this tries to revert it
|
||||
if (!volumeSlider) return;
|
||||
const observer = new MutationObserver(() => {
|
||||
const transform = volumeSlider.style.getPropertyValue("--progress-bar-transform");
|
||||
if (volumeSlider) {
|
||||
const observer = new MutationObserver(() => {
|
||||
if (!hijackActive.get()) return;
|
||||
const transform = volumeSlider.style.getPropertyValue("--progress-bar-transform");
|
||||
|
||||
const currentPercent = currentVolume * 100;
|
||||
const transformPercent = parseFloat(transform); // strips the "%"
|
||||
const currentPercent = currentVolume * 100;
|
||||
const transformPercent = parseFloat(transform); // strips the "%"
|
||||
|
||||
// 0.1% tolerance (floating point)
|
||||
if (Math.abs(currentPercent - transformPercent) > 0.1) {
|
||||
observer.disconnect(); // prevent re-triggering while we update
|
||||
volumeSlider.style.setProperty("--progress-bar-transform", `${currentPercent}%`);
|
||||
observer.observe(volumeSlider, { attributes: true, attributeFilter: ["style"] });
|
||||
}
|
||||
});
|
||||
observer.observe(volumeSlider, { attributes: true, attributeFilter: ["style"] });
|
||||
// 0.1% tolerance (floating point)
|
||||
if (Math.abs(currentPercent - transformPercent) > 0.1) {
|
||||
observer.disconnect(); // prevent re-triggering while we update
|
||||
volumeSlider.style.setProperty("--progress-bar-transform", `${currentPercent}%`);
|
||||
observer.observe(volumeSlider, { attributes: true, attributeFilter: ["style"] });
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(volumeSlider, { attributes: true, attributeFilter: ["style"] });
|
||||
}
|
||||
|
||||
// Similar to the other observer, but for the input (you'll notice it when scrolling the volume slider)
|
||||
if (!volumeSliderInput) return;
|
||||
const inputObserver = new MutationObserver(() => {
|
||||
// 0.1% tolerance (floating point)
|
||||
if (Math.abs(currentVolume - volumeSliderInput.valueAsNumber) > 0.1) {
|
||||
inputObserver.disconnect(); // prevent re-triggering while we update
|
||||
volumeSliderInput.value = currentVolume.toString();
|
||||
inputObserver.observe(volumeSlider, { attributes: true, attributeFilter: ["value"] });
|
||||
}
|
||||
});
|
||||
inputObserver.observe(volumeSlider, { attributes: true, attributeFilter: ["value"] });
|
||||
if (volumeSliderInput) {
|
||||
const inputObserver = new MutationObserver(() => {
|
||||
if (!hijackActive.get()) return;
|
||||
|
||||
// 0.1% tolerance (floating point)
|
||||
if (Math.abs(currentVolume - volumeSliderInput.valueAsNumber) > 0.1) {
|
||||
inputObserver.disconnect(); // prevent re-triggering while we update
|
||||
volumeSliderInput.value = currentVolume.toString();
|
||||
inputObserver.observe(volumeSliderInput, { attributes: true, attributeFilter: ["value"] });
|
||||
}
|
||||
});
|
||||
|
||||
inputObserver.observe(volumeSliderInput, { attributes: true, attributeFilter: ["value"] });
|
||||
}
|
||||
|
||||
// Similar, but for volume icon (tries to show up as muted)
|
||||
if (volumeIcon) {
|
||||
let currentIcon = "";
|
||||
const observer = new MutationObserver(() => {
|
||||
if (!hijackActive.get()) return;
|
||||
|
||||
const expectedIcon = getExpectedVolumeIcon();
|
||||
if (currentIcon === expectedIcon) return;
|
||||
|
||||
observer.disconnect(); // prevent re-triggering while we update
|
||||
currentIcon = expectedIcon;
|
||||
volumeIcon.innerHTML = VOLUME_ICONS[getExpectedVolumeIcon()];
|
||||
observer.observe(volumeIcon, { childList: true, subtree: true });
|
||||
});
|
||||
|
||||
observer.observe(volumeIcon, { childList: true, subtree: true });
|
||||
}
|
||||
}
|
||||
|
||||
function getExpectedVolumeIcon(): string {
|
||||
if (currentVolume >= 0.66) return "high";
|
||||
if (currentVolume >= 0.33) return "medium";
|
||||
if (currentVolume !== 0) return "low";
|
||||
return "muted";
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue