CODEX - Added modal colours for the Bells

This commit is contained in:
2026-02-23 19:20:30 +02:00
parent a46e296dc3
commit cd218a55fe
6 changed files with 246 additions and 10 deletions

View File

@@ -1,4 +1,6 @@
import { useState, useEffect, useRef, useCallback } from "react";
import api from "../api/client";
function bellFrequency(bellNumber) {
return 880 * Math.pow(Math.pow(2, 1 / 12), -2 * (bellNumber - 1));
@@ -145,6 +147,11 @@ function bellDotGlow(assignedBell) {
return `hsla(${hue}, 78%, 56%, 0.45)`;
}
function bellCustomGlow(color) {
if (!color || typeof color !== "string") return null;
return `${color}66`;
}
const mutedStyle = { color: "var(--text-muted)" };
const labelStyle = { color: "var(--text-secondary)" };
const NOTE_LABELS = "ABCDEFGHIJKLMNOP";
@@ -165,6 +172,7 @@ export default function PlaybackModal({ open, melody, builtMelody, files, archet
const [toneLengthMs, setToneLengthMs] = useState(80);
const [loopEnabled, setLoopEnabled] = useState(true);
const [activeBells, setActiveBells] = useState(new Set());
const [noteColors, setNoteColors] = useState([]);
const audioCtxRef = useRef(null);
const playbackRef = useRef(null);
@@ -181,6 +189,19 @@ export default function PlaybackModal({ open, melody, builtMelody, files, archet
useEffect(() => { toneLengthRef.current = toneLengthMs; }, [toneLengthMs]);
useEffect(() => { noteAssignmentsRef.current = noteAssignments; }, [noteAssignments]);
useEffect(() => { loopEnabledRef.current = loopEnabled; }, [loopEnabled]);
useEffect(() => {
if (!open) return;
let canceled = false;
api.get("/settings/melody")
.then((s) => {
if (canceled) return;
setNoteColors((s?.note_assignment_colors || []).slice(0, 16));
})
.catch(() => {
if (!canceled) setNoteColors([]);
});
return () => { canceled = true; };
}, [open]);
const stopPlayback = useCallback(() => {
if (playbackRef.current) {
@@ -495,6 +516,7 @@ export default function PlaybackModal({ open, melody, builtMelody, files, archet
const enabled = Boolean(stepValue & (1 << noteIdx));
const isCurrent = currentStep === stepIdx;
const assignedBell = Number(noteAssignments[noteIdx] || 0);
const assignedColor = assignedBell > 0 ? noteColors?.[assignedBell - 1] : null;
const dotLabel = assignedBell > 0 ? assignedBell : "";
const isUnassigned = assignedBell <= 0;
const dotVisible = enabled || (isUnassigned && Boolean(stepValue & (1 << noteIdx)));
@@ -516,12 +538,12 @@ export default function PlaybackModal({ open, melody, builtMelody, files, archet
width: "68%",
height: "68%",
borderRadius: "9999px",
backgroundColor: isUnassigned ? "rgba(100,116,139,0.7)" : bellDotColor(assignedBell),
backgroundColor: isUnassigned ? "rgba(100,116,139,0.7)" : (assignedColor || bellDotColor(assignedBell)),
color: "#111827",
opacity: dotVisible ? 1 : 0,
transform: dotVisible ? "scale(1)" : "scale(0.4)",
boxShadow: dotVisible
? (isUnassigned ? "0 0 8px 2px rgba(100,116,139,0.35)" : `0 0 10px 3px ${bellDotGlow(assignedBell)}`)
? (isUnassigned ? "0 0 8px 2px rgba(100,116,139,0.35)" : `0 0 10px 3px ${bellCustomGlow(assignedColor) || bellDotGlow(assignedBell)}`)
: "none",
transition: "opacity 140ms ease, transform 140ms ease, box-shadow 180ms ease",
}}
@@ -557,3 +579,5 @@ export default function PlaybackModal({ open, melody, builtMelody, files, archet
</div>
);
}