From c98592a412d2e554e7d5fd432d0cb640fdff53c0 Mon Sep 17 00:00:00 2001 From: Adam Shiervani Date: Mon, 8 Sep 2025 11:38:49 +0200 Subject: [PATCH] feat(ui): Enhance EDID settings with loading state (#691) * feat(ui): Enhance EDID settings with loading state and Fieldset component * fix(ui): Improve notifications and adjust styling in custom EDID component * fix(ui): specify JsonRpcResponse type --- ui/src/routes/devices.$id.settings.video.tsx | 165 +++++++++++-------- 1 file changed, 92 insertions(+), 73 deletions(-) diff --git a/ui/src/routes/devices.$id.settings.video.tsx b/ui/src/routes/devices.$id.settings.video.tsx index e5072d6..ea1a101 100644 --- a/ui/src/routes/devices.$id.settings.video.tsx +++ b/ui/src/routes/devices.$id.settings.video.tsx @@ -1,15 +1,16 @@ -import { useState, useEffect } from "react"; +import { useEffect, useState } from "react"; import { Button } from "@/components/Button"; import { TextAreaWithLabel } from "@/components/TextArea"; import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc"; import { SettingsPageHeader } from "@components/SettingsPageheader"; import { useSettingsStore } from "@/hooks/stores"; - -import notifications from "../notifications"; -import { SelectMenuBasic } from "../components/SelectMenuBasic"; +import { SelectMenuBasic } from "@components/SelectMenuBasic"; +import Fieldset from "@components/Fieldset"; +import notifications from "@/notifications"; import { SettingsItem } from "./devices.$id.settings"; + const defaultEdid = "00ffffffffffff0052620188008888881c150103800000780a0dc9a05747982712484c00000001010101010101010101010101010101023a801871382d40582c4500c48e2100001e011d007251d01e206e285500c48e2100001e000000fc00543734392d6648443732300a20000000fd00147801ff1d000a202020202020017b"; const edids = [ @@ -50,21 +51,27 @@ export default function SettingsVideoRoute() { const [streamQuality, setStreamQuality] = useState("1"); const [customEdidValue, setCustomEdidValue] = useState(null); const [edid, setEdid] = useState(null); + const [edidLoading, setEdidLoading] = useState(false); // Video enhancement settings from store const { - videoSaturation, setVideoSaturation, - videoBrightness, setVideoBrightness, - videoContrast, setVideoContrast + videoSaturation, + setVideoSaturation, + videoBrightness, + setVideoBrightness, + videoContrast, + setVideoContrast, } = useSettingsStore(); useEffect(() => { + setEdidLoading(true); send("getStreamQualityFactor", {}, (resp: JsonRpcResponse) => { if ("error" in resp) return; setStreamQuality(String(resp.result)); }); send("getEDID", {}, (resp: JsonRpcResponse) => { + setEdidLoading(false); if ("error" in resp) { notifications.error(`Failed to get EDID: ${resp.error.data || "Unknown error"}`); return; @@ -89,28 +96,36 @@ export default function SettingsVideoRoute() { }, [send]); const handleStreamQualityChange = (factor: string) => { - send("setStreamQualityFactor", { factor: Number(factor) }, (resp: JsonRpcResponse) => { - if ("error" in resp) { - notifications.error( - `Failed to set stream quality: ${resp.error.data || "Unknown error"}`, - ); - return; - } + send( + "setStreamQualityFactor", + { factor: Number(factor) }, + (resp: JsonRpcResponse) => { + if ("error" in resp) { + notifications.error( + `Failed to set stream quality: ${resp.error.data || "Unknown error"}`, + ); + return; + } - notifications.success(`Stream quality set to ${streamQualityOptions.find(x => x.value === factor)?.label}`); - setStreamQuality(factor); - }); + notifications.success( + `Stream quality set to ${streamQualityOptions.find(x => x.value === factor)?.label}`, + ); + setStreamQuality(factor); + }, + ); }; const handleEDIDChange = (newEdid: string) => { + setEdidLoading(true); send("setEDID", { edid: newEdid }, (resp: JsonRpcResponse) => { + setEdidLoading(false); if ("error" in resp) { notifications.error(`Failed to set EDID: ${resp.error.data || "Unknown error"}`); return; } notifications.success( - `EDID set successfully to ${edids.find(x => x.value === newEdid)?.label}`, + `EDID set successfully to ${edids.find(x => x.value === newEdid)?.label ?? "the custom EDID"}`, ); // Update the EDID value in the UI setEdid(newEdid); @@ -158,7 +173,7 @@ export default function SettingsVideoRoute() { step="0.1" value={videoSaturation} onChange={e => setVideoSaturation(parseFloat(e.target.value))} - className="w-32 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" + className="h-2 w-32 cursor-pointer appearance-none rounded-lg bg-gray-200 dark:bg-gray-700" /> @@ -173,7 +188,7 @@ export default function SettingsVideoRoute() { step="0.1" value={videoBrightness} onChange={e => setVideoBrightness(parseFloat(e.target.value))} - className="w-32 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" + className="h-2 w-32 cursor-pointer appearance-none rounded-lg bg-gray-200 dark:bg-gray-700" /> @@ -188,7 +203,7 @@ export default function SettingsVideoRoute() { step="0.1" value={videoContrast} onChange={e => setVideoContrast(parseFloat(e.target.value))} - className="w-32 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" + className="h-2 w-32 cursor-pointer appearance-none rounded-lg bg-gray-200 dark:bg-gray-700" /> @@ -205,60 +220,64 @@ export default function SettingsVideoRoute() { /> - - - { - if (e.target.value === "custom") { - setEdid("custom"); - setCustomEdidValue(""); - } else { - setCustomEdidValue(null); - handleEDIDChange(e.target.value as string); - } - }} - options={[...edids, { value: "custom", label: "Custom" }]} - /> - - {customEdidValue !== null && ( - <> - - setCustomEdidValue(e.target.value)} - /> -
-
- - )} + setCustomEdidValue(e.target.value)} + /> +
+
+ + )} +