diff --git a/src/static/main.css b/src/static/main.css index 15226a5..417fd9c 100644 --- a/src/static/main.css +++ b/src/static/main.css @@ -107,3 +107,57 @@ input[type="range"]::-moz-range-thumb { margin-right: 10px; vertical-align: middle; /* Aligns them nicely if heights vary */ } + +#colors_palette { + margin-bottom: 20px; +} + +#colors_container { + display: flex; + flex-wrap: wrap; + gap: 10px; + margin-bottom: 10px; +} + +.color-item { + display: flex; + align-items: center; + gap: 5px; +} + +.color-input { + width: 60px !important; + height: 40px; + border: 2px solid #ddd; + border-radius: 4px; + cursor: pointer; +} + +.remove-color-btn { + background-color: #f44336; + color: white; + border: none; + border-radius: 4px; + width: 30px; + height: 30px; + cursor: pointer; + font-size: 18px; + line-height: 1; +} + +.remove-color-btn:hover { + background-color: #da190b; +} + +#add_color_btn { + background-color: #4caf50; + color: white; + border: none; + padding: 8px 16px; + border-radius: 4px; + cursor: pointer; +} + +#add_color_btn:hover { + background-color: #45a049; +} diff --git a/src/static/main.js b/src/static/main.js index 9e00994..3f31bcc 100644 --- a/src/static/main.js +++ b/src/static/main.js @@ -1,7 +1,6 @@ let delayTimeout; let brightnessTimeout; -let colorTimeout; -let color2Timeout; +let colorsTimeout; let ws; // Variable to hold the WebSocket connection let connectionStatusElement; // Variable to hold the connection status element @@ -98,22 +97,60 @@ async function get(path) { } } -async function updateColor(event) { - event.preventDefault(); - clearTimeout(colorTimeout); - colorTimeout = setTimeout(function () { - const color = document.getElementById("color").value; - sendWebSocketData({ color1: color }); +function updateColors() { + clearTimeout(colorsTimeout); + colorsTimeout = setTimeout(function () { + const colorInputs = document.querySelectorAll(".color-input"); + const colors = Array.from(colorInputs).map(input => input.value); + sendWebSocketData({ colors: colors }); }, 500); } -async function updateColor2(event) { - event.preventDefault(); - clearTimeout(color2Timeout); - color2Timeout = setTimeout(function () { - const color = document.getElementById("color2").value; - sendWebSocketData({ color2: color }); - }, 500); +function addColorInput(color = "#ff0000") { + const container = document.getElementById("colors_container"); + const colorDiv = document.createElement("div"); + colorDiv.className = "color-item"; + + const colorInput = document.createElement("input"); + colorInput.type = "color"; + colorInput.className = "color-input"; + colorInput.value = color; + colorInput.addEventListener("input", updateColors); + + const removeBtn = document.createElement("button"); + removeBtn.type = "button"; + removeBtn.textContent = "×"; + removeBtn.className = "remove-color-btn"; + removeBtn.addEventListener("click", function() { + colorDiv.remove(); + updateColors(); + }); + + colorDiv.appendChild(colorInput); + colorDiv.appendChild(removeBtn); + container.appendChild(colorDiv); +} + +function initializeColors(initialColors = null) { + const container = document.getElementById("colors_container"); + container.innerHTML = ""; + // Get initial colors from data attribute or use defaults + if (initialColors === null) { + const colorsData = document.getElementById("colors_container").dataset.colors; + if (colorsData) { + try { + initialColors = JSON.parse(colorsData); + } catch (e) { + initialColors = ["#ff0000", "#00ff00"]; + } + } else { + initialColors = ["#ff0000", "#00ff00"]; + } + } + if (initialColors.length === 0) { + initialColors = ["#ff0000"]; + } + initialColors.forEach(color => addColorInput(color)); } async function updatePattern(pattern) { @@ -198,8 +235,11 @@ document.addEventListener("DOMContentLoaded", async function () { // Establish WebSocket connection on page load connectWebSocket(); - document.getElementById("color").addEventListener("input", updateColor); - document.getElementById("color2").addEventListener("input", updateColor2); + // Initialize colors palette + initializeColors(); + document.getElementById("add_color_btn").addEventListener("click", function() { + addColorInput(); + }); document.getElementById("delay").addEventListener("input", updateDelay); document .getElementById("brightness") diff --git a/src/templates/index.html b/src/templates/index.html index 4e1a112..3aa77b9 100644 --- a/src/templates/index.html +++ b/src/templates/index.html @@ -1,4 +1,4 @@ -{% args settings, patterns, mac %} +{% args settings, patterns, colors_json, mac %} @@ -46,22 +46,13 @@ step="1" /> -
- -
-
- -
+
+ +
+ +
+ +
diff --git a/src/web.py b/src/web.py index 8e847bc..944d424 100644 --- a/src/web.py +++ b/src/web.py @@ -12,7 +12,19 @@ def web(settings, patterns): @app.route('/') async def index_hnadler(request): mac = wifi.get_mac().hex() - return Template('index.html').render(settings=settings, patterns=patterns.patterns.keys()) + # Convert colors from RGB tuples to hex strings for display + colors_hex = [] + for color in patterns.colors: + # Convert (R, G, B) tuple to #RRGGBB hex string + colors_hex.append(f"#{color[0]:02x}{color[1]:02x}{color[2]:02x}") + # Convert to JSON string for data attribute + colors_json = json.dumps(colors_hex) + return Template('index.html').render( + settings, + patterns.patterns.keys(), + colors_json, + mac + ) @app.route("/static/") def static_handler(request, path):