Remove useMemo/useCallback across the web UI

This commit is contained in:
proddy
2026-04-27 13:24:07 +02:00
parent e39af36589
commit 1a880f14a0
53 changed files with 1940 additions and 2594 deletions

View File

@@ -1,5 +1,3 @@
import { useCallback, useMemo } from 'react';
import { ToggleButton, ToggleButtonGroup } from '@mui/material';
import OptionIcon from './OptionIcon';
@@ -11,7 +9,6 @@ interface EntityMaskToggleProps {
de: DeviceEntity;
}
// Available mask values
const MASK_VALUES = [
DeviceEntityMask.DV_WEB_EXCLUDE, // 1
DeviceEntityMask.DV_API_MQTT_EXCLUDE, // 2
@@ -20,123 +17,95 @@ const MASK_VALUES = [
DeviceEntityMask.DV_DELETED // 128
];
/**
* Converts an array of mask strings to a bitmask number
*/
const getMaskNumber = (newMask: string[]): number => {
return newMask.reduce((mask, entry) => mask | Number(entry), 0);
};
const getMaskNumber = (newMask: string[]): number =>
newMask.reduce((mask, entry) => mask | Number(entry), 0);
/**
* Converts a bitmask number to an array of mask strings
*/
const getMaskString = (mask: number): string[] => {
return MASK_VALUES.filter((value) => (mask & value) === value).map((value) =>
const getMaskString = (mask: number): string[] =>
MASK_VALUES.filter((value) => (mask & value) === value).map((value) =>
String(value)
);
};
/**
* Checks if a specific mask bit is set
*/
const hasMask = (mask: number, flag: number): boolean => (mask & flag) === flag;
const EntityMaskToggle = ({ onUpdate, de }: EntityMaskToggleProps) => {
const handleChange = useCallback(
(_event: unknown, mask: string[]) => {
// Convert selected masks to a number
const newMask = getMaskNumber(mask);
const updatedDe = { ...de };
const handleChange = (_event: unknown, mask: string[]) => {
const newMask = getMaskNumber(mask);
const updatedDe = { ...de };
// Apply business logic for mask interactions
// If entity has no name and is set to readonly, also exclude from web
if (updatedDe.n === '' && hasMask(newMask, DeviceEntityMask.DV_READONLY)) {
updatedDe.m = newMask | DeviceEntityMask.DV_WEB_EXCLUDE;
} else {
updatedDe.m = newMask;
}
// If entity has no name and is set to readonly, also exclude from web
if (updatedDe.n === '' && hasMask(newMask, DeviceEntityMask.DV_READONLY)) {
updatedDe.m = newMask | DeviceEntityMask.DV_WEB_EXCLUDE;
} else {
updatedDe.m = newMask;
}
// If excluded from web, cannot be favorite
if (hasMask(updatedDe.m, DeviceEntityMask.DV_WEB_EXCLUDE)) {
updatedDe.m = updatedDe.m & ~DeviceEntityMask.DV_FAVORITE;
}
// If excluded from web, cannot be favorite
if (hasMask(updatedDe.m, DeviceEntityMask.DV_WEB_EXCLUDE)) {
updatedDe.m = updatedDe.m & ~DeviceEntityMask.DV_FAVORITE;
}
onUpdate(updatedDe);
},
[de, onUpdate]
);
// Memoize mask string value
const maskStringValue = useMemo(() => getMaskString(de.m), [de.m]);
// Memoize disabled states
const isFavoriteDisabled = useMemo(
() =>
hasMask(de.m, DeviceEntityMask.DV_WEB_EXCLUDE | DeviceEntityMask.DV_DELETED) ||
de.n === undefined,
[de.m, de.n]
);
const isReadonlyDisabled = useMemo(
() =>
!de.w ||
hasMask(de.m, DeviceEntityMask.DV_WEB_EXCLUDE | DeviceEntityMask.DV_FAVORITE),
[de.w, de.m]
);
const isApiMqttExcludeDisabled = useMemo(
() => de.n === '' || hasMask(de.m, DeviceEntityMask.DV_DELETED),
[de.n, de.m]
);
const isWebExcludeDisabled = useMemo(
() => de.n === undefined || hasMask(de.m, DeviceEntityMask.DV_DELETED),
[de.n, de.m]
);
// Memoize mask flag checks
const isFavoriteSet = useMemo(
() => hasMask(de.m, DeviceEntityMask.DV_FAVORITE),
[de.m]
);
const isReadonlySet = useMemo(
() => hasMask(de.m, DeviceEntityMask.DV_READONLY),
[de.m]
);
const isApiMqttExcludeSet = useMemo(
() => hasMask(de.m, DeviceEntityMask.DV_API_MQTT_EXCLUDE),
[de.m]
);
const isWebExcludeSet = useMemo(
() => hasMask(de.m, DeviceEntityMask.DV_WEB_EXCLUDE),
[de.m]
);
const isDeletedSet = useMemo(
() => hasMask(de.m, DeviceEntityMask.DV_DELETED),
[de.m]
);
onUpdate(updatedDe);
};
return (
<ToggleButtonGroup
size="small"
color="secondary"
value={maskStringValue}
value={getMaskString(de.m)}
onChange={handleChange}
>
<ToggleButton value="8" disabled={isFavoriteDisabled}>
<OptionIcon type="favorite" isSet={isFavoriteSet} />
<ToggleButton
value="8"
disabled={
hasMask(
de.m,
DeviceEntityMask.DV_WEB_EXCLUDE | DeviceEntityMask.DV_DELETED
) || de.n === undefined
}
>
<OptionIcon
type="favorite"
isSet={hasMask(de.m, DeviceEntityMask.DV_FAVORITE)}
/>
</ToggleButton>
<ToggleButton value="4" disabled={isReadonlyDisabled}>
<OptionIcon type="readonly" isSet={isReadonlySet} />
<ToggleButton
value="4"
disabled={
!de.w ||
hasMask(
de.m,
DeviceEntityMask.DV_WEB_EXCLUDE | DeviceEntityMask.DV_FAVORITE
)
}
>
<OptionIcon
type="readonly"
isSet={hasMask(de.m, DeviceEntityMask.DV_READONLY)}
/>
</ToggleButton>
<ToggleButton value="2" disabled={isApiMqttExcludeDisabled}>
<OptionIcon type="api_mqtt_exclude" isSet={isApiMqttExcludeSet} />
<ToggleButton
value="2"
disabled={de.n === '' || hasMask(de.m, DeviceEntityMask.DV_DELETED)}
>
<OptionIcon
type="api_mqtt_exclude"
isSet={hasMask(de.m, DeviceEntityMask.DV_API_MQTT_EXCLUDE)}
/>
</ToggleButton>
<ToggleButton value="1" disabled={isWebExcludeDisabled}>
<OptionIcon type="web_exclude" isSet={isWebExcludeSet} />
<ToggleButton
value="1"
disabled={de.n === undefined || hasMask(de.m, DeviceEntityMask.DV_DELETED)}
>
<OptionIcon
type="web_exclude"
isSet={hasMask(de.m, DeviceEntityMask.DV_WEB_EXCLUDE)}
/>
</ToggleButton>
<ToggleButton value="128">
<OptionIcon type="deleted" isSet={isDeletedSet} />
<OptionIcon
type="deleted"
isSet={hasMask(de.m, DeviceEntityMask.DV_DELETED)}
/>
</ToggleButton>
</ToggleButtonGroup>
);