mirror of
https://github.com/meowarex/TidaLuna-Plugins.git
synced 2026-06-18 03:43:10 +10:00
Updated Settings
This commit is contained in:
@@ -2,7 +2,7 @@ import { ReactiveStore } from "@luna/core";
|
||||
import { LunaSettings, LunaNumberSetting, LunaSwitchSetting, LunaTextSetting } from "@luna/ui";
|
||||
import React from "react";
|
||||
|
||||
export type ColoramaMode = "single" | "gradient" | "auto-single" | "auto-gradient" | "rainbow";
|
||||
export type ColoramaMode = "single" | "gradient-experimental" | "cover" | "cover-gradient";
|
||||
|
||||
export const settings = await ReactiveStore.getPluginStorage("ColoramaLyrics", {
|
||||
enabled: true,
|
||||
@@ -15,7 +15,6 @@ export const settings = await ReactiveStore.getPluginStorage("ColoramaLyrics", {
|
||||
gradientEnd: "#AAFFFF",
|
||||
gradientEndAlpha: 100,
|
||||
gradientAngle: 0,
|
||||
rainbowSpeed: 8,
|
||||
customColors: [] as string[],
|
||||
excludeInactive: false
|
||||
});
|
||||
@@ -30,7 +29,6 @@ export const Settings = () => {
|
||||
const [gradientEnd, setGradientEnd] = React.useState(settings.gradientEnd);
|
||||
const [gradientEndAlpha, setGradientEndAlpha] = React.useState<number>(settings.gradientEndAlpha ?? 100);
|
||||
const [gradientAngle, setGradientAngle] = React.useState(settings.gradientAngle);
|
||||
const [rainbowSpeed, setRainbowSpeed] = React.useState<number>(settings.rainbowSpeed ?? 8);
|
||||
const [customInput, setCustomInput] = React.useState(settings.singleColor);
|
||||
const [customColors, setCustomColors] = React.useState(settings.customColors);
|
||||
const [showPicker, setShowPicker] = React.useState(false);
|
||||
@@ -129,8 +127,10 @@ export const Settings = () => {
|
||||
|
||||
{/* Mode selection via dropdown (aligned right) */}
|
||||
<div style={{ padding: "8px 0", display: "flex", alignItems: "center", gap: 12 }}>
|
||||
<div style={{ fontWeight: "normal", fontSize: "1.075rem" }}>Mode</div>
|
||||
<div style={{ opacity: 0.7, fontSize: 14 }}>Choose how lyrics are colored</div>
|
||||
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||
<div style={{ fontWeight: "normal", fontSize: "1.075rem" }}>Mode</div>
|
||||
<div style={{ opacity: 0.7, fontSize: 14 }}>Choose how lyrics are colored</div>
|
||||
</div>
|
||||
<select
|
||||
value={mode}
|
||||
onChange={(e) => {
|
||||
@@ -150,10 +150,9 @@ export const Settings = () => {
|
||||
}}
|
||||
>
|
||||
<option value="single" style={{ color: '#000', background: '#fff' }}>Single</option>
|
||||
<option value="gradient" style={{ color: '#000', background: '#fff' }}>Gradient</option>
|
||||
<option value="auto-single" style={{ color: '#000', background: '#fff' }}>Auto (Cover)</option>
|
||||
<option value="auto-gradient" style={{ color: '#000', background: '#fff' }}>Auto Gradient</option>
|
||||
<option value="rainbow" style={{ color: '#000', background: '#fff' }}>Rainbow</option>
|
||||
<option value="gradient-experimental" style={{ color: '#000', background: '#fff' }}>Gradient - Experimental</option>
|
||||
<option value="cover" style={{ color: '#000', background: '#fff' }}>Cover - Experimental</option>
|
||||
<option value="cover-gradient" style={{ color: '#000', background: '#fff' }}>Cover (Gradient) - Experimental</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -161,7 +160,7 @@ export const Settings = () => {
|
||||
<div style={{ padding: "8px 0", display: mode === "single" ? "flex" : "none", justifyContent: "space-between", alignItems: "center" }}>
|
||||
<div>
|
||||
<div style={{ fontWeight: "normal", fontSize: "1.075rem", marginBottom: 4 }}>Lyrics Color</div>
|
||||
<div style={{ opacity: 0.7, fontSize: 14 }}>Solid color (configure inside picker)</div>
|
||||
<div style={{ opacity: 0.7, fontSize: 14 }}>Set lyrics color</div>
|
||||
</div>
|
||||
<div style={{ display: "flex", gap: 8, alignItems: "center", position: "relative" }}>
|
||||
<button
|
||||
@@ -179,35 +178,32 @@ export const Settings = () => {
|
||||
</div>
|
||||
|
||||
|
||||
{/* Gradient controls (triggers only) */}
|
||||
<div style={{ padding: "8px 0", display: mode === "gradient" ? "block" : "none" }}>
|
||||
<div style={{ fontWeight: "normal", fontSize: "1.075rem", marginBottom: 4 }}>Gradient</div>
|
||||
<div style={{ opacity: 0.7, fontSize: 14, marginBottom: 8 }}>Pick start/end and angle (inside picker)</div>
|
||||
<div style={{ display: "flex", gap: 12, alignItems: "center" }}>
|
||||
<button
|
||||
onClick={() => {
|
||||
setCustomInput(gradientStart);
|
||||
openPicker('start');
|
||||
}}
|
||||
title="Start Color"
|
||||
style={{ width: 32, height: 32, border: "1px solid rgba(255,255,255,0.15)", borderRadius: 6, background: normalizeToRGB(gradientStart) }}
|
||||
/>
|
||||
<button
|
||||
onClick={() => {
|
||||
setCustomInput(gradientEnd);
|
||||
openPicker('end');
|
||||
}}
|
||||
title="End Color"
|
||||
style={{ width: 32, height: 32, border: "1px solid rgba(255,255,255,0.15)", borderRadius: 6, background: normalizeToRGB(gradientEnd) }}
|
||||
/>
|
||||
{/* Gradient controls (open picker) */}
|
||||
<div style={{ padding: "8px 0", display: mode === "gradient-experimental" ? "flex" : "none", justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<div>
|
||||
<div style={{ fontWeight: "normal", fontSize: "1.075rem", marginBottom: 4 }}>Gradient (Experimental)</div>
|
||||
<div style={{ opacity: 0.7, fontSize: 14 }}>Set colors & angle</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => { setCustomInput(gradientStart); openPicker('start'); }}
|
||||
style={{
|
||||
padding: '8px 12px',
|
||||
borderRadius: 8,
|
||||
border: '1px solid rgba(255,255,255,0.2)',
|
||||
background: 'rgba(255,255,255,0.08)',
|
||||
color: '#fff',
|
||||
cursor: 'pointer'
|
||||
}}
|
||||
>
|
||||
Configure
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Auto gradient controls (open picker for angle) */}
|
||||
<div style={{ padding: "8px 0", display: mode === "auto-gradient" ? "flex" : "none", justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
{/* Cover gradient controls (open picker for angle) */}
|
||||
<div style={{ padding: "8px 0", display: mode === "cover-gradient" ? "flex" : "none", justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<div>
|
||||
<div style={{ fontWeight: "normal", fontSize: "1.075rem", marginBottom: 4 }}>Auto Gradient</div>
|
||||
<div style={{ opacity: 0.7, fontSize: 14 }}>Configure angle inside the picker</div>
|
||||
<div style={{ fontWeight: "normal", fontSize: "1.075rem", marginBottom: 4 }}>Cover (Gradient) - Experimental</div>
|
||||
<div style={{ opacity: 0.7, fontSize: 14 }}>Set angle</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => openPicker('start')}
|
||||
@@ -224,7 +220,7 @@ export const Settings = () => {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Rainbow controls removed: mode exists but has no UI */}
|
||||
{/* Rainbow mode removed */}
|
||||
|
||||
{/* Modal for picking and managing colors (reused) */}
|
||||
{shouldRender && (
|
||||
@@ -267,7 +263,7 @@ export const Settings = () => {
|
||||
<div style={{ marginBottom: 12, color: "#fff", fontWeight: "bold", fontSize: 14 }}>
|
||||
{mode === 'single' ? 'Single Color' : 'Gradient Colors'}
|
||||
</div>
|
||||
{mode === 'gradient' && (
|
||||
{mode === 'gradient-experimental' && (
|
||||
<div style={{ display: 'flex', gap: 8, alignItems: 'center', marginBottom: 12 }}>
|
||||
<div style={{ color: 'rgba(255,255,255,0.7)', fontSize: 12 }}>Editing</div>
|
||||
<button
|
||||
@@ -296,7 +292,7 @@ export const Settings = () => {
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{mode !== 'auto-gradient' && (
|
||||
{mode !== 'cover-gradient' && (
|
||||
<div style={{ display: "grid", gridTemplateColumns: "repeat(7, 1fr)", gap: 8, marginBottom: 16 }}>
|
||||
{allColors.map((color, index) => (
|
||||
<button
|
||||
@@ -305,7 +301,7 @@ export const Settings = () => {
|
||||
if (mode === "single") {
|
||||
const next = normalizeToRGB(color);
|
||||
setSingleColor((settings.singleColor = next));
|
||||
} else if (mode === "gradient") {
|
||||
} else if (mode === "gradient-experimental") {
|
||||
if (activeEndpoint === 'end') {
|
||||
setGradientEnd((settings.gradientEnd = normalizeToRGB(color)));
|
||||
} else {
|
||||
@@ -327,7 +323,7 @@ export const Settings = () => {
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
{mode !== 'auto-gradient' && (
|
||||
{mode !== 'cover-gradient' && (
|
||||
<div style={{ marginBottom: 12 }}>
|
||||
<div style={{ color: "rgba(255,255,255,0.7)", fontSize: 12, marginBottom: 6 }}>Custom Hex (#RRGGBB)</div>
|
||||
<div style={{ display: "flex", gap: 8, alignItems: "center" }}>
|
||||
@@ -343,7 +339,7 @@ export const Settings = () => {
|
||||
const next = normalizeToRGB(trimmed);
|
||||
setSingleColor((settings.singleColor = next));
|
||||
setCustomInput(next);
|
||||
} else if (mode === "gradient") {
|
||||
} else if (mode === "gradient-experimental") {
|
||||
const norm = normalizeToRGB(trimmed);
|
||||
if (activeEndpoint === 'end') {
|
||||
setGradientEnd((settings.gradientEnd = norm));
|
||||
@@ -376,7 +372,7 @@ export const Settings = () => {
|
||||
if (hexColorRegex.test(trimmed)) {
|
||||
if (mode === "single") {
|
||||
setSingleColor((settings.singleColor = normalizeToRGB(trimmed)));
|
||||
} else if (mode === "gradient") {
|
||||
} else if (mode === "gradient-experimental") {
|
||||
const norm = normalizeToRGB(trimmed);
|
||||
if (activeEndpoint === 'end') {
|
||||
setGradientEnd((settings.gradientEnd = norm));
|
||||
@@ -428,7 +424,7 @@ export const Settings = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{mode === 'gradient' && (
|
||||
{mode === 'gradient-experimental' && (
|
||||
<div style={{ marginBottom: 16, display: 'grid', gap: 16 }}>
|
||||
<div>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6 }}>
|
||||
@@ -490,7 +486,7 @@ export const Settings = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{mode === 'auto-gradient' && (
|
||||
{mode === 'cover-gradient' && (
|
||||
<div style={{ marginBottom: 16 }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 }}>
|
||||
<div style={{ color: 'rgba(255,255,255,0.8)', fontSize: 12 }}>Angle</div>
|
||||
@@ -531,7 +527,7 @@ export const Settings = () => {
|
||||
</>
|
||||
)}
|
||||
<AnySwitch
|
||||
title="Exclude Inactive | Experimental"
|
||||
title="Exclude Inactive"
|
||||
desc="Apply color/gradient only to the currently active lyric line"
|
||||
checked={excludeInactive}
|
||||
onChange={(_: unknown, checked: boolean) => {
|
||||
|
||||
@@ -124,10 +124,10 @@ function applyGradient(start: string, end: string, angle: number) {
|
||||
}
|
||||
|
||||
function resetModeClasses(): void {
|
||||
document.body.classList.remove('colorama-single', 'colorama-gradient', 'colorama-rainbow');
|
||||
document.body.classList.remove('colorama-single', 'colorama-gradient');
|
||||
}
|
||||
|
||||
async function applyAutoColors(gradient: boolean) {
|
||||
async function applyCoverColors(gradient: boolean) {
|
||||
const img = await getCoverArtElement();
|
||||
if (!img) return;
|
||||
const colors = getDominantColorsFromImage(img, gradient ? 2 : 1);
|
||||
@@ -143,7 +143,7 @@ async function applyAutoColors(gradient: boolean) {
|
||||
|
||||
function applyColoramaLyrics(): void {
|
||||
if (!settings.enabled) {
|
||||
document.body.classList.remove('colorama-single', 'colorama-gradient', 'colorama-rainbow');
|
||||
document.body.classList.remove('colorama-single', 'colorama-gradient');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -158,17 +158,14 @@ function applyColoramaLyrics(): void {
|
||||
case "single":
|
||||
applySingleColor(settings.singleColor);
|
||||
break;
|
||||
case "gradient":
|
||||
case "gradient-experimental":
|
||||
applyGradient(settings.gradientStart, settings.gradientEnd, settings.gradientAngle);
|
||||
break;
|
||||
case "rainbow":
|
||||
// no-op: rainbow mode disabled
|
||||
case "cover":
|
||||
applyCoverColors(false);
|
||||
break;
|
||||
case "auto-single":
|
||||
applyAutoColors(false);
|
||||
break;
|
||||
case "auto-gradient":
|
||||
applyAutoColors(true);
|
||||
case "cover-gradient":
|
||||
applyCoverColors(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -182,7 +179,7 @@ function observeTrackChanges(): void {
|
||||
const currentTrackId = PlayState.playbackContext?.actualProductId;
|
||||
if (currentTrackId && currentTrackId !== lastTrackId) {
|
||||
lastTrackId = currentTrackId;
|
||||
if (settings.mode.startsWith("auto")) {
|
||||
if (settings.mode === 'cover' || settings.mode === 'cover-gradient') {
|
||||
setTimeout(() => applyColoramaLyrics(), 200);
|
||||
}
|
||||
}
|
||||
@@ -220,7 +217,6 @@ function hookRadiantUpdates(): void {
|
||||
|
||||
setTimeout(() => hookRadiantUpdates(), 0);
|
||||
|
||||
// Observe active lyric span changes and restart rainbow animation to avoid freezes
|
||||
// Rainbow mode disabled: no lyrics observer needed
|
||||
// Rainbow mode removed
|
||||
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
-webkit-text-fill-color: transparent !important;
|
||||
}
|
||||
|
||||
/* Ensure active line keeps rainbow in only-active mode */
|
||||
/* Only-active: apply container class only on the active line via JS */
|
||||
|
||||
/* Slight emphasis on current line (uniform to single mode) */
|
||||
|
||||
Reference in New Issue
Block a user