diff options
| author | Michael McVady <michaelm@telnyx.com> | 2026-02-26 10:55:14 -0500 |
|---|---|---|
| committer | Michael McVady <michaelm@telnyx.com> | 2026-02-26 11:03:59 -0500 |
| commit | 239928ede767501438d1cae2c55793adb8c3923d (patch) | |
| tree | aeec65256c3d3a4296533291885328ee50b4cdf9 /app.py | |
| parent | fe21d3eb2b9eedbf5971f2445358e32756acf7b4 (diff) | |
add color picker
Diffstat (limited to 'app.py')
| -rw-r--r-- | app.py | 75 |
1 files changed, 67 insertions, 8 deletions
@@ -1,5 +1,5 @@ import logging -from colorsys import hsv_to_rgb +from colorsys import hsv_to_rgb, rgb_to_hsv from dataclasses import dataclass from random import randint @@ -8,7 +8,9 @@ from lifxlan import LifxLAN, Light from litestar import Litestar, get, post from litestar.contrib.jinja import JinjaTemplateEngine from litestar.di import Provide +from litestar.enums import RequestEncodingType from litestar.logging import LoggingConfig +from litestar.params import Body from litestar.response import Template from litestar.template import TemplateConfig @@ -17,9 +19,25 @@ TEMPLATE_STR = """<!DOCTYPE html> <html lang="zxx"> <head> <title>lux</title> +<style> + body { margin: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: 100vh; } + h1 { font-family: monospace; } + input[type=color] { + width: 200px; height: 200px; border: none; border-radius: 50%; cursor: pointer; padding: 0; + background: radial-gradient(circle, white 0%, transparent 70%), + conic-gradient(hsl(0,100%,50%), hsl(60,100%,50%), hsl(120,100%,50%), + hsl(180,100%,50%), hsl(240,100%,50%), hsl(300,100%,50%), hsl(360,100%,50%)); + } + input[type=color]::-webkit-color-swatch-wrapper { padding: 0; } + input[type=color]::-webkit-color-swatch { border: none; border-radius: 50%; opacity: 0; } + input[type=color]::-moz-color-swatch { border: none; border-radius: 50%; opacity: 0; } +</style> </head> <body style="background-color: {{ background_color }};"> -<h1 style="color: {{ color }}; font-family: monospace">{{ message }}</h1> +<h1 style="color: {{ color }};">{{ message }}</h1> +<form method="post"> +<input type="color" name="color" value="{{ current_color }}" onchange="this.form.submit()"> +</form> <script data-goatcounter="https://test.bunkergate.org/count" async src="https://test.bunkergate.org/count.js"></script> </body> </html> @@ -37,11 +55,30 @@ class RGBColor: green: int blue: int + @classmethod + def from_hex(cls, hex_str: str) -> "RGBColor": + hex_str = hex_str.lstrip("#") + return cls( + red=int(hex_str[0:2], 16), + green=int(hex_str[2:4], 16), + blue=int(hex_str[4:6], 16), + ) + @property def hex(self) -> str: return "#%02X%02X%02X" % (self.red, self.green, self.blue) @property + def hsbk(self) -> "HSBKColor": + h, s, v = rgb_to_hsv(self.red / 255, self.green / 255, self.blue / 255) + return HSBKColor( + hue=int(h * 65535), + saturation=int(s * 65535), + brightness=int(v * 65535), + kelvin=3500, + ) + + @property def yit(self) -> int: yit = ((self.red * 299) + (self.green * 587) + (self.blue * 114)) // 1000 log.info(f"yit: {yit}") @@ -93,8 +130,7 @@ def get_random_hsbk_color() -> HSBKColor: ) -def random_color(lux: Light) -> Template: - hsbk = get_random_hsbk_color() +def _set_light_color(lux: Light, hsbk: HSBKColor) -> Template: log.info(f"Setting color to {hsbk} {hsbk.rgb}") try: @@ -105,7 +141,12 @@ def random_color(lux: Light) -> Template: log.exception("Error setting color") return Template( template_str=TEMPLATE_STR, - context={"color": DEFAULT_COLOR, "message": f"error: {str(e)}"}, + context={ + "background_color": DEFAULT_COLOR, + "color": "white", + "message": f"error: {str(e)}", + "current_color": DEFAULT_COLOR, + }, ) rgb = hsbk.rgb @@ -117,20 +158,38 @@ def random_color(lux: Light) -> Template: "background_color": rgb_hex, "color": text_color, "message": rgb_hex, + "current_color": rgb_hex, }, ) +def random_color(lux: Light) -> Template: + return _set_light_color(lux, get_random_hsbk_color()) + + +def chosen_color(lux: Light, hex_color: str) -> Template: + rgb = RGBColor.from_hex(hex_color) + return _set_light_color(lux, rgb.hsbk) + + @get("/") async def get_index(lux: Light = Provide(get_lux)) -> Template: """Return index""" return random_color(lux) +@dataclass +class ColorForm: + color: str + + @post("/") -async def post_index(lux: Light = Provide(get_lux)) -> Template: - """Update index""" - return random_color(lux) +async def post_index( + data: ColorForm = Body(media_type=RequestEncodingType.URL_ENCODED), + lux: Light = Provide(get_lux), +) -> Template: + """Set light to chosen color""" + return chosen_color(lux, data.color) app = Litestar( |
