Fix UI lint warnings

There were a bunch of ref and useEffect violations.
This commit is contained in:
Marc Brooks 2025-10-13 20:11:58 -05:00
parent 0eb577b6f7
commit 0dcf56ef18
No known key found for this signature in database
GPG Key ID: 583A6AF2D6AE1DC6
4 changed files with 73 additions and 77 deletions

View File

@ -41,8 +41,6 @@ export default function SettingsGeneralUpdateRoute() {
return <Dialog onClose={() => navigate("..")} onConfirmUpdate={onConfirmUpdate} />;
}
export function Dialog({
onClose,
onConfirmUpdate,
@ -71,11 +69,6 @@ export function Dialog({
[setModalView],
);
// Reset modal view when dialog is opened
useEffect(() => {
setVersionInfo(null);
}, [setModalView]);
return (
<div className="pointer-events-auto relative mx-auto text-left">
<div>
@ -133,8 +126,6 @@ function LoadingState({
const progressBarRef = useRef<HTMLDivElement>(null);
useEffect(() => {
setProgressWidth("0%");
abortControllerRef.current = new AbortController();
const signal = abortControllerRef.current.signal;

View File

@ -1,20 +1,19 @@
import { useEffect } from "react";
import { BacklightSettings, useSettingsStore } from "@hooks/stores";
import { JsonRpcResponse, useJsonRpc } from "@hooks/useJsonRpc";
import { FeatureFlag } from "@components/FeatureFlag";
import { SelectMenuBasic } from "@components/SelectMenuBasic";
import { SettingsItem } from "@components/SettingsItem";
import { SettingsPageHeader } from "@components/SettingsPageheader";
import { BacklightSettings, useSettingsStore } from "@/hooks/stores";
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
import { SelectMenuBasic } from "@components/SelectMenuBasic";
import { UsbDeviceSetting } from "@components/UsbDeviceSetting";
import notifications from "../notifications";
import { UsbInfoSetting } from "../components/UsbInfoSetting";
import { FeatureFlag } from "../components/FeatureFlag";
import { UsbInfoSetting } from "@components/UsbInfoSetting";
import notifications from "@/notifications";
export default function SettingsHardwareRoute() {
const { send } = useJsonRpc();
const settings = useSettingsStore();
const { setDisplayRotation } = useSettingsStore();
const { displayRotation, setDisplayRotation } = useSettingsStore();
const handleDisplayRotationChange = (rotation: string) => {
setDisplayRotation(rotation);
@ -22,7 +21,7 @@ export default function SettingsHardwareRoute() {
};
const handleDisplayRotationSave = () => {
send("setDisplayRotation", { params: { rotation: settings.displayRotation } }, (resp: JsonRpcResponse) => {
send("setDisplayRotation", { params: { rotation: displayRotation } }, (resp: JsonRpcResponse) => {
if ("error" in resp) {
notifications.error(
`Failed to set display orientation: ${resp.error.data || "Unknown error"}`,
@ -33,7 +32,7 @@ export default function SettingsHardwareRoute() {
});
};
const { setBacklightSettings } = useSettingsStore();
const { backlightSettings, setBacklightSettings } = useSettingsStore();
const handleBacklightSettingsChange = (settings: BacklightSettings) => {
// If the user has set the display to dim after it turns off, set the dim_after
@ -47,7 +46,7 @@ export default function SettingsHardwareRoute() {
};
const handleBacklightSettingsSave = () => {
send("setBacklightSettings", { params: settings.backlightSettings }, (resp: JsonRpcResponse) => {
send("setBacklightSettings", { params: backlightSettings }, (resp: JsonRpcResponse) => {
if ("error" in resp) {
notifications.error(
`Failed to set backlight settings: ${resp.error.data || "Unknown error"}`,
@ -58,6 +57,21 @@ export default function SettingsHardwareRoute() {
});
};
const handleBacklightMaxBrightnessChange = (max_brightness: number) => {
const settings = { ...backlightSettings, max_brightness };
handleBacklightSettingsChange(settings);
};
const handleBacklightDimAfterChange = (dim_after: number) => {
const settings = { ...backlightSettings, dim_after };
handleBacklightSettingsChange(settings);
};
const handleBacklightOffAfterChange = (off_after: number) => {
const settings = { ...backlightSettings, off_after };
handleBacklightSettingsChange(settings);
};
useEffect(() => {
send("getBacklightSettings", {}, (resp: JsonRpcResponse) => {
if ("error" in resp) {
@ -90,8 +104,7 @@ export default function SettingsHardwareRoute() {
{ value: "90", label: "Inverted" },
]}
onChange={e => {
settings.displayRotation = e.target.value;
handleDisplayRotationChange(settings.displayRotation);
handleDisplayRotationChange(e.target.value);
}}
/>
</SettingsItem>
@ -102,7 +115,7 @@ export default function SettingsHardwareRoute() {
<SelectMenuBasic
size="SM"
label=""
value={settings.backlightSettings.max_brightness.toString()}
value={backlightSettings.max_brightness.toString()}
options={[
{ value: "0", label: "Off" },
{ value: "10", label: "Low" },
@ -110,12 +123,11 @@ export default function SettingsHardwareRoute() {
{ value: "64", label: "High" },
]}
onChange={e => {
settings.backlightSettings.max_brightness = parseInt(e.target.value);
handleBacklightSettingsChange(settings.backlightSettings);
handleBacklightMaxBrightnessChange(parseInt(e.target.value));
}}
/>
</SettingsItem>
{settings.backlightSettings.max_brightness != 0 && (
{backlightSettings.max_brightness != 0 && (
<>
<SettingsItem
title="Dim Display After"
@ -124,7 +136,7 @@ export default function SettingsHardwareRoute() {
<SelectMenuBasic
size="SM"
label=""
value={settings.backlightSettings.dim_after.toString()}
value={backlightSettings.dim_after.toString()}
options={[
{ value: "0", label: "Never" },
{ value: "60", label: "1 Minute" },
@ -134,8 +146,7 @@ export default function SettingsHardwareRoute() {
{ value: "3600", label: "1 Hour" },
]}
onChange={e => {
settings.backlightSettings.dim_after = parseInt(e.target.value);
handleBacklightSettingsChange(settings.backlightSettings);
handleBacklightDimAfterChange(parseInt(e.target.value));
}}
/>
</SettingsItem>
@ -146,7 +157,7 @@ export default function SettingsHardwareRoute() {
<SelectMenuBasic
size="SM"
label=""
value={settings.backlightSettings.off_after.toString()}
value={backlightSettings.off_after.toString()}
options={[
{ value: "0", label: "Never" },
{ value: "300", label: "5 Minutes" },
@ -155,8 +166,7 @@ export default function SettingsHardwareRoute() {
{ value: "3600", label: "1 Hour" },
]}
onChange={e => {
settings.backlightSettings.off_after = parseInt(e.target.value);
handleBacklightSettingsChange(settings.backlightSettings);
handleBacklightOffAfterChange(parseInt(e.target.value));
}}
/>
</SettingsItem>

View File

@ -1,4 +1,4 @@
import { useCallback, useEffect, useRef, useState } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import { LuEthernetPort } from "react-icons/lu";
@ -12,23 +12,22 @@ import {
NetworkState,
TimeSyncMode,
useNetworkStateStore,
} from "@/hooks/stores";
import { JsonRpcResponse, useJsonRpc } from "@/hooks/useJsonRpc";
} from "@hooks/stores";
import { JsonRpcResponse, useJsonRpc } from "@hooks/useJsonRpc";
import AutoHeight from "@components/AutoHeight";
import { Button } from "@components/Button";
import { ConfirmDialog } from "@components/ConfirmDialog";
import EmptyCard from "@components/EmptyCard";
import Fieldset from "@components/Fieldset";
import { GridCard } from "@components/Card";
import InputField, { InputFieldWithLabel } from "@components/InputField";
import { SelectMenuBasic } from "@/components/SelectMenuBasic";
import { SettingsPageHeader } from "@/components/SettingsPageheader";
import Fieldset from "@/components/Fieldset";
import { ConfirmDialog } from "@/components/ConfirmDialog";
import Ipv6NetworkCard from "@components/Ipv6NetworkCard";
import DhcpLeaseCard from "@components/DhcpLeaseCard";
import { SelectMenuBasic } from "@components/SelectMenuBasic";
import { SettingsItem } from "@components/SettingsItem";
import { SettingsPageHeader } from "@components/SettingsPageheader";
import notifications from "@/notifications";
import Ipv6NetworkCard from "../components/Ipv6NetworkCard";
import EmptyCard from "../components/EmptyCard";
import AutoHeight from "../components/AutoHeight";
import DhcpLeaseCard from "../components/DhcpLeaseCard";
dayjs.extend(relativeTime);
const defaultNetworkSettings: NetworkSettings = {
@ -46,14 +45,18 @@ const defaultNetworkSettings: NetworkSettings = {
export function LifeTimeLabel({ lifetime }: { lifetime: string }) {
const [remaining, setRemaining] = useState<string | null>(null);
useEffect(() => {
const updateRemaining = useCallback(() => {
setRemaining(dayjs(lifetime).fromNow());
}, [lifetime]);
useEffect(() => {
setTimeout(() => updateRemaining(), 0);
const interval = setInterval(() => {
setRemaining(dayjs(lifetime).fromNow());
updateRemaining();
}, 1000 * 30);
return () => clearInterval(interval);
}, [lifetime]);
}, [updateRemaining]);
if (lifetime == "") {
return <strong>N/A</strong>;
@ -81,24 +84,19 @@ export default function SettingsNetworkRoute() {
useState<NetworkSettings>(defaultNetworkSettings);
// We use this to determine whether the settings have changed
const firstNetworkSettings = useRef<NetworkSettings | undefined>(undefined);
const [firstNetworkSettings, setFirstNetworkSettings] = useState<NetworkSettings | undefined>(undefined);
const [networkSettingsLoaded, setNetworkSettingsLoaded] = useState(false);
const [customDomain, setCustomDomain] = useState<string>("");
const [selectedDomainOption, setSelectedDomainOption] = useState<string>("dhcp");
const selectedDomainOption = useMemo(() => {
if (!networkSettingsLoaded) return "dhcp";
const predefinedOptions = ["dhcp", "local"];
return predefinedOptions.includes(networkSettings.domain) ? networkSettings.domain : "custom";
}, [networkSettings.domain, networkSettingsLoaded]);
useEffect(() => {
if (networkSettings.domain && networkSettingsLoaded) {
// Check if the domain is one of the predefined options
const predefinedOptions = ["dhcp", "local"];
if (predefinedOptions.includes(networkSettings.domain)) {
setSelectedDomainOption(networkSettings.domain);
} else {
setSelectedDomainOption("custom");
setCustomDomain(networkSettings.domain);
}
}
const customDomain = useMemo(() => {
if (!networkSettingsLoaded) return "";
const predefinedOptions = ["dhcp", "local"];
return predefinedOptions.includes(networkSettings.domain) ? "" : networkSettings.domain;
}, [networkSettings.domain, networkSettingsLoaded]);
const getNetworkSettings = useCallback(() => {
@ -109,12 +107,12 @@ export default function SettingsNetworkRoute() {
console.debug("Network settings: ", networkSettings);
setNetworkSettings(networkSettings);
if (!firstNetworkSettings.current) {
firstNetworkSettings.current = networkSettings;
if (!firstNetworkSettings) {
setFirstNetworkSettings(networkSettings);
}
setNetworkSettingsLoaded(true);
});
}, [send]);
}, [send, firstNetworkSettings]);
const getNetworkState = useCallback(() => {
send("getNetworkState", {}, (resp: JsonRpcResponse) => {
@ -132,14 +130,13 @@ export default function SettingsNetworkRoute() {
if ("error" in resp) {
notifications.error(
"Failed to save network settings: " +
(resp.error.data ? resp.error.data : resp.error.message),
(resp.error.data ? resp.error.data : resp.error.message),
);
setNetworkSettingsLoaded(true);
return;
}
const networkSettings = resp.result as NetworkSettings;
// We need to update the firstNetworkSettings ref to the new settings so we can use it to determine if the settings have changed
firstNetworkSettings.current = networkSettings;
setFirstNetworkSettings(networkSettings);
setNetworkSettings(networkSettings);
getNetworkState();
setNetworkSettingsLoaded(true);
@ -160,8 +157,10 @@ export default function SettingsNetworkRoute() {
}, [send]);
useEffect(() => {
getNetworkState();
getNetworkSettings();
setTimeout(() => {
getNetworkState();
getNetworkSettings();
}, 0);
}, [getNetworkState, getNetworkSettings]);
const handleIpv4ModeChange = (value: IPv4Mode | string) => {
@ -197,14 +196,12 @@ export default function SettingsNetworkRoute() {
};
const handleDomainOptionChange = (value: string) => {
setSelectedDomainOption(value);
if (value !== "custom") {
handleDomainChange(value);
}
};
const handleCustomDomainChange = (value: string) => {
setCustomDomain(value);
handleDomainChange(value);
};
@ -309,7 +306,6 @@ export default function SettingsNetworkRoute() {
placeholder="home"
value={customDomain}
onChange={e => {
setCustomDomain(e.target.value);
handleCustomDomainChange(e.target.value);
}}
/>
@ -361,7 +357,7 @@ export default function SettingsNetworkRoute() {
<Button
size="SM"
theme="primary"
disabled={firstNetworkSettings.current === networkSettings}
disabled={firstNetworkSettings === networkSettings}
text="Save Settings"
onClick={() => setNetworkSettingsRemote(networkSettings)}
/>
@ -429,7 +425,7 @@ export default function SettingsNetworkRoute() {
</SettingsItem>
<AutoHeight>
{!networkSettingsLoaded &&
!(networkState?.ipv6_addresses && networkState.ipv6_addresses.length > 0) ? (
!(networkState?.ipv6_addresses && networkState.ipv6_addresses.length > 0) ? (
<GridCard>
<div className="p-4">
<div className="space-y-4">

View File

@ -50,7 +50,7 @@ export default function SettingsVideoRoute() {
const [streamQuality, setStreamQuality] = useState("1");
const [customEdidValue, setCustomEdidValue] = useState<string | null>(null);
const [edid, setEdid] = useState<string | null>(null);
const [edidLoading, setEdidLoading] = useState(false);
const [edidLoading, setEdidLoading] = useState(true);
const { debugMode } = useSettingsStore();
// Video enhancement settings from store
const {
@ -63,7 +63,6 @@ export default function SettingsVideoRoute() {
} = useSettingsStore();
useEffect(() => {
setEdidLoading(true);
send("getStreamQualityFactor", {}, (resp: JsonRpcResponse) => {
if ("error" in resp) return;
setStreamQuality(String(resp.result));