@iobroker/dm-gui-components 10.0.21 → 10.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -197,6 +197,14 @@ const indicator = {
197
197
  -->
198
198
 
199
199
  ## Changelog
200
+ ### 10.0.23 (2026-09-21)
201
+ - (@BenAhrdt) Supported explicit line breaks in status indicator tooltips
202
+
203
+ ### 10.0.22 (2026-09-18)
204
+ - (@GermanBluefox) Updated packages
205
+ - (@GermanBluefox) Renamed `Config manager` to `Konfig-Manager` (DE)
206
+ - (@GermanBluefox) Text colors in toolbar was changed
207
+
200
208
  ### 10.0.21 (2026-08-31)
201
209
  - (@GermanBluefox) Improved: device list performance with many devices (ioBroker/ioBroker.matter#864) — cards are only rendered while they are near the viewport, a reload no longer unmounts and remounts the whole list, and a second load requested while one is running is no longer executed in parallel
202
210
  - (@GermanBluefox) Changed: filtering moved from the cards into the list, so filtered out devices no longer stay mounted with all their subscriptions
@@ -40,6 +40,25 @@ function deviceKey(device) {
40
40
  * and a few hundred pulsing placeholders cost more than the cards they are waiting for.
41
41
  */
42
42
  const MAX_SKELETONS = 12;
43
+ /**
44
+ * The toolbar is grey in both themes, so its content is always white. Buttons and inputs bring their own
45
+ * colors (primary blue, the text color of the theme), which are hard to read on grey and are overridden here.
46
+ */
47
+ const TOOLBAR_SX = {
48
+ backgroundColor: '#777',
49
+ color: '#fff',
50
+ '& .MuiButtonBase-root.Mui-disabled': { color: 'rgba(255, 255, 255, 0.4)' },
51
+ '& .MuiInputBase-root, & .MuiSelect-icon': { color: 'inherit' },
52
+ '& .MuiInputBase-input::placeholder': { opacity: 0.7 },
53
+ '& .MuiInput-underline::before': { borderBottomColor: 'rgba(255, 255, 255, 0.7)' },
54
+ '& .MuiInput-underline:hover:not(.Mui-disabled, .Mui-error)::before': { borderBottomColor: '#fff' },
55
+ '& .MuiInput-underline::after': { borderBottomColor: '#fff' },
56
+ };
57
+ /** Marks an active toggle button in the toolbar, as the primary color is not readable there */
58
+ const TOOLBAR_TOGGLE_ACTIVE_SX = {
59
+ backgroundColor: 'rgba(255, 255, 255, 0.25)',
60
+ '&:hover': { backgroundColor: 'rgba(255, 255, 255, 0.35)' },
61
+ };
43
62
  /** Returns true if any of the device status objects carries a battery value */
44
63
  function hasBatteryStatus(status) {
45
64
  if (!status || typeof status === 'string') {
@@ -626,7 +645,7 @@ export default class DeviceList extends Communication {
626
645
  input: {
627
646
  autoComplete: 'new-password',
628
647
  endAdornment: this.state.filterText ? (React.createElement(InputAdornment, { position: "end" },
629
- React.createElement(IconButton, { tabIndex: -1, onClick: () => this.handleFilterChange(''), edge: "end" },
648
+ React.createElement(IconButton, { tabIndex: -1, onClick: () => this.handleFilterChange(''), color: "inherit", edge: "end" },
630
649
  React.createElement(Clear, null)))) : null,
631
650
  },
632
651
  htmlInput: {
@@ -718,7 +737,7 @@ export default class DeviceList extends Communication {
718
737
  }
719
738
  return (React.createElement(React.Fragment, null,
720
739
  React.createElement(Tooltip, { title: getTranslation('indicatorsTooltip'), slotProps: { popper: { sx: { pointerEvents: 'none' } } } },
721
- React.createElement(IconButton, { size: "small", onClick: e => this.setState({ indicatorsAnchor: e.currentTarget }) },
740
+ React.createElement(IconButton, { size: "small", color: "inherit", onClick: e => this.setState({ indicatorsAnchor: e.currentTarget }) },
722
741
  React.createElement(Tune, null))),
723
742
  React.createElement(Menu, { open: !!this.state.indicatorsAnchor, anchorEl: this.state.indicatorsAnchor, onClose: () => this.setState({ indicatorsAnchor: null }) },
724
743
  React.createElement(ListSubheader, { style: { lineHeight: '32px' } }, getTranslation('indicatorsTitle')),
@@ -867,8 +886,7 @@ export default class DeviceList extends Communication {
867
886
  this.state.apiVersionError ? React.createElement("div", null, I18n.t('apiVersionError')) : list));
868
887
  }
869
888
  return (React.createElement("div", { style: { width: '100%', height: '100%', overflow: 'hidden', display: 'flex', flexDirection: 'column' } },
870
- React.createElement(Toolbar, { variant: "dense", style: {
871
- backgroundColor: '#777',
889
+ React.createElement(Toolbar, { variant: "dense", sx: TOOLBAR_SX, style: {
872
890
  display: 'flex',
873
891
  flexWrap: 'wrap',
874
892
  rowGap: 4,
@@ -880,17 +898,17 @@ export default class DeviceList extends Communication {
880
898
  this.state.dmInstances &&
881
899
  this.state.selectedInstance ? (React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: 8 } },
882
900
  Object.keys(this.state.dmInstances).length > 1 ? (React.createElement(Tooltip, { title: getTranslation('backToInstancesList'), slotProps: { popper: { sx: { pointerEvents: 'none' } } } },
883
- React.createElement(IconButton, { onClick: () => this.backToInstancesList(), size: "small" },
901
+ React.createElement(IconButton, { onClick: () => this.backToInstancesList(), color: "inherit", size: "small" },
884
902
  React.createElement(ArrowBack, null)))) : null,
885
903
  this.state.dmInstances[this.state.selectedInstance]?.icon ? (React.createElement(Icon, { src: this.state.dmInstances[this.state.selectedInstance].icon, style: { width: 24, height: 24 } })) : null,
886
904
  React.createElement("span", { style: { marginRight: 8 } }, this.state.selectedInstance))) : null,
887
905
  this.props.selectedInstance === undefined && !this.state.selectedInstance ? (React.createElement(Tooltip, { title: getTranslation('refreshInstanceList'), slotProps: { popper: { sx: { pointerEvents: 'none' } } } },
888
906
  React.createElement("span", null,
889
- React.createElement(IconButton, { onClick: () => this.refreshInstanceList(), disabled: !this.state.dmInstances, size: "small" },
907
+ React.createElement(IconButton, { onClick: () => this.refreshInstanceList(), disabled: !this.state.dmInstances, color: "inherit", size: "small" },
890
908
  React.createElement(Refresh, null))))) : null,
891
909
  this.state.selectedInstance ? (React.createElement(Tooltip, { title: getTranslation('refreshTooltip'), slotProps: { popper: { sx: { pointerEvents: 'none' } } } },
892
910
  React.createElement("span", null,
893
- React.createElement(IconButton, { onClick: () => this.loadAllData(), disabled: !this.state.alive || this.state.apiVersionError, size: "small" },
911
+ React.createElement(IconButton, { onClick: () => this.loadAllData(), disabled: !this.state.alive || this.state.apiVersionError, color: "inherit", size: "small" },
894
912
  React.createElement(Refresh, null))))) : null,
895
913
  !this.state.apiVersionError && this.state.alive && this.renderInstanceActions(),
896
914
  !this.state.apiVersionError && this.state.alive && this.state.instanceInfo?.indicators?.length ? (React.createElement(StatusIndicators, { indicators: this.state.instanceInfo.indicators.filter(indicator => this.isIndicatorVisible(indicator)), theme: this.props.theme, stateOrObjectHandler: this.stateOrObjectHandler, resolveAction: this.resolveInstanceIndicatorAction, defaultColor: "#fff", style: { marginLeft: 20 } })) : null,
@@ -899,7 +917,7 @@ export default class DeviceList extends Communication {
899
917
  !this.state.apiVersionError &&
900
918
  this.state.alive &&
901
919
  this.state.devices.some(device => device.update) ? (React.createElement(Tooltip, { title: getTranslation('onlyUpdatableTooltip'), slotProps: { popper: { sx: { pointerEvents: 'none' } } } },
902
- React.createElement(IconButton, { color: this.state.onlyUpdatable ? 'primary' : 'default', onClick: () => {
920
+ React.createElement(IconButton, { color: "inherit", sx: this.state.onlyUpdatable ? TOOLBAR_TOGGLE_ACTIVE_SX : undefined, onClick: () => {
903
921
  const onlyUpdatable = !this.state.onlyUpdatable;
904
922
  this.setState({ onlyUpdatable });
905
923
  window.localStorage.setItem('dm_onlyUpdatable', onlyUpdatable ? 'true' : 'false');
@@ -908,7 +926,7 @@ export default class DeviceList extends Communication {
908
926
  !this.state.apiVersionError &&
909
927
  this.state.alive &&
910
928
  this.state.devices.some(device => hasBatteryStatus(device.status)) ? (React.createElement(Tooltip, { title: getTranslation('onlyBatteryProblemTooltip'), slotProps: { popper: { sx: { pointerEvents: 'none' } } } },
911
- React.createElement(IconButton, { color: this.state.onlyBatteryProblem ? 'primary' : 'default', onClick: () => {
929
+ React.createElement(IconButton, { color: "inherit", sx: this.state.onlyBatteryProblem ? TOOLBAR_TOGGLE_ACTIVE_SX : undefined, onClick: () => {
912
930
  const onlyBatteryProblem = !this.state.onlyBatteryProblem;
913
931
  this.setState({ onlyBatteryProblem });
914
932
  window.localStorage.setItem('dm_onlyBatteryProblem', onlyBatteryProblem ? 'true' : 'false');
@@ -916,15 +934,14 @@ export default class DeviceList extends Communication {
916
934
  React.createElement(BatteryAlert, null)))) : null,
917
935
  !this.state.apiVersionError && this.state.alive ? this.renderIndicatorSettings() : null,
918
936
  !this.state.apiVersionError && this.state.alive ? (React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' } },
919
- React.createElement(FilterAlt, { style: { color: '#fff' } }),
937
+ React.createElement(FilterAlt, null),
920
938
  this.renderFilterFields(),
921
939
  this.renderFilterValue())) : null,
922
940
  React.createElement(Typography, { sx: { display: { xs: 'none', md: 'block' } }, style: {
923
941
  marginLeft: 16,
924
942
  fontWeight: 'bold',
925
943
  whiteSpace: 'nowrap',
926
- color: '#fff',
927
- } }, "Config-Manager")),
944
+ } }, I18n.t('configManager'))),
928
945
  React.createElement("div", { ref: this.containerRef, style: {
929
946
  width: '100%',
930
947
  flex: 1,
@@ -1 +1 @@
1
- {"version":3,"file":"DeviceList.js","sourceRoot":"./src/","sources":["DeviceList.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { type JSX } from 'react';\nimport {\n IconButton,\n InputAdornment,\n TextField,\n Toolbar,\n Tooltip,\n LinearProgress,\n Select,\n MenuItem,\n Card,\n CardActionArea,\n CardContent,\n Typography,\n Menu,\n Checkbox,\n ListSubheader,\n} from '@mui/material';\n\nimport {\n ArrowBack,\n Clear,\n QuestionMark,\n Refresh,\n FilterAlt,\n FilterAltOff,\n SystemUpdateAlt,\n BatteryAlert,\n Tune,\n} from '@mui/icons-material';\n\nimport { I18n, DeviceTypeIcon, Icon, InfoBox } from '@iobroker/gui-components';\nimport type { DeviceId, DeviceInfo, DeviceStatus, InstanceDetails, StatusIndicator } from './protocol/api';\n\nimport DeviceCard, {\n DeviceCardSkeleton,\n CARD_WIDTH,\n CARD_MIN_HEIGHT,\n CARD_MARGIN,\n SMALL_CARD_WIDTH,\n SMALL_CARD_MIN_HEIGHT,\n SMALL_CARD_MARGIN,\n} from './DeviceCard';\nimport { getTranslation, renderIcon } from './Utils';\nimport Communication, { type CommunicationProps, type CommunicationState } from './Communication';\nimport InstanceActionButton from './InstanceActionButton';\nimport { StatusIndicators } from './StatusIndicator';\nimport { StateOrObjectHandler } from './StateOrObjectHandler';\nimport { DeviceFieldsResolver, type DeviceFilterField } from './DeviceFields';\nimport { LazyRender, LazyRenderObserver } from './LazyRender';\n\nimport de from './i18n/de.json';\nimport en from './i18n/en.json';\nimport ru from './i18n/ru.json';\nimport pt from './i18n/pt.json';\nimport nl from './i18n/nl.json';\nimport fr from './i18n/fr.json';\nimport it from './i18n/it.json';\nimport es from './i18n/es.json';\nimport pl from './i18n/pl.json';\nimport uk from './i18n/uk.json';\nimport zhCn from './i18n/zh-cn.json';\n\n/**\n * The key of a device. It is used as React key, for the resolved fields and for the filter, so it is\n * computed on every render for every device. `JSON.stringify` adds up noticeably with a few hundred\n * devices, therefore the result is cached per device object.\n */\nconst deviceKeys = new WeakMap<DeviceInfo, string>();\n\nfunction deviceKey(device: DeviceInfo): string {\n let key = deviceKeys.get(device);\n if (key === undefined) {\n key = JSON.stringify(device.id);\n deviceKeys.set(device, key);\n }\n return key;\n}\n\n/**\n * How many skeletons are shown at most while loading. They stand for devices that are not there yet,\n * and a few hundred pulsing placeholders cost more than the cards they are waiting for.\n */\nconst MAX_SKELETONS = 12;\n\n/** Returns true if any of the device status objects carries a battery value */\nfunction hasBatteryStatus(status?: DeviceStatus | DeviceStatus[]): boolean {\n if (!status || typeof status === 'string') {\n return false;\n }\n const list = Array.isArray(status) ? status : [status];\n return list.some(entry => typeof entry !== 'string' && entry.battery !== undefined);\n}\n\ninterface DeviceListProps extends CommunicationProps {\n /** Instance to upload images to, like `adapterName.X` */\n uploadImagesToInstance?: string;\n /** Filter devices with this string */\n filter?: string;\n /** If this component is used in GUI with own toolbar. `false` if this list is used with multiple instances and true if only with one (in this case, it will monitor alive itself */\n embedded?: boolean;\n /** If embedded, this text is shown in the toolbar */\n title?: string;\n /** Style of a component that displays all devices */\n style?: React.CSSProperties;\n /** Use small cards for devices */\n smallCards?: boolean;\n /** To trigger the reload of devices, just change this variable */\n triggerLoad?: number;\n}\n\ninterface DeviceListState extends CommunicationState {\n devices: DeviceInfo[];\n totalDevices?: number;\n filter: string;\n filterText: string;\n instanceInfo: InstanceDetails | null;\n loading: boolean | null;\n alive: boolean | null;\n triggerLoad: number;\n groupKey: string;\n dmInstances: { [instanceName: string]: { title: string; icon: string; instance: number } } | null;\n apiVersionError: boolean;\n /** Show only devices that have an available update */\n onlyUpdatable: boolean;\n /** Show only devices that have a battery problem */\n onlyBatteryProblem: boolean;\n /** Device field the text filter applies to */\n filterField: DeviceFilterField;\n /** Distinct resolved model values across the loaded devices (for the model filter dropdown) */\n modelOptions: string[];\n /** Visibility of the configurable indicators, as explicitly chosen by the user for this instance */\n indicatorVisibility: Record<string, boolean>;\n /** Anchor of the indicator visibility menu */\n indicatorsAnchor: HTMLElement | null;\n /** Increased whenever a device field bound to a state or an object changed, to trigger a re-render */\n fieldsVersion: number;\n}\n\n/**\n * Device List Component\n */\nexport default class DeviceList extends Communication<DeviceListProps, DeviceListState> {\n static i18nInitialized = false;\n\n private lastInstance: string;\n\n private lastAliveSubscribe = '';\n\n /**\n * Synchronous mirror of `state.alive`. `setState` is asynchronous, so the guard in `aliveHandler`\n * cannot rely on `state.alive` being committed yet when `subscribeState` replays the current value.\n * This field is always updated synchronously together with `setState({ alive })` and is the source\n * of truth for the \"did alive actually change?\" check, which prevents the double device load.\n */\n private alive: boolean | null = null;\n\n private lastTriggerLoad = 0;\n\n private filterTimeout: ReturnType<typeof setTimeout> | null = null;\n\n private readonly language: ioBroker.Languages = I18n.getLanguage();\n\n /**\n * One handler for the toolbar indicators and for all cards, so that several devices referring to\n * the same object or state share a single subscription on the socket.\n */\n private readonly stateOrObjectHandler: StateOrObjectHandler;\n\n /** Resolves the device fields that may be bound to a state or an object (name, model, ...) */\n private readonly fieldsResolver: DeviceFieldsResolver;\n\n /** One `IntersectionObserver` for all cards: only what is near the viewport is really rendered */\n private readonly lazyObserver = new LazyRenderObserver();\n\n /** The scrolling container of the card list; it is the root of `lazyObserver` */\n private readonly containerRef = React.createRef<HTMLDivElement>();\n\n /** A load is running. A second one must not tear down the same list in parallel */\n private loadingDevices = false;\n\n /** A load was requested while another one was still running */\n private reloadRequested = false;\n\n /** Devices of the running initial load that are not published to the state yet */\n private pendingDevices: DeviceInfo[] | null = null;\n\n private pendingTotal: number | undefined;\n\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n\n /** Memoized result of `getHiddenIndicators`, so that all cards keep getting the same array */\n private hiddenIndicatorsCache: { key: string; value: string[] } | null = null;\n\n constructor(props: DeviceListProps) {\n super(props);\n\n this.stateOrObjectHandler = new StateOrObjectHandler(this.props.socket);\n this.fieldsResolver = new DeviceFieldsResolver(this.stateOrObjectHandler, this.onFieldsChanged);\n\n if (!DeviceList.i18nInitialized) {\n DeviceList.i18nInitialized = true;\n I18n.extendTranslations({\n en,\n de,\n ru,\n pt,\n nl,\n fr,\n it,\n es,\n pl,\n uk,\n 'zh-cn': zhCn,\n });\n }\n\n this.state = {\n ...this.state,\n devices: [],\n filter: '',\n filterText: '',\n instanceInfo: null,\n loading: null,\n alive: null,\n groupKey: '',\n dmInstances: null,\n apiVersionError: false,\n onlyUpdatable: window.localStorage.getItem('dm_onlyUpdatable') === 'true',\n onlyBatteryProblem: window.localStorage.getItem('dm_onlyBatteryProblem') === 'true',\n filterField: (window.localStorage.getItem('dm_filterField') as DeviceFilterField) || 'name',\n modelOptions: [],\n indicatorVisibility: {},\n indicatorsAnchor: null,\n fieldsVersion: 0,\n };\n\n if (this.props.selectedInstance === undefined) {\n // Start with the root page that shows all instances as cards\n this.state = { ...this.state, selectedInstance: this.props.instance ?? '' };\n }\n\n this.state = {\n ...this.state,\n indicatorVisibility: DeviceList.loadIndicatorVisibility(this.state.selectedInstance),\n };\n\n this.lastInstance = this.state.selectedInstance;\n this.lastTriggerLoad = this.props.triggerLoad || 0;\n }\n\n setStateAsync(state: Partial<DeviceListState>): Promise<void> {\n return new Promise<void>(resolve => this.setState(state as DeviceListState, resolve));\n }\n\n private async loadAdapters(): Promise<void> {\n await this.props.socket.waitForFirstConnection();\n\n console.log('Loading adapters...');\n const res = await this.props.socket.getObjectViewSystem('instance', 'system.adapter.', 'system.adapter.\\u9999');\n const dmInstances: { [instanceName: string]: { title: string; icon: string; instance: number } } = {};\n for (const id in res) {\n if (!res[id].common.supportedMessages?.deviceManager) {\n continue;\n }\n\n const instanceName = id.substring('system.adapter.'.length);\n try {\n // Check if the instance is alive by getting the state alive\n const alive = await this.props.socket.getState(`system.adapter.${instanceName}.alive`);\n if (!alive?.val) {\n continue;\n }\n\n const instance = parseInt(instanceName.split('.').pop() || '0') || 0;\n const common = res[id].common;\n const adapterName = instanceName.split('.')[0];\n dmInstances[instanceName] = {\n title: common.titleLang ? this.getText(common.titleLang) : common.title || adapterName,\n icon: common.icon ? `./adapter/${adapterName}/${common.icon}` : common.extIcon || '',\n instance,\n };\n } catch (error) {\n console.error(error);\n }\n }\n\n if (Object.keys(dmInstances).length === 1) {\n // With only one instance, select it directly and do not show the root page\n const selectedInstance = Object.keys(dmInstances)[0];\n await this.setStateAsync({\n dmInstances,\n selectedInstance,\n groupKey: window.localStorage.getItem(`dm_group_${selectedInstance}`) || '',\n });\n } else {\n await this.setStateAsync({ dmInstances });\n }\n }\n\n private selectInstance(instanceId: string): void {\n window.localStorage.setItem('dmSelectedInstance', instanceId);\n this.props.onInstanceChanged?.(instanceId);\n this.setState({\n selectedInstance: instanceId,\n groupKey: window.localStorage.getItem(`dm_group_${instanceId}`) || '',\n });\n }\n\n private backToInstancesList(): void {\n window.localStorage.removeItem('dmSelectedInstance');\n this.props.onInstanceChanged?.('');\n this.alive = null;\n this.applyDevices([], {\n selectedInstance: '',\n totalDevices: undefined,\n instanceInfo: null,\n alive: null,\n groupKey: '',\n filter: '',\n filterText: '',\n apiVersionError: false,\n });\n }\n\n private refreshInstanceList(): void {\n this.setState({ dmInstances: null }, () => this.loadAdapters().catch(console.error));\n }\n\n async componentDidMount(): Promise<void> {\n this.lazyObserver.setRoot(this.containerRef.current);\n\n let alive = false;\n // If an instance selector must be shown\n if (this.props.selectedInstance === undefined) {\n // show instance selector\n await this.loadAdapters();\n }\n\n if (this.alive === null && this.state.selectedInstance) {\n try {\n // check if the instance is alive\n const stateAlive = await this.props.socket.getState(\n `system.adapter.${this.state.selectedInstance}.alive`,\n );\n if (stateAlive?.val) {\n alive = true;\n }\n } catch (error) {\n console.error(error);\n }\n // Update the synchronous mirror BEFORE subscribing. `subscribeState` replays the current\n // value to `aliveHandler`; with `this.alive` already set, that replay is recognized as\n // \"no change\" and does not trigger a second `loadAllData()` in addition to the one below.\n this.alive = alive;\n this.lastAliveSubscribe = this.state.selectedInstance;\n this.setState({ alive });\n await this.props.socket.subscribeState(\n `system.adapter.${this.state.selectedInstance}.alive`,\n this.aliveHandler,\n );\n } else if (this.alive !== null) {\n alive = this.alive;\n }\n\n if (alive) {\n try {\n await this.loadAllData();\n } catch (error) {\n console.error(error);\n }\n }\n }\n\n componentWillUnmount(): void {\n super.componentWillUnmount();\n this.cancelDeviceFlush();\n this.fieldsResolver.destroy();\n this.stateOrObjectHandler.destroy();\n this.lazyObserver.destroy();\n if (this.filterTimeout) {\n clearTimeout(this.filterTimeout);\n this.filterTimeout = null;\n }\n if (this.state.selectedInstance) {\n this.props.socket.unsubscribeState(\n `system.adapter.${this.state.selectedInstance}.alive`,\n this.aliveHandler,\n );\n }\n }\n\n /**\n * The side effects that used to be triggered from `render()`. A render must not have any, and\n * the `setTimeout` there was executed on every single render.\n */\n componentDidUpdate(): void {\n // The scrolling container only exists after the first render\n this.lazyObserver.setRoot(this.containerRef.current);\n\n if ((this.props.triggerLoad || 0) !== this.lastTriggerLoad) {\n this.lastTriggerLoad = this.props.triggerLoad || 0;\n this.loadDeviceList();\n }\n\n // if instance changed\n if (this.lastInstance !== this.state.selectedInstance) {\n this.lastInstance = this.state.selectedInstance;\n // The indicator visibility is stored per instance\n this.setState({\n indicatorVisibility: DeviceList.loadIndicatorVisibility(this.state.selectedInstance),\n indicatorsAnchor: null,\n });\n if (this.state.selectedInstance) {\n this.loadAllData().catch(error => console.error(error));\n } else {\n this.loadDeviceList();\n }\n }\n\n if (this.props.selectedInstance && this.props.selectedInstance !== this.state.selectedInstance) {\n this.setState({ selectedInstance: this.props.selectedInstance });\n }\n }\n\n /**\n * A value bound to a state or an object arrived. The cards are `PureComponent`s and receive the\n * values through their `fields` property, so the list only has to trigger a re-render.\n */\n private onFieldsChanged = (): void => {\n const modelOptions = this.fieldsResolver.getModels();\n const modelsChanged =\n modelOptions.length !== this.state.modelOptions.length ||\n modelOptions.some((model, i) => model !== this.state.modelOptions[i]);\n\n this.setState({\n fieldsVersion: this.state.fieldsVersion + 1,\n modelOptions: modelsChanged ? modelOptions : this.state.modelOptions,\n });\n };\n\n /**\n * Publish a new device list.\n *\n * The resolver is updated *before* the state, because it resolves literal values synchronously -\n * the cards and the filter therefore already have their values on the very first render.\n */\n private applyDevices(devices: DeviceInfo[], state: Partial<DeviceListState>): void {\n this.fieldsResolver.setDevices(devices.map(device => ({ key: deviceKey(device), device })));\n this.setState({ ...state, devices } as DeviceListState);\n }\n\n /**\n * Publish the devices loaded so far, but at most every 100 ms: a fast backend delivers a dozen\n * batches in a row, and every single one of them would otherwise re-render the complete list.\n */\n private scheduleDeviceFlush(devices: DeviceInfo[], total?: number): void {\n this.pendingDevices = devices;\n this.pendingTotal = total;\n if (this.flushTimer) {\n return;\n }\n this.flushTimer = setTimeout(() => {\n this.flushTimer = null;\n const pending = this.pendingDevices;\n if (pending) {\n this.pendingDevices = null;\n this.applyDevices(pending, { loading: true, totalDevices: this.pendingTotal });\n }\n }, 100);\n }\n\n private cancelDeviceFlush(): void {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n this.pendingDevices = null;\n }\n\n aliveHandler: ioBroker.StateChangeHandler = (id: string, state: ioBroker.State | null | undefined): void => {\n if (this.state.selectedInstance && id === `system.adapter.${this.state.selectedInstance}.alive`) {\n const alive = !!state?.val;\n // Compare against the synchronous mirror, not `state.alive` (which may not be committed yet\n // when `subscribeState` replays the initial value). This is what stops the double load.\n if (alive !== this.alive) {\n this.alive = alive;\n this.setState({ alive }, () => {\n if (alive) {\n // The instance just became alive: (re)load all data directly instead of\n // re-running the whole mount logic.\n this.loadAllData().catch(console.error);\n }\n });\n }\n }\n };\n\n override async loadAllData(): Promise<void> {\n await this.loadInstanceInfos();\n this.loadDeviceList();\n }\n\n override async loadInstanceInfos(): Promise<InstanceDetails> {\n const instanceInfo = await super.loadInstanceInfos();\n return new Promise<InstanceDetails>(resolve =>\n this.setState(\n { instanceInfo, apiVersionError: !['v1', 'v2', 'v3'].includes(instanceInfo.apiVersion) },\n () => resolve(instanceInfo),\n ),\n );\n }\n\n /**\n * Load devices.\n *\n * The list is deliberately *not* emptied first: as long as the keys stay the same React keeps the\n * existing cards, so a reload - the matter adapter triggers one on every `updateController`\n * message - no longer unmounts and remounts a few hundred cards with all their subscriptions.\n */\n override loadDeviceList(): void {\n if (this.loadingDevices) {\n // Remember the request and repeat the load once the running one has finished, instead of\n // running two loads over the same list at the same time.\n this.reloadRequested = true;\n return;\n }\n this.loadingDevices = true;\n\n this.setState({ loading: true }, async () => {\n console.log(`Loading devices for ${this.state.selectedInstance}...`);\n let alive = this.alive;\n\n if (this.state.selectedInstance !== this.lastAliveSubscribe) {\n if (this.lastAliveSubscribe) {\n // unsubscribe from the old instance\n this.props.socket.unsubscribeState(\n `system.adapter.${this.lastAliveSubscribe}.alive`,\n this.aliveHandler,\n );\n }\n\n this.lastAliveSubscribe = this.state.selectedInstance;\n\n if (this.state.selectedInstance) {\n try {\n // check if the instance is alive\n const stateAlive = await this.props.socket.getState(\n `system.adapter.${this.state.selectedInstance}.alive`,\n );\n alive = !!stateAlive?.val;\n } catch (error) {\n console.error(error);\n alive = false;\n }\n // Set the synchronous mirror before subscribing so the replayed initial value\n // does not trigger an extra load on top of the one performed right below.\n this.alive = alive;\n await this.props.socket.subscribeState(\n `system.adapter.${this.state.selectedInstance}.alive`,\n this.aliveHandler,\n );\n } else {\n alive = false;\n }\n }\n\n // Only the very first load shows the devices step by step (with skeletons for the ones\n // that are still missing). A reload keeps the current list until the new one is complete,\n // so the already rendered cards survive.\n const incremental = !this.state.devices.length;\n let devices: DeviceInfo[] = [];\n try {\n this.alive = alive;\n this.setState({ loading: !!alive, alive });\n if (alive) {\n await this.loadDevices((batch, total) => {\n devices = devices.concat(batch);\n if (incremental) {\n this.scheduleDeviceFlush(devices, total);\n }\n console.log(`Loaded ${devices.length} of ${total} devices...`);\n });\n }\n } catch (error) {\n console.error(error);\n devices = [];\n }\n\n this.cancelDeviceFlush();\n this.applyDevices(devices, { loading: false, totalDevices: devices.length });\n console.log(`Loaded ${devices.length} devices for ${this.state.selectedInstance}`);\n\n this.loadingDevices = false;\n if (this.reloadRequested) {\n this.reloadRequested = false;\n setTimeout(() => this.loadDeviceList(), 0);\n }\n });\n }\n\n override updateDevice(update: DeviceInfo): void {\n const updateId = JSON.stringify(update.id);\n this.applyDevices(\n this.state.devices.map(d => (deviceKey(d) === updateId ? update : d)),\n {},\n );\n }\n\n override deleteDevice(deviceId: DeviceId): void {\n const deleteId = JSON.stringify(deviceId);\n const devices = this.state.devices.filter(d => deviceKey(d) !== deleteId);\n const totalDevices =\n this.state.totalDevices && devices.length < this.state.devices.length\n ? this.state.totalDevices - 1\n : undefined;\n this.applyDevices(devices, { totalDevices });\n }\n\n getText(text: ioBroker.StringOrTranslated): string {\n if (typeof text === 'object') {\n return text[this.language] || text.en;\n }\n\n return text;\n }\n\n handleFilterChange(filter: string): void {\n this.setState({ filterText: filter });\n if (this.filterTimeout) {\n clearTimeout(this.filterTimeout);\n }\n this.filterTimeout = setTimeout(() => {\n this.filterTimeout = null;\n this.setState({ filter });\n }, 250);\n }\n\n renderGroups(\n groups: { name: string; value: string; count: number; icon?: React.JSX.Element | string | null }[] | undefined,\n ): React.JSX.Element | null {\n if (!groups?.length) {\n return null;\n }\n\n return (\n <Select\n style={{ minWidth: 120, marginRight: 8, flexShrink: 0 }}\n variant=\"standard\"\n value={this.state.groupKey || '_'}\n renderValue={value => {\n if (value === '_') {\n value = '';\n }\n const g = groups.find(g => g.value === value);\n return (\n <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n {g?.icon || <div style={{ width: 24 }} />}\n {g?.name || value}\n </div>\n );\n }}\n onChange={e => {\n if (e.target.value) {\n window.localStorage.setItem(`dm_group_${this.state.selectedInstance}`, e.target.value);\n } else {\n window.localStorage.removeItem(`dm_group_${this.state.selectedInstance}`);\n }\n this.setState({ groupKey: e.target.value === '_' ? '' : e.target.value });\n }}\n >\n {groups.map(g => (\n <MenuItem\n value={g.value || '_'}\n key={g.value || '_'}\n style={{ display: 'flex', alignItems: 'center', gap: 8 }}\n >\n {g.icon || <div style={{ width: 24 }} />}\n {g.name}\n </MenuItem>\n ))}\n </Select>\n );\n }\n\n renderInstanceCards(): React.JSX.Element[] {\n if (!this.state.dmInstances) {\n return [\n <LinearProgress\n key=\"loadingInstances\"\n style={{ width: '100%' }}\n />,\n ];\n }\n\n const instanceIds = Object.keys(this.state.dmInstances);\n if (!instanceIds.length) {\n return [\n <div\n style={{ padding: 25 }}\n key=\"noInstances\"\n >\n <span>{getTranslation('noInstancesFoundText')}</span>\n </div>,\n ];\n }\n\n const backgroundColor = this.props.theme.palette.mode === 'dark' ? '#0b0b0b' : '#d5d5d5';\n\n if (this.props.smallCards) {\n return instanceIds.map(id => {\n const info = this.state.dmInstances![id];\n return (\n <Card\n key={id}\n sx={{ width: 200, margin: '5px', backgroundColor }}\n >\n <CardActionArea\n onClick={() => this.selectInstance(id)}\n style={{ height: '100%' }}\n >\n <CardContent\n style={{\n height: '100%',\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n padding: 8,\n }}\n >\n {info.icon ? (\n <Icon\n src={info.icon}\n style={{ width: 32, height: 32, flexShrink: 0 }}\n />\n ) : (\n <QuestionMark style={{ width: 32, height: 32, flexShrink: 0 }} />\n )}\n <div style={{ overflow: 'hidden' }}>\n <Typography\n variant=\"body1\"\n noWrap\n style={{ fontSize: 14, fontWeight: 'bold' }}\n >\n {id}\n </Typography>\n {info.title ? (\n <Typography\n variant=\"caption\"\n color=\"textSecondary\"\n noWrap\n component=\"div\"\n >\n {info.title}\n </Typography>\n ) : null}\n </div>\n </CardContent>\n </CardActionArea>\n </Card>\n );\n });\n }\n\n return instanceIds.map(id => {\n const info = this.state.dmInstances![id];\n return (\n <Card\n key={id}\n sx={{ width: 240, margin: '10px', backgroundColor }}\n >\n <CardActionArea\n onClick={() => this.selectInstance(id)}\n style={{ height: '100%' }}\n >\n <CardContent\n style={{\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n gap: 8,\n }}\n >\n {info.icon ? (\n <Icon\n src={info.icon}\n style={{ width: 64, height: 64 }}\n />\n ) : (\n <QuestionMark style={{ width: 64, height: 64 }} />\n )}\n <Typography\n variant=\"h6\"\n style={{ textAlign: 'center', wordBreak: 'break-all' }}\n >\n {id}\n </Typography>\n {info.title ? (\n <Typography\n variant=\"body2\"\n color=\"textSecondary\"\n style={{ textAlign: 'center' }}\n >\n {info.title}\n </Typography>\n ) : null}\n </CardContent>\n </CardActionArea>\n </Card>\n );\n });\n }\n\n /**\n * Apply the text filter and the \"only updatable\" / \"only battery problem\" filters.\n *\n * This used to be done by every card for itself. A filtered out card stayed mounted with all its\n * subscriptions and only rendered nothing, so filtering did not reduce the load at all - and a\n * card that is not rendered cannot filter itself in the first place.\n */\n private filterDevices(devices: DeviceInfo[]): DeviceInfo[] {\n const filter = (this.props.embedded ? this.props.filter : this.state.filter)?.toLowerCase();\n const field: DeviceFilterField = this.props.embedded ? 'name' : this.getEffectiveFilterField();\n const onlyUpdatable = !this.props.embedded && this.state.onlyUpdatable;\n const onlyBatteryProblem = !this.props.embedded && this.state.onlyBatteryProblem;\n\n if (!filter && !onlyUpdatable && !onlyBatteryProblem) {\n return devices;\n }\n\n return devices.filter(device => {\n const fields = this.fieldsResolver.getValues(deviceKey(device));\n if (\n filter &&\n !String(fields[field] ?? '')\n .toLowerCase()\n .includes(filter)\n ) {\n return false;\n }\n if (onlyUpdatable && !fields.updateAvailable) {\n return false;\n }\n if (onlyBatteryProblem && !fields.batteryProblem) {\n return false;\n }\n return true;\n });\n }\n\n /** The selected filter field, falling back to `name` if the stored field is not available (e.g. no models found) */\n private getEffectiveFilterField(): DeviceFilterField {\n const field = this.state.filterField;\n if (field === 'name') {\n return 'name';\n }\n // The model field is only available if at least one model value was actually found\n if (field === 'model') {\n return this.state.modelOptions.length ? 'model' : 'name';\n }\n return this.state.devices.some(device => device[field] !== undefined) ? field : 'name';\n }\n\n renderFilterFields(): React.JSX.Element | null {\n const fields: { value: DeviceFilterField; label: string }[] = [\n { value: 'name', label: getTranslation('name') },\n ];\n if (this.state.devices.some(device => device.identifier !== undefined)) {\n fields.push({\n value: 'identifier',\n label: this.getText(this.state.instanceInfo?.identifierLabel ?? 'ID'),\n });\n }\n if (this.state.devices.some(device => device.manufacturer !== undefined)) {\n fields.push({ value: 'manufacturer', label: getTranslation('manufacturer') });\n }\n // Only offer the model filter if at least one model value was actually found\n if (this.state.modelOptions.length) {\n fields.push({ value: 'model', label: getTranslation('model') });\n }\n\n // Only show the field selector when there is more than just the name to choose from\n if (fields.length < 2) {\n return null;\n }\n\n const current = this.getEffectiveFilterField();\n\n return (\n <Select\n variant=\"standard\"\n style={{ width: 130, flexShrink: 0 }}\n value={current}\n onChange={e => {\n const filterField = e.target.value;\n this.setState({ filterField });\n window.localStorage.setItem('dm_filterField', filterField);\n // reset the current filter value when switching the field\n this.handleFilterChange('');\n }}\n >\n {fields.map(field => (\n <MenuItem\n value={field.value}\n key={field.value}\n >\n {field.label}\n </MenuItem>\n ))}\n </Select>\n );\n }\n\n /** The filter value input: a model dropdown for the `model` field, a free-text field otherwise */\n renderFilterValue(): React.JSX.Element {\n if (this.getEffectiveFilterField() === 'model') {\n const value = this.state.modelOptions.includes(this.state.filterText) ? this.state.filterText : '';\n return (\n <Select\n variant=\"standard\"\n style={{ width: 200 }}\n displayEmpty\n value={value}\n onChange={e => this.handleFilterChange(e.target.value)}\n >\n <MenuItem value=\"\">\n <em>{getTranslation('allModels')}</em>\n </MenuItem>\n {this.state.modelOptions.map(model => (\n <MenuItem\n value={model}\n key={model}\n >\n {model}\n </MenuItem>\n ))}\n </Select>\n );\n }\n\n return (\n <TextField\n variant=\"standard\"\n style={{ width: 200 }}\n size=\"small\"\n placeholder={getTranslation('filterLabelText')}\n onChange={e => this.handleFilterChange(e.target.value)}\n value={this.state.filterText}\n autoComplete=\"off\"\n slotProps={{\n input: {\n autoComplete: 'new-password',\n endAdornment: this.state.filterText ? (\n <InputAdornment position=\"end\">\n <IconButton\n tabIndex={-1}\n onClick={() => this.handleFilterChange('')}\n edge=\"end\"\n >\n <Clear />\n </IconButton>\n </InputAdornment>\n ) : null,\n },\n htmlInput: {\n autoComplete: 'off',\n },\n }}\n />\n );\n }\n\n renderRootInfo(): React.JSX.Element {\n // The root ThemeProvider (Communication.render) already supplies the correct theme context. The explicit color\n // is a safety net, so older InfoBox versions (whose Typography has no own color) stay readable in dark mode.\n return (\n <InfoBox\n key=\"rootInfo\"\n type=\"info\"\n closeable\n storeId=\"dm_rootInfoClosed\"\n style={{\n width: 'calc(100% - 20px)',\n margin: '0 10px 8px 10px',\n color: this.props.theme.palette.text.primary,\n }}\n >\n {I18n.t('rootInfoText')}\n </InfoBox>\n );\n }\n\n /** Key of the stored indicator visibility of one instance */\n private static indicatorStorageKey(instanceId: string): string {\n return `dm_indicators_${instanceId}`;\n }\n\n /** Read the visibility the user has explicitly chosen for the configurable indicators of an instance */\n private static loadIndicatorVisibility(instanceId: string): Record<string, boolean> {\n if (!instanceId) {\n return {};\n }\n try {\n const stored = window.localStorage.getItem(DeviceList.indicatorStorageKey(instanceId));\n return stored ? (JSON.parse(stored) as Record<string, boolean>) : {};\n } catch (error) {\n console.error(error);\n return {};\n }\n }\n\n /**\n * All configurable indicators of the instance and of the loaded devices, unique by ID.\n * Indicators with the same ID on different devices are configured together.\n */\n private getConfigurableIndicators(): StatusIndicator[] {\n const result: StatusIndicator[] = [];\n const seen = new Set<string>();\n\n const collect = (indicators?: StatusIndicator[]): void => {\n for (const indicator of indicators || []) {\n if (indicator.configurable && !seen.has(indicator.id)) {\n seen.add(indicator.id);\n result.push(indicator);\n }\n }\n };\n\n collect(this.state.instanceInfo?.indicators);\n for (const device of this.state.devices) {\n collect(device.indicators);\n }\n\n return result;\n }\n\n /** True if the given configurable indicator is currently shown */\n private isIndicatorVisible(indicator: StatusIndicator): boolean {\n if (!indicator.configurable) {\n return true;\n }\n return this.state.indicatorVisibility[indicator.id] ?? indicator.defaultVisible !== false;\n }\n\n /** IDs of the configurable indicators the user has switched off */\n private getHiddenIndicators(): string[] {\n const hidden = this.getConfigurableIndicators()\n .filter(indicator => !this.isIndicatorVisible(indicator))\n .map(indicator => indicator.id);\n\n // The array is handed to every card. A new array on every render would defeat the shallow\n // property comparison of `DeviceCard`.\n const key = hidden.join(',');\n if (!this.hiddenIndicatorsCache || this.hiddenIndicatorsCache.key !== key) {\n this.hiddenIndicatorsCache = { key, value: hidden };\n }\n return this.hiddenIndicatorsCache.value;\n }\n\n private toggleIndicator(indicator: StatusIndicator): void {\n const indicatorVisibility = {\n ...this.state.indicatorVisibility,\n [indicator.id]: !this.isIndicatorVisible(indicator),\n };\n this.setState({ indicatorVisibility });\n window.localStorage.setItem(\n DeviceList.indicatorStorageKey(this.state.selectedInstance),\n JSON.stringify(indicatorVisibility),\n );\n }\n\n /** The toolbar button that lets the user show or hide the configurable indicators */\n renderIndicatorSettings(): JSX.Element | null {\n const configurable = this.getConfigurableIndicators();\n if (!configurable.length) {\n return null;\n }\n\n return (\n <>\n <Tooltip\n title={getTranslation('indicatorsTooltip')}\n slotProps={{ popper: { sx: { pointerEvents: 'none' } } }}\n >\n <IconButton\n size=\"small\"\n onClick={e => this.setState({ indicatorsAnchor: e.currentTarget })}\n >\n <Tune />\n </IconButton>\n </Tooltip>\n <Menu\n open={!!this.state.indicatorsAnchor}\n anchorEl={this.state.indicatorsAnchor}\n onClose={() => this.setState({ indicatorsAnchor: null })}\n >\n <ListSubheader style={{ lineHeight: '32px' }}>{getTranslation('indicatorsTitle')}</ListSubheader>\n {configurable.map(indicator => (\n <MenuItem\n key={indicator.id}\n onClick={() => this.toggleIndicator(indicator)}\n >\n <Checkbox\n edge=\"start\"\n size=\"small\"\n checked={this.isIndicatorVisible(indicator)}\n />\n {/* Only a literal icon can be shown here, a state-bound one has no value without a device */}\n {typeof indicator.icon === 'string' ? (\n <span style={{ display: 'inline-flex', marginRight: 8 }}>\n {renderIcon(indicator.icon, undefined, true)}\n </span>\n ) : null}\n {this.getText(indicator.label || indicator.tooltip || indicator.id)}\n </MenuItem>\n ))}\n </Menu>\n </>\n );\n }\n\n /** Resolve how an instance indicator behaves on click by looking up the referenced instance action */\n private resolveInstanceIndicatorAction = (\n actionId: string,\n ): { onClick?: () => void; url?: string; disabled?: boolean } | undefined => {\n const action = this.state.instanceInfo?.actions?.find(a => a.id === actionId);\n if (!action) {\n console.warn(\n `Indicator of instance ${this.state.selectedInstance} references unknown action \"${actionId}\"`,\n );\n return undefined;\n }\n\n if ('url' in action && action.url) {\n return { url: getTranslation(action.url), disabled: action.disabled };\n }\n\n return { onClick: this.instanceHandler(action), disabled: action.disabled };\n };\n\n /** Instance actions in the toolbar. An action referenced by an indicator is not rendered twice */\n renderInstanceActions(): JSX.Element | null {\n const referenced = new Set(\n (this.state.instanceInfo?.indicators || [])\n .map(indicator => indicator.actionId)\n .filter((actionId): actionId is string => !!actionId),\n );\n const actions = this.state.instanceInfo?.actions?.filter(action => !referenced.has(action.id));\n\n if (!actions?.length) {\n return null;\n }\n\n return (\n <div style={{ marginLeft: 20 }}>\n {actions.map(action => (\n <InstanceActionButton\n key={action.id}\n action={action}\n instanceHandler={this.instanceHandler}\n />\n ))}\n </div>\n );\n }\n\n renderContent(): JSX.Element | JSX.Element[] | null {\n const emptyStyle: React.CSSProperties = {\n padding: 25,\n };\n\n const deviceGroups: { name: string; value: string; count: number; icon?: React.JSX.Element | string | null }[] =\n [];\n const showRootPage =\n !this.props.embedded && this.props.selectedInstance === undefined && !this.state.selectedInstance;\n\n let list: React.JSX.Element[] | undefined;\n if (showRootPage) {\n list = this.renderInstanceCards();\n list.unshift(this.renderRootInfo());\n } else if (!this.props.embedded && !this.state.alive) {\n list = [\n <div\n style={emptyStyle}\n key=\"notAlive\"\n >\n <span>{getTranslation('instanceNotAlive')}</span>\n </div>,\n ];\n } else if (!this.state.devices.length && this.state.selectedInstance && !this.state.loading) {\n list = [\n <div\n style={emptyStyle}\n key=\"notFound\"\n >\n <span>{getTranslation('noDevicesFoundText')}</span>\n </div>,\n ];\n } else {\n // build a device types list\n let filteredDevices = this.state.devices;\n if (!this.state.loading && !this.props.embedded && filteredDevices.find(device => device.group)) {\n deviceGroups.push({\n name: I18n.t('All'),\n value: '',\n count: filteredDevices.length,\n icon: <FilterAltOff />,\n });\n filteredDevices.forEach(device => {\n if (device.group) {\n const type = deviceGroups.find(t => t.value === device.group?.key);\n if (type) {\n type.count++;\n } else {\n const icon = device.group.icon ? <DeviceTypeIcon src={device.group.icon} /> : null;\n\n deviceGroups.push({\n name: this.getText(device.group.name || device.group.key),\n value: device.group.key,\n count: 1,\n icon,\n });\n }\n }\n });\n const unknown = filteredDevices.filter(device => !device.group);\n if (unknown.length) {\n deviceGroups.push({\n name: I18n.t('Unknown'),\n value: '?',\n count: unknown.length,\n icon: <QuestionMark />,\n });\n }\n\n if (this.state.groupKey && this.state.groupKey !== '_') {\n // filter out all devices belonging to this group\n if (this.state.groupKey === '?') {\n filteredDevices = filteredDevices.filter(device => !device.group?.key);\n } else {\n filteredDevices = filteredDevices.filter(device => device.group?.key === this.state.groupKey);\n }\n }\n }\n\n if (this.state.selectedInstance) {\n const selectedInstance = this.state.selectedInstance;\n const hiddenIndicators = this.getHiddenIndicators();\n const smallCards = this.props.smallCards ?? this.state.instanceInfo?.smallCards;\n const identifierLabel = this.state.instanceInfo?.identifierLabel ?? 'ID';\n const cardWidth = smallCards ? SMALL_CARD_WIDTH : CARD_WIDTH;\n const cardMinHeight = smallCards ? SMALL_CARD_MIN_HEIGHT : CARD_MIN_HEIGHT;\n const cardMargin = smallCards ? SMALL_CARD_MARGIN : CARD_MARGIN;\n const visibleDevices = this.filterDevices(filteredDevices);\n\n // Every card is wrapped in a `LazyRender`: the placeholder always occupies the full\n // footprint of a card, but the card itself is only built while it is near the visible\n // area. Without that, 80 devices mean thousands of DOM nodes and several hundred MUI\n // tooltips and buttons at once - which is what makes Safari (and especially iPadOS)\n // hang and finally kill the tab.\n list = visibleDevices.map(device => {\n const key = deviceKey(device);\n return (\n <LazyRender\n key={key}\n observer={this.lazyObserver}\n width={cardWidth}\n minHeight={cardMinHeight}\n margin={cardMargin}\n >\n {() => (\n <DeviceCard\n fillContainer\n smallCards={smallCards}\n alive={!!this.state.alive}\n id={device.id}\n identifierLabel={identifierLabel}\n device={device}\n fields={this.fieldsResolver.getValues(key)}\n stateOrObjectHandler={this.stateOrObjectHandler}\n instanceId={selectedInstance}\n uploadImagesToInstance={this.props.uploadImagesToInstance}\n deviceHandler={this.deviceHandler}\n controlHandler={this.controlHandler}\n controlStateHandler={this.controlStateHandler}\n socket={this.props.socket}\n themeName={this.props.themeName}\n themeType={this.props.themeType}\n theme={this.props.theme}\n isFloatComma={this.props.isFloatComma}\n dateFormat={this.props.dateFormat}\n hiddenIndicators={hiddenIndicators}\n />\n )}\n </LazyRender>\n );\n });\n\n if (this.state.loading) {\n // How many devices are still missing - deliberately not derived from `list`,\n // which only contains the devices that pass the filter\n const loaded = this.state.devices.length;\n const missing = (this.state.totalDevices ?? loaded + 1) - loaded;\n const skeletons = Math.min(missing, MAX_SKELETONS);\n for (let i = 0; i < skeletons; i++) {\n list.push(\n <DeviceCardSkeleton\n key={`skeleton-${i}`}\n smallCards={smallCards}\n theme={this.props.theme}\n />,\n );\n }\n } else if (!visibleDevices.length && this.state.devices.length > 0) {\n // The filter is applied here now, so the list knows that nothing is left instead\n // of having to hide the message with a CSS rule\n list.push(\n <div\n style={emptyStyle}\n key=\"filtered\"\n >\n <span>{getTranslation('allDevicesFilteredOut')}</span>\n </div>,\n );\n }\n } else {\n list = [\n <div\n style={emptyStyle}\n key=\"selectInstance\"\n >\n <span>{getTranslation('selectInstanceText')}</span>\n </div>,\n ];\n }\n }\n\n if (this.props.embedded) {\n return (\n <>\n {this.state.loading ? <LinearProgress style={{ width: '100%' }} /> : null}\n {this.state.apiVersionError ? <div>{I18n.t('apiVersionError')}</div> : list}\n </>\n );\n }\n\n return (\n <div\n style={{ width: '100%', height: '100%', overflow: 'hidden', display: 'flex', flexDirection: 'column' }}\n >\n <Toolbar\n variant=\"dense\"\n style={{\n backgroundColor: '#777',\n display: 'flex',\n flexWrap: 'wrap',\n rowGap: 4,\n alignItems: 'center',\n flexShrink: 0,\n }}\n >\n {this.props.title}\n {this.props.selectedInstance === undefined &&\n this.state.dmInstances &&\n this.state.selectedInstance ? (\n <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n {Object.keys(this.state.dmInstances).length > 1 ? (\n <Tooltip\n title={getTranslation('backToInstancesList')}\n slotProps={{ popper: { sx: { pointerEvents: 'none' } } }}\n >\n <IconButton\n onClick={() => this.backToInstancesList()}\n size=\"small\"\n >\n <ArrowBack />\n </IconButton>\n </Tooltip>\n ) : null}\n {this.state.dmInstances[this.state.selectedInstance]?.icon ? (\n <Icon\n src={this.state.dmInstances[this.state.selectedInstance].icon}\n style={{ width: 24, height: 24 }}\n />\n ) : null}\n <span style={{ marginRight: 8 }}>{this.state.selectedInstance}</span>\n </div>\n ) : null}\n {this.props.selectedInstance === undefined && !this.state.selectedInstance ? (\n <Tooltip\n title={getTranslation('refreshInstanceList')}\n slotProps={{ popper: { sx: { pointerEvents: 'none' } } }}\n >\n <span>\n <IconButton\n onClick={() => this.refreshInstanceList()}\n disabled={!this.state.dmInstances}\n size=\"small\"\n >\n <Refresh />\n </IconButton>\n </span>\n </Tooltip>\n ) : null}\n {this.state.selectedInstance ? (\n <Tooltip\n title={getTranslation('refreshTooltip')}\n slotProps={{ popper: { sx: { pointerEvents: 'none' } } }}\n >\n <span>\n <IconButton\n onClick={() => this.loadAllData()}\n disabled={!this.state.alive || this.state.apiVersionError}\n size=\"small\"\n >\n <Refresh />\n </IconButton>\n </span>\n </Tooltip>\n ) : null}\n {!this.state.apiVersionError && this.state.alive && this.renderInstanceActions()}\n {!this.state.apiVersionError && this.state.alive && this.state.instanceInfo?.indicators?.length ? (\n <StatusIndicators\n indicators={this.state.instanceInfo.indicators.filter(indicator =>\n this.isIndicatorVisible(indicator),\n )}\n theme={this.props.theme}\n stateOrObjectHandler={this.stateOrObjectHandler}\n resolveAction={this.resolveInstanceIndicatorAction}\n defaultColor=\"#fff\"\n style={{ marginLeft: 20 }}\n />\n ) : null}\n\n <div style={{ flexGrow: 1 }} />\n\n {!this.state.apiVersionError && this.renderGroups(deviceGroups)}\n {!this.state.apiVersionError &&\n this.state.alive &&\n this.state.devices.some(device => device.update) ? (\n <Tooltip\n title={getTranslation('onlyUpdatableTooltip')}\n slotProps={{ popper: { sx: { pointerEvents: 'none' } } }}\n >\n <IconButton\n color={this.state.onlyUpdatable ? 'primary' : 'default'}\n onClick={() => {\n const onlyUpdatable = !this.state.onlyUpdatable;\n this.setState({ onlyUpdatable });\n window.localStorage.setItem('dm_onlyUpdatable', onlyUpdatable ? 'true' : 'false');\n }}\n size=\"small\"\n >\n <SystemUpdateAlt />\n </IconButton>\n </Tooltip>\n ) : null}\n {!this.state.apiVersionError &&\n this.state.alive &&\n this.state.devices.some(device => hasBatteryStatus(device.status)) ? (\n <Tooltip\n title={getTranslation('onlyBatteryProblemTooltip')}\n slotProps={{ popper: { sx: { pointerEvents: 'none' } } }}\n >\n <IconButton\n color={this.state.onlyBatteryProblem ? 'primary' : 'default'}\n onClick={() => {\n const onlyBatteryProblem = !this.state.onlyBatteryProblem;\n this.setState({ onlyBatteryProblem });\n window.localStorage.setItem(\n 'dm_onlyBatteryProblem',\n onlyBatteryProblem ? 'true' : 'false',\n );\n }}\n size=\"small\"\n >\n <BatteryAlert />\n </IconButton>\n </Tooltip>\n ) : null}\n {!this.state.apiVersionError && this.state.alive ? this.renderIndicatorSettings() : null}\n {!this.state.apiVersionError && this.state.alive ? (\n <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>\n <FilterAlt style={{ color: '#fff' }} />\n {this.renderFilterFields()}\n {this.renderFilterValue()}\n </div>\n ) : null}\n <Typography\n sx={{ display: { xs: 'none', md: 'block' } }}\n style={{\n marginLeft: 16,\n fontWeight: 'bold',\n whiteSpace: 'nowrap',\n color: '#fff',\n }}\n >\n Config-Manager\n </Typography>\n </Toolbar>\n <div\n ref={this.containerRef}\n style={{\n width: '100%',\n flex: 1,\n minHeight: 0,\n marginTop: 8,\n overflow: 'auto',\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'stretch',\n alignContent: 'flex-start',\n ...this.props.style,\n }}\n >\n {this.state.loading ? <LinearProgress style={{ width: '100%' }} /> : null}\n {this.state.apiVersionError ? <div>{I18n.t('apiVersionError')}</div> : list}\n </div>\n </div>\n );\n }\n}\n"]}
1
+ {"version":3,"file":"DeviceList.js","sourceRoot":"./src/","sources":["DeviceList.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { type JSX } from 'react';\nimport {\n IconButton,\n InputAdornment,\n TextField,\n Toolbar,\n Tooltip,\n LinearProgress,\n Select,\n MenuItem,\n Card,\n CardActionArea,\n CardContent,\n Typography,\n Menu,\n Checkbox,\n ListSubheader,\n} from '@mui/material';\n\nimport {\n ArrowBack,\n Clear,\n QuestionMark,\n Refresh,\n FilterAlt,\n FilterAltOff,\n SystemUpdateAlt,\n BatteryAlert,\n Tune,\n} from '@mui/icons-material';\n\nimport { I18n, DeviceTypeIcon, Icon, InfoBox } from '@iobroker/gui-components';\nimport type { DeviceId, DeviceInfo, DeviceStatus, InstanceDetails, StatusIndicator } from './protocol/api';\n\nimport DeviceCard, {\n DeviceCardSkeleton,\n CARD_WIDTH,\n CARD_MIN_HEIGHT,\n CARD_MARGIN,\n SMALL_CARD_WIDTH,\n SMALL_CARD_MIN_HEIGHT,\n SMALL_CARD_MARGIN,\n} from './DeviceCard';\nimport { getTranslation, renderIcon } from './Utils';\nimport Communication, { type CommunicationProps, type CommunicationState } from './Communication';\nimport InstanceActionButton from './InstanceActionButton';\nimport { StatusIndicators } from './StatusIndicator';\nimport { StateOrObjectHandler } from './StateOrObjectHandler';\nimport { DeviceFieldsResolver, type DeviceFilterField } from './DeviceFields';\nimport { LazyRender, LazyRenderObserver } from './LazyRender';\n\nimport de from './i18n/de.json';\nimport en from './i18n/en.json';\nimport ru from './i18n/ru.json';\nimport pt from './i18n/pt.json';\nimport nl from './i18n/nl.json';\nimport fr from './i18n/fr.json';\nimport it from './i18n/it.json';\nimport es from './i18n/es.json';\nimport pl from './i18n/pl.json';\nimport uk from './i18n/uk.json';\nimport zhCn from './i18n/zh-cn.json';\n\n/**\n * The key of a device. It is used as React key, for the resolved fields and for the filter, so it is\n * computed on every render for every device. `JSON.stringify` adds up noticeably with a few hundred\n * devices, therefore the result is cached per device object.\n */\nconst deviceKeys = new WeakMap<DeviceInfo, string>();\n\nfunction deviceKey(device: DeviceInfo): string {\n let key = deviceKeys.get(device);\n if (key === undefined) {\n key = JSON.stringify(device.id);\n deviceKeys.set(device, key);\n }\n return key;\n}\n\n/**\n * How many skeletons are shown at most while loading. They stand for devices that are not there yet,\n * and a few hundred pulsing placeholders cost more than the cards they are waiting for.\n */\nconst MAX_SKELETONS = 12;\n\n/**\n * The toolbar is grey in both themes, so its content is always white. Buttons and inputs bring their own\n * colors (primary blue, the text color of the theme), which are hard to read on grey and are overridden here.\n */\nconst TOOLBAR_SX = {\n backgroundColor: '#777',\n color: '#fff',\n '& .MuiButtonBase-root.Mui-disabled': { color: 'rgba(255, 255, 255, 0.4)' },\n '& .MuiInputBase-root, & .MuiSelect-icon': { color: 'inherit' },\n '& .MuiInputBase-input::placeholder': { opacity: 0.7 },\n '& .MuiInput-underline::before': { borderBottomColor: 'rgba(255, 255, 255, 0.7)' },\n '& .MuiInput-underline:hover:not(.Mui-disabled, .Mui-error)::before': { borderBottomColor: '#fff' },\n '& .MuiInput-underline::after': { borderBottomColor: '#fff' },\n};\n\n/** Marks an active toggle button in the toolbar, as the primary color is not readable there */\nconst TOOLBAR_TOGGLE_ACTIVE_SX = {\n backgroundColor: 'rgba(255, 255, 255, 0.25)',\n '&:hover': { backgroundColor: 'rgba(255, 255, 255, 0.35)' },\n};\n\n/** Returns true if any of the device status objects carries a battery value */\nfunction hasBatteryStatus(status?: DeviceStatus | DeviceStatus[]): boolean {\n if (!status || typeof status === 'string') {\n return false;\n }\n const list = Array.isArray(status) ? status : [status];\n return list.some(entry => typeof entry !== 'string' && entry.battery !== undefined);\n}\n\ninterface DeviceListProps extends CommunicationProps {\n /** Instance to upload images to, like `adapterName.X` */\n uploadImagesToInstance?: string;\n /** Filter devices with this string */\n filter?: string;\n /** If this component is used in GUI with own toolbar. `false` if this list is used with multiple instances and true if only with one (in this case, it will monitor alive itself */\n embedded?: boolean;\n /** If embedded, this text is shown in the toolbar */\n title?: string;\n /** Style of a component that displays all devices */\n style?: React.CSSProperties;\n /** Use small cards for devices */\n smallCards?: boolean;\n /** To trigger the reload of devices, just change this variable */\n triggerLoad?: number;\n}\n\ninterface DeviceListState extends CommunicationState {\n devices: DeviceInfo[];\n totalDevices?: number;\n filter: string;\n filterText: string;\n instanceInfo: InstanceDetails | null;\n loading: boolean | null;\n alive: boolean | null;\n triggerLoad: number;\n groupKey: string;\n dmInstances: { [instanceName: string]: { title: string; icon: string; instance: number } } | null;\n apiVersionError: boolean;\n /** Show only devices that have an available update */\n onlyUpdatable: boolean;\n /** Show only devices that have a battery problem */\n onlyBatteryProblem: boolean;\n /** Device field the text filter applies to */\n filterField: DeviceFilterField;\n /** Distinct resolved model values across the loaded devices (for the model filter dropdown) */\n modelOptions: string[];\n /** Visibility of the configurable indicators, as explicitly chosen by the user for this instance */\n indicatorVisibility: Record<string, boolean>;\n /** Anchor of the indicator visibility menu */\n indicatorsAnchor: HTMLElement | null;\n /** Increased whenever a device field bound to a state or an object changed, to trigger a re-render */\n fieldsVersion: number;\n}\n\n/**\n * Device List Component\n */\nexport default class DeviceList extends Communication<DeviceListProps, DeviceListState> {\n static i18nInitialized = false;\n\n private lastInstance: string;\n\n private lastAliveSubscribe = '';\n\n /**\n * Synchronous mirror of `state.alive`. `setState` is asynchronous, so the guard in `aliveHandler`\n * cannot rely on `state.alive` being committed yet when `subscribeState` replays the current value.\n * This field is always updated synchronously together with `setState({ alive })` and is the source\n * of truth for the \"did alive actually change?\" check, which prevents the double device load.\n */\n private alive: boolean | null = null;\n\n private lastTriggerLoad = 0;\n\n private filterTimeout: ReturnType<typeof setTimeout> | null = null;\n\n private readonly language: ioBroker.Languages = I18n.getLanguage();\n\n /**\n * One handler for the toolbar indicators and for all cards, so that several devices referring to\n * the same object or state share a single subscription on the socket.\n */\n private readonly stateOrObjectHandler: StateOrObjectHandler;\n\n /** Resolves the device fields that may be bound to a state or an object (name, model, ...) */\n private readonly fieldsResolver: DeviceFieldsResolver;\n\n /** One `IntersectionObserver` for all cards: only what is near the viewport is really rendered */\n private readonly lazyObserver = new LazyRenderObserver();\n\n /** The scrolling container of the card list; it is the root of `lazyObserver` */\n private readonly containerRef = React.createRef<HTMLDivElement>();\n\n /** A load is running. A second one must not tear down the same list in parallel */\n private loadingDevices = false;\n\n /** A load was requested while another one was still running */\n private reloadRequested = false;\n\n /** Devices of the running initial load that are not published to the state yet */\n private pendingDevices: DeviceInfo[] | null = null;\n\n private pendingTotal: number | undefined;\n\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n\n /** Memoized result of `getHiddenIndicators`, so that all cards keep getting the same array */\n private hiddenIndicatorsCache: { key: string; value: string[] } | null = null;\n\n constructor(props: DeviceListProps) {\n super(props);\n\n this.stateOrObjectHandler = new StateOrObjectHandler(this.props.socket);\n this.fieldsResolver = new DeviceFieldsResolver(this.stateOrObjectHandler, this.onFieldsChanged);\n\n if (!DeviceList.i18nInitialized) {\n DeviceList.i18nInitialized = true;\n I18n.extendTranslations({\n en,\n de,\n ru,\n pt,\n nl,\n fr,\n it,\n es,\n pl,\n uk,\n 'zh-cn': zhCn,\n });\n }\n\n this.state = {\n ...this.state,\n devices: [],\n filter: '',\n filterText: '',\n instanceInfo: null,\n loading: null,\n alive: null,\n groupKey: '',\n dmInstances: null,\n apiVersionError: false,\n onlyUpdatable: window.localStorage.getItem('dm_onlyUpdatable') === 'true',\n onlyBatteryProblem: window.localStorage.getItem('dm_onlyBatteryProblem') === 'true',\n filterField: (window.localStorage.getItem('dm_filterField') as DeviceFilterField) || 'name',\n modelOptions: [],\n indicatorVisibility: {},\n indicatorsAnchor: null,\n fieldsVersion: 0,\n };\n\n if (this.props.selectedInstance === undefined) {\n // Start with the root page that shows all instances as cards\n this.state = { ...this.state, selectedInstance: this.props.instance ?? '' };\n }\n\n this.state = {\n ...this.state,\n indicatorVisibility: DeviceList.loadIndicatorVisibility(this.state.selectedInstance),\n };\n\n this.lastInstance = this.state.selectedInstance;\n this.lastTriggerLoad = this.props.triggerLoad || 0;\n }\n\n setStateAsync(state: Partial<DeviceListState>): Promise<void> {\n return new Promise<void>(resolve => this.setState(state as DeviceListState, resolve));\n }\n\n private async loadAdapters(): Promise<void> {\n await this.props.socket.waitForFirstConnection();\n\n console.log('Loading adapters...');\n const res = await this.props.socket.getObjectViewSystem('instance', 'system.adapter.', 'system.adapter.\\u9999');\n const dmInstances: { [instanceName: string]: { title: string; icon: string; instance: number } } = {};\n for (const id in res) {\n if (!res[id].common.supportedMessages?.deviceManager) {\n continue;\n }\n\n const instanceName = id.substring('system.adapter.'.length);\n try {\n // Check if the instance is alive by getting the state alive\n const alive = await this.props.socket.getState(`system.adapter.${instanceName}.alive`);\n if (!alive?.val) {\n continue;\n }\n\n const instance = parseInt(instanceName.split('.').pop() || '0') || 0;\n const common = res[id].common;\n const adapterName = instanceName.split('.')[0];\n dmInstances[instanceName] = {\n title: common.titleLang ? this.getText(common.titleLang) : common.title || adapterName,\n icon: common.icon ? `./adapter/${adapterName}/${common.icon}` : common.extIcon || '',\n instance,\n };\n } catch (error) {\n console.error(error);\n }\n }\n\n if (Object.keys(dmInstances).length === 1) {\n // With only one instance, select it directly and do not show the root page\n const selectedInstance = Object.keys(dmInstances)[0];\n await this.setStateAsync({\n dmInstances,\n selectedInstance,\n groupKey: window.localStorage.getItem(`dm_group_${selectedInstance}`) || '',\n });\n } else {\n await this.setStateAsync({ dmInstances });\n }\n }\n\n private selectInstance(instanceId: string): void {\n window.localStorage.setItem('dmSelectedInstance', instanceId);\n this.props.onInstanceChanged?.(instanceId);\n this.setState({\n selectedInstance: instanceId,\n groupKey: window.localStorage.getItem(`dm_group_${instanceId}`) || '',\n });\n }\n\n private backToInstancesList(): void {\n window.localStorage.removeItem('dmSelectedInstance');\n this.props.onInstanceChanged?.('');\n this.alive = null;\n this.applyDevices([], {\n selectedInstance: '',\n totalDevices: undefined,\n instanceInfo: null,\n alive: null,\n groupKey: '',\n filter: '',\n filterText: '',\n apiVersionError: false,\n });\n }\n\n private refreshInstanceList(): void {\n this.setState({ dmInstances: null }, () => this.loadAdapters().catch(console.error));\n }\n\n async componentDidMount(): Promise<void> {\n this.lazyObserver.setRoot(this.containerRef.current);\n\n let alive = false;\n // If an instance selector must be shown\n if (this.props.selectedInstance === undefined) {\n // show instance selector\n await this.loadAdapters();\n }\n\n if (this.alive === null && this.state.selectedInstance) {\n try {\n // check if the instance is alive\n const stateAlive = await this.props.socket.getState(\n `system.adapter.${this.state.selectedInstance}.alive`,\n );\n if (stateAlive?.val) {\n alive = true;\n }\n } catch (error) {\n console.error(error);\n }\n // Update the synchronous mirror BEFORE subscribing. `subscribeState` replays the current\n // value to `aliveHandler`; with `this.alive` already set, that replay is recognized as\n // \"no change\" and does not trigger a second `loadAllData()` in addition to the one below.\n this.alive = alive;\n this.lastAliveSubscribe = this.state.selectedInstance;\n this.setState({ alive });\n await this.props.socket.subscribeState(\n `system.adapter.${this.state.selectedInstance}.alive`,\n this.aliveHandler,\n );\n } else if (this.alive !== null) {\n alive = this.alive;\n }\n\n if (alive) {\n try {\n await this.loadAllData();\n } catch (error) {\n console.error(error);\n }\n }\n }\n\n componentWillUnmount(): void {\n super.componentWillUnmount();\n this.cancelDeviceFlush();\n this.fieldsResolver.destroy();\n this.stateOrObjectHandler.destroy();\n this.lazyObserver.destroy();\n if (this.filterTimeout) {\n clearTimeout(this.filterTimeout);\n this.filterTimeout = null;\n }\n if (this.state.selectedInstance) {\n this.props.socket.unsubscribeState(\n `system.adapter.${this.state.selectedInstance}.alive`,\n this.aliveHandler,\n );\n }\n }\n\n /**\n * The side effects that used to be triggered from `render()`. A render must not have any, and\n * the `setTimeout` there was executed on every single render.\n */\n componentDidUpdate(): void {\n // The scrolling container only exists after the first render\n this.lazyObserver.setRoot(this.containerRef.current);\n\n if ((this.props.triggerLoad || 0) !== this.lastTriggerLoad) {\n this.lastTriggerLoad = this.props.triggerLoad || 0;\n this.loadDeviceList();\n }\n\n // if instance changed\n if (this.lastInstance !== this.state.selectedInstance) {\n this.lastInstance = this.state.selectedInstance;\n // The indicator visibility is stored per instance\n this.setState({\n indicatorVisibility: DeviceList.loadIndicatorVisibility(this.state.selectedInstance),\n indicatorsAnchor: null,\n });\n if (this.state.selectedInstance) {\n this.loadAllData().catch(error => console.error(error));\n } else {\n this.loadDeviceList();\n }\n }\n\n if (this.props.selectedInstance && this.props.selectedInstance !== this.state.selectedInstance) {\n this.setState({ selectedInstance: this.props.selectedInstance });\n }\n }\n\n /**\n * A value bound to a state or an object arrived. The cards are `PureComponent`s and receive the\n * values through their `fields` property, so the list only has to trigger a re-render.\n */\n private onFieldsChanged = (): void => {\n const modelOptions = this.fieldsResolver.getModels();\n const modelsChanged =\n modelOptions.length !== this.state.modelOptions.length ||\n modelOptions.some((model, i) => model !== this.state.modelOptions[i]);\n\n this.setState({\n fieldsVersion: this.state.fieldsVersion + 1,\n modelOptions: modelsChanged ? modelOptions : this.state.modelOptions,\n });\n };\n\n /**\n * Publish a new device list.\n *\n * The resolver is updated *before* the state, because it resolves literal values synchronously -\n * the cards and the filter therefore already have their values on the very first render.\n */\n private applyDevices(devices: DeviceInfo[], state: Partial<DeviceListState>): void {\n this.fieldsResolver.setDevices(devices.map(device => ({ key: deviceKey(device), device })));\n this.setState({ ...state, devices } as DeviceListState);\n }\n\n /**\n * Publish the devices loaded so far, but at most every 100 ms: a fast backend delivers a dozen\n * batches in a row, and every single one of them would otherwise re-render the complete list.\n */\n private scheduleDeviceFlush(devices: DeviceInfo[], total?: number): void {\n this.pendingDevices = devices;\n this.pendingTotal = total;\n if (this.flushTimer) {\n return;\n }\n this.flushTimer = setTimeout(() => {\n this.flushTimer = null;\n const pending = this.pendingDevices;\n if (pending) {\n this.pendingDevices = null;\n this.applyDevices(pending, { loading: true, totalDevices: this.pendingTotal });\n }\n }, 100);\n }\n\n private cancelDeviceFlush(): void {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n this.pendingDevices = null;\n }\n\n aliveHandler: ioBroker.StateChangeHandler = (id: string, state: ioBroker.State | null | undefined): void => {\n if (this.state.selectedInstance && id === `system.adapter.${this.state.selectedInstance}.alive`) {\n const alive = !!state?.val;\n // Compare against the synchronous mirror, not `state.alive` (which may not be committed yet\n // when `subscribeState` replays the initial value). This is what stops the double load.\n if (alive !== this.alive) {\n this.alive = alive;\n this.setState({ alive }, () => {\n if (alive) {\n // The instance just became alive: (re)load all data directly instead of\n // re-running the whole mount logic.\n this.loadAllData().catch(console.error);\n }\n });\n }\n }\n };\n\n override async loadAllData(): Promise<void> {\n await this.loadInstanceInfos();\n this.loadDeviceList();\n }\n\n override async loadInstanceInfos(): Promise<InstanceDetails> {\n const instanceInfo = await super.loadInstanceInfos();\n return new Promise<InstanceDetails>(resolve =>\n this.setState(\n { instanceInfo, apiVersionError: !['v1', 'v2', 'v3'].includes(instanceInfo.apiVersion) },\n () => resolve(instanceInfo),\n ),\n );\n }\n\n /**\n * Load devices.\n *\n * The list is deliberately *not* emptied first: as long as the keys stay the same React keeps the\n * existing cards, so a reload - the matter adapter triggers one on every `updateController`\n * message - no longer unmounts and remounts a few hundred cards with all their subscriptions.\n */\n override loadDeviceList(): void {\n if (this.loadingDevices) {\n // Remember the request and repeat the load once the running one has finished, instead of\n // running two loads over the same list at the same time.\n this.reloadRequested = true;\n return;\n }\n this.loadingDevices = true;\n\n this.setState({ loading: true }, async () => {\n console.log(`Loading devices for ${this.state.selectedInstance}...`);\n let alive = this.alive;\n\n if (this.state.selectedInstance !== this.lastAliveSubscribe) {\n if (this.lastAliveSubscribe) {\n // unsubscribe from the old instance\n this.props.socket.unsubscribeState(\n `system.adapter.${this.lastAliveSubscribe}.alive`,\n this.aliveHandler,\n );\n }\n\n this.lastAliveSubscribe = this.state.selectedInstance;\n\n if (this.state.selectedInstance) {\n try {\n // check if the instance is alive\n const stateAlive = await this.props.socket.getState(\n `system.adapter.${this.state.selectedInstance}.alive`,\n );\n alive = !!stateAlive?.val;\n } catch (error) {\n console.error(error);\n alive = false;\n }\n // Set the synchronous mirror before subscribing so the replayed initial value\n // does not trigger an extra load on top of the one performed right below.\n this.alive = alive;\n await this.props.socket.subscribeState(\n `system.adapter.${this.state.selectedInstance}.alive`,\n this.aliveHandler,\n );\n } else {\n alive = false;\n }\n }\n\n // Only the very first load shows the devices step by step (with skeletons for the ones\n // that are still missing). A reload keeps the current list until the new one is complete,\n // so the already rendered cards survive.\n const incremental = !this.state.devices.length;\n let devices: DeviceInfo[] = [];\n try {\n this.alive = alive;\n this.setState({ loading: !!alive, alive });\n if (alive) {\n await this.loadDevices((batch, total) => {\n devices = devices.concat(batch);\n if (incremental) {\n this.scheduleDeviceFlush(devices, total);\n }\n console.log(`Loaded ${devices.length} of ${total} devices...`);\n });\n }\n } catch (error) {\n console.error(error);\n devices = [];\n }\n\n this.cancelDeviceFlush();\n this.applyDevices(devices, { loading: false, totalDevices: devices.length });\n console.log(`Loaded ${devices.length} devices for ${this.state.selectedInstance}`);\n\n this.loadingDevices = false;\n if (this.reloadRequested) {\n this.reloadRequested = false;\n setTimeout(() => this.loadDeviceList(), 0);\n }\n });\n }\n\n override updateDevice(update: DeviceInfo): void {\n const updateId = JSON.stringify(update.id);\n this.applyDevices(\n this.state.devices.map(d => (deviceKey(d) === updateId ? update : d)),\n {},\n );\n }\n\n override deleteDevice(deviceId: DeviceId): void {\n const deleteId = JSON.stringify(deviceId);\n const devices = this.state.devices.filter(d => deviceKey(d) !== deleteId);\n const totalDevices =\n this.state.totalDevices && devices.length < this.state.devices.length\n ? this.state.totalDevices - 1\n : undefined;\n this.applyDevices(devices, { totalDevices });\n }\n\n getText(text: ioBroker.StringOrTranslated): string {\n if (typeof text === 'object') {\n return text[this.language] || text.en;\n }\n\n return text;\n }\n\n handleFilterChange(filter: string): void {\n this.setState({ filterText: filter });\n if (this.filterTimeout) {\n clearTimeout(this.filterTimeout);\n }\n this.filterTimeout = setTimeout(() => {\n this.filterTimeout = null;\n this.setState({ filter });\n }, 250);\n }\n\n renderGroups(\n groups: { name: string; value: string; count: number; icon?: React.JSX.Element | string | null }[] | undefined,\n ): React.JSX.Element | null {\n if (!groups?.length) {\n return null;\n }\n\n return (\n <Select\n style={{ minWidth: 120, marginRight: 8, flexShrink: 0 }}\n variant=\"standard\"\n value={this.state.groupKey || '_'}\n renderValue={value => {\n if (value === '_') {\n value = '';\n }\n const g = groups.find(g => g.value === value);\n return (\n <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n {g?.icon || <div style={{ width: 24 }} />}\n {g?.name || value}\n </div>\n );\n }}\n onChange={e => {\n if (e.target.value) {\n window.localStorage.setItem(`dm_group_${this.state.selectedInstance}`, e.target.value);\n } else {\n window.localStorage.removeItem(`dm_group_${this.state.selectedInstance}`);\n }\n this.setState({ groupKey: e.target.value === '_' ? '' : e.target.value });\n }}\n >\n {groups.map(g => (\n <MenuItem\n value={g.value || '_'}\n key={g.value || '_'}\n style={{ display: 'flex', alignItems: 'center', gap: 8 }}\n >\n {g.icon || <div style={{ width: 24 }} />}\n {g.name}\n </MenuItem>\n ))}\n </Select>\n );\n }\n\n renderInstanceCards(): React.JSX.Element[] {\n if (!this.state.dmInstances) {\n return [\n <LinearProgress\n key=\"loadingInstances\"\n style={{ width: '100%' }}\n />,\n ];\n }\n\n const instanceIds = Object.keys(this.state.dmInstances);\n if (!instanceIds.length) {\n return [\n <div\n style={{ padding: 25 }}\n key=\"noInstances\"\n >\n <span>{getTranslation('noInstancesFoundText')}</span>\n </div>,\n ];\n }\n\n const backgroundColor = this.props.theme.palette.mode === 'dark' ? '#0b0b0b' : '#d5d5d5';\n\n if (this.props.smallCards) {\n return instanceIds.map(id => {\n const info = this.state.dmInstances![id];\n return (\n <Card\n key={id}\n sx={{ width: 200, margin: '5px', backgroundColor }}\n >\n <CardActionArea\n onClick={() => this.selectInstance(id)}\n style={{ height: '100%' }}\n >\n <CardContent\n style={{\n height: '100%',\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n padding: 8,\n }}\n >\n {info.icon ? (\n <Icon\n src={info.icon}\n style={{ width: 32, height: 32, flexShrink: 0 }}\n />\n ) : (\n <QuestionMark style={{ width: 32, height: 32, flexShrink: 0 }} />\n )}\n <div style={{ overflow: 'hidden' }}>\n <Typography\n variant=\"body1\"\n noWrap\n style={{ fontSize: 14, fontWeight: 'bold' }}\n >\n {id}\n </Typography>\n {info.title ? (\n <Typography\n variant=\"caption\"\n color=\"textSecondary\"\n noWrap\n component=\"div\"\n >\n {info.title}\n </Typography>\n ) : null}\n </div>\n </CardContent>\n </CardActionArea>\n </Card>\n );\n });\n }\n\n return instanceIds.map(id => {\n const info = this.state.dmInstances![id];\n return (\n <Card\n key={id}\n sx={{ width: 240, margin: '10px', backgroundColor }}\n >\n <CardActionArea\n onClick={() => this.selectInstance(id)}\n style={{ height: '100%' }}\n >\n <CardContent\n style={{\n height: '100%',\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n gap: 8,\n }}\n >\n {info.icon ? (\n <Icon\n src={info.icon}\n style={{ width: 64, height: 64 }}\n />\n ) : (\n <QuestionMark style={{ width: 64, height: 64 }} />\n )}\n <Typography\n variant=\"h6\"\n style={{ textAlign: 'center', wordBreak: 'break-all' }}\n >\n {id}\n </Typography>\n {info.title ? (\n <Typography\n variant=\"body2\"\n color=\"textSecondary\"\n style={{ textAlign: 'center' }}\n >\n {info.title}\n </Typography>\n ) : null}\n </CardContent>\n </CardActionArea>\n </Card>\n );\n });\n }\n\n /**\n * Apply the text filter and the \"only updatable\" / \"only battery problem\" filters.\n *\n * This used to be done by every card for itself. A filtered out card stayed mounted with all its\n * subscriptions and only rendered nothing, so filtering did not reduce the load at all - and a\n * card that is not rendered cannot filter itself in the first place.\n */\n private filterDevices(devices: DeviceInfo[]): DeviceInfo[] {\n const filter = (this.props.embedded ? this.props.filter : this.state.filter)?.toLowerCase();\n const field: DeviceFilterField = this.props.embedded ? 'name' : this.getEffectiveFilterField();\n const onlyUpdatable = !this.props.embedded && this.state.onlyUpdatable;\n const onlyBatteryProblem = !this.props.embedded && this.state.onlyBatteryProblem;\n\n if (!filter && !onlyUpdatable && !onlyBatteryProblem) {\n return devices;\n }\n\n return devices.filter(device => {\n const fields = this.fieldsResolver.getValues(deviceKey(device));\n if (\n filter &&\n !String(fields[field] ?? '')\n .toLowerCase()\n .includes(filter)\n ) {\n return false;\n }\n if (onlyUpdatable && !fields.updateAvailable) {\n return false;\n }\n if (onlyBatteryProblem && !fields.batteryProblem) {\n return false;\n }\n return true;\n });\n }\n\n /** The selected filter field, falling back to `name` if the stored field is not available (e.g. no models found) */\n private getEffectiveFilterField(): DeviceFilterField {\n const field = this.state.filterField;\n if (field === 'name') {\n return 'name';\n }\n // The model field is only available if at least one model value was actually found\n if (field === 'model') {\n return this.state.modelOptions.length ? 'model' : 'name';\n }\n return this.state.devices.some(device => device[field] !== undefined) ? field : 'name';\n }\n\n renderFilterFields(): React.JSX.Element | null {\n const fields: { value: DeviceFilterField; label: string }[] = [\n { value: 'name', label: getTranslation('name') },\n ];\n if (this.state.devices.some(device => device.identifier !== undefined)) {\n fields.push({\n value: 'identifier',\n label: this.getText(this.state.instanceInfo?.identifierLabel ?? 'ID'),\n });\n }\n if (this.state.devices.some(device => device.manufacturer !== undefined)) {\n fields.push({ value: 'manufacturer', label: getTranslation('manufacturer') });\n }\n // Only offer the model filter if at least one model value was actually found\n if (this.state.modelOptions.length) {\n fields.push({ value: 'model', label: getTranslation('model') });\n }\n\n // Only show the field selector when there is more than just the name to choose from\n if (fields.length < 2) {\n return null;\n }\n\n const current = this.getEffectiveFilterField();\n\n return (\n <Select\n variant=\"standard\"\n style={{ width: 130, flexShrink: 0 }}\n value={current}\n onChange={e => {\n const filterField = e.target.value;\n this.setState({ filterField });\n window.localStorage.setItem('dm_filterField', filterField);\n // reset the current filter value when switching the field\n this.handleFilterChange('');\n }}\n >\n {fields.map(field => (\n <MenuItem\n value={field.value}\n key={field.value}\n >\n {field.label}\n </MenuItem>\n ))}\n </Select>\n );\n }\n\n /** The filter value input: a model dropdown for the `model` field, a free-text field otherwise */\n renderFilterValue(): React.JSX.Element {\n if (this.getEffectiveFilterField() === 'model') {\n const value = this.state.modelOptions.includes(this.state.filterText) ? this.state.filterText : '';\n return (\n <Select\n variant=\"standard\"\n style={{ width: 200 }}\n displayEmpty\n value={value}\n onChange={e => this.handleFilterChange(e.target.value)}\n >\n <MenuItem value=\"\">\n <em>{getTranslation('allModels')}</em>\n </MenuItem>\n {this.state.modelOptions.map(model => (\n <MenuItem\n value={model}\n key={model}\n >\n {model}\n </MenuItem>\n ))}\n </Select>\n );\n }\n\n return (\n <TextField\n variant=\"standard\"\n style={{ width: 200 }}\n size=\"small\"\n placeholder={getTranslation('filterLabelText')}\n onChange={e => this.handleFilterChange(e.target.value)}\n value={this.state.filterText}\n autoComplete=\"off\"\n slotProps={{\n input: {\n autoComplete: 'new-password',\n endAdornment: this.state.filterText ? (\n <InputAdornment position=\"end\">\n <IconButton\n tabIndex={-1}\n onClick={() => this.handleFilterChange('')}\n color=\"inherit\"\n edge=\"end\"\n >\n <Clear />\n </IconButton>\n </InputAdornment>\n ) : null,\n },\n htmlInput: {\n autoComplete: 'off',\n },\n }}\n />\n );\n }\n\n renderRootInfo(): React.JSX.Element {\n // The root ThemeProvider (Communication.render) already supplies the correct theme context. The explicit color\n // is a safety net, so older InfoBox versions (whose Typography has no own color) stay readable in dark mode.\n return (\n <InfoBox\n key=\"rootInfo\"\n type=\"info\"\n closeable\n storeId=\"dm_rootInfoClosed\"\n style={{\n width: 'calc(100% - 20px)',\n margin: '0 10px 8px 10px',\n color: this.props.theme.palette.text.primary,\n }}\n >\n {I18n.t('rootInfoText')}\n </InfoBox>\n );\n }\n\n /** Key of the stored indicator visibility of one instance */\n private static indicatorStorageKey(instanceId: string): string {\n return `dm_indicators_${instanceId}`;\n }\n\n /** Read the visibility the user has explicitly chosen for the configurable indicators of an instance */\n private static loadIndicatorVisibility(instanceId: string): Record<string, boolean> {\n if (!instanceId) {\n return {};\n }\n try {\n const stored = window.localStorage.getItem(DeviceList.indicatorStorageKey(instanceId));\n return stored ? (JSON.parse(stored) as Record<string, boolean>) : {};\n } catch (error) {\n console.error(error);\n return {};\n }\n }\n\n /**\n * All configurable indicators of the instance and of the loaded devices, unique by ID.\n * Indicators with the same ID on different devices are configured together.\n */\n private getConfigurableIndicators(): StatusIndicator[] {\n const result: StatusIndicator[] = [];\n const seen = new Set<string>();\n\n const collect = (indicators?: StatusIndicator[]): void => {\n for (const indicator of indicators || []) {\n if (indicator.configurable && !seen.has(indicator.id)) {\n seen.add(indicator.id);\n result.push(indicator);\n }\n }\n };\n\n collect(this.state.instanceInfo?.indicators);\n for (const device of this.state.devices) {\n collect(device.indicators);\n }\n\n return result;\n }\n\n /** True if the given configurable indicator is currently shown */\n private isIndicatorVisible(indicator: StatusIndicator): boolean {\n if (!indicator.configurable) {\n return true;\n }\n return this.state.indicatorVisibility[indicator.id] ?? indicator.defaultVisible !== false;\n }\n\n /** IDs of the configurable indicators the user has switched off */\n private getHiddenIndicators(): string[] {\n const hidden = this.getConfigurableIndicators()\n .filter(indicator => !this.isIndicatorVisible(indicator))\n .map(indicator => indicator.id);\n\n // The array is handed to every card. A new array on every render would defeat the shallow\n // property comparison of `DeviceCard`.\n const key = hidden.join(',');\n if (!this.hiddenIndicatorsCache || this.hiddenIndicatorsCache.key !== key) {\n this.hiddenIndicatorsCache = { key, value: hidden };\n }\n return this.hiddenIndicatorsCache.value;\n }\n\n private toggleIndicator(indicator: StatusIndicator): void {\n const indicatorVisibility = {\n ...this.state.indicatorVisibility,\n [indicator.id]: !this.isIndicatorVisible(indicator),\n };\n this.setState({ indicatorVisibility });\n window.localStorage.setItem(\n DeviceList.indicatorStorageKey(this.state.selectedInstance),\n JSON.stringify(indicatorVisibility),\n );\n }\n\n /** The toolbar button that lets the user show or hide the configurable indicators */\n renderIndicatorSettings(): JSX.Element | null {\n const configurable = this.getConfigurableIndicators();\n if (!configurable.length) {\n return null;\n }\n\n return (\n <>\n <Tooltip\n title={getTranslation('indicatorsTooltip')}\n slotProps={{ popper: { sx: { pointerEvents: 'none' } } }}\n >\n <IconButton\n size=\"small\"\n color=\"inherit\"\n onClick={e => this.setState({ indicatorsAnchor: e.currentTarget })}\n >\n <Tune />\n </IconButton>\n </Tooltip>\n <Menu\n open={!!this.state.indicatorsAnchor}\n anchorEl={this.state.indicatorsAnchor}\n onClose={() => this.setState({ indicatorsAnchor: null })}\n >\n <ListSubheader style={{ lineHeight: '32px' }}>{getTranslation('indicatorsTitle')}</ListSubheader>\n {configurable.map(indicator => (\n <MenuItem\n key={indicator.id}\n onClick={() => this.toggleIndicator(indicator)}\n >\n <Checkbox\n edge=\"start\"\n size=\"small\"\n checked={this.isIndicatorVisible(indicator)}\n />\n {/* Only a literal icon can be shown here, a state-bound one has no value without a device */}\n {typeof indicator.icon === 'string' ? (\n <span style={{ display: 'inline-flex', marginRight: 8 }}>\n {renderIcon(indicator.icon, undefined, true)}\n </span>\n ) : null}\n {this.getText(indicator.label || indicator.tooltip || indicator.id)}\n </MenuItem>\n ))}\n </Menu>\n </>\n );\n }\n\n /** Resolve how an instance indicator behaves on click by looking up the referenced instance action */\n private resolveInstanceIndicatorAction = (\n actionId: string,\n ): { onClick?: () => void; url?: string; disabled?: boolean } | undefined => {\n const action = this.state.instanceInfo?.actions?.find(a => a.id === actionId);\n if (!action) {\n console.warn(\n `Indicator of instance ${this.state.selectedInstance} references unknown action \"${actionId}\"`,\n );\n return undefined;\n }\n\n if ('url' in action && action.url) {\n return { url: getTranslation(action.url), disabled: action.disabled };\n }\n\n return { onClick: this.instanceHandler(action), disabled: action.disabled };\n };\n\n /** Instance actions in the toolbar. An action referenced by an indicator is not rendered twice */\n renderInstanceActions(): JSX.Element | null {\n const referenced = new Set(\n (this.state.instanceInfo?.indicators || [])\n .map(indicator => indicator.actionId)\n .filter((actionId): actionId is string => !!actionId),\n );\n const actions = this.state.instanceInfo?.actions?.filter(action => !referenced.has(action.id));\n\n if (!actions?.length) {\n return null;\n }\n\n return (\n <div style={{ marginLeft: 20 }}>\n {actions.map(action => (\n <InstanceActionButton\n key={action.id}\n action={action}\n instanceHandler={this.instanceHandler}\n />\n ))}\n </div>\n );\n }\n\n renderContent(): JSX.Element | JSX.Element[] | null {\n const emptyStyle: React.CSSProperties = {\n padding: 25,\n };\n\n const deviceGroups: { name: string; value: string; count: number; icon?: React.JSX.Element | string | null }[] =\n [];\n const showRootPage =\n !this.props.embedded && this.props.selectedInstance === undefined && !this.state.selectedInstance;\n\n let list: React.JSX.Element[] | undefined;\n if (showRootPage) {\n list = this.renderInstanceCards();\n list.unshift(this.renderRootInfo());\n } else if (!this.props.embedded && !this.state.alive) {\n list = [\n <div\n style={emptyStyle}\n key=\"notAlive\"\n >\n <span>{getTranslation('instanceNotAlive')}</span>\n </div>,\n ];\n } else if (!this.state.devices.length && this.state.selectedInstance && !this.state.loading) {\n list = [\n <div\n style={emptyStyle}\n key=\"notFound\"\n >\n <span>{getTranslation('noDevicesFoundText')}</span>\n </div>,\n ];\n } else {\n // build a device types list\n let filteredDevices = this.state.devices;\n if (!this.state.loading && !this.props.embedded && filteredDevices.find(device => device.group)) {\n deviceGroups.push({\n name: I18n.t('All'),\n value: '',\n count: filteredDevices.length,\n icon: <FilterAltOff />,\n });\n filteredDevices.forEach(device => {\n if (device.group) {\n const type = deviceGroups.find(t => t.value === device.group?.key);\n if (type) {\n type.count++;\n } else {\n const icon = device.group.icon ? <DeviceTypeIcon src={device.group.icon} /> : null;\n\n deviceGroups.push({\n name: this.getText(device.group.name || device.group.key),\n value: device.group.key,\n count: 1,\n icon,\n });\n }\n }\n });\n const unknown = filteredDevices.filter(device => !device.group);\n if (unknown.length) {\n deviceGroups.push({\n name: I18n.t('Unknown'),\n value: '?',\n count: unknown.length,\n icon: <QuestionMark />,\n });\n }\n\n if (this.state.groupKey && this.state.groupKey !== '_') {\n // filter out all devices belonging to this group\n if (this.state.groupKey === '?') {\n filteredDevices = filteredDevices.filter(device => !device.group?.key);\n } else {\n filteredDevices = filteredDevices.filter(device => device.group?.key === this.state.groupKey);\n }\n }\n }\n\n if (this.state.selectedInstance) {\n const selectedInstance = this.state.selectedInstance;\n const hiddenIndicators = this.getHiddenIndicators();\n const smallCards = this.props.smallCards ?? this.state.instanceInfo?.smallCards;\n const identifierLabel = this.state.instanceInfo?.identifierLabel ?? 'ID';\n const cardWidth = smallCards ? SMALL_CARD_WIDTH : CARD_WIDTH;\n const cardMinHeight = smallCards ? SMALL_CARD_MIN_HEIGHT : CARD_MIN_HEIGHT;\n const cardMargin = smallCards ? SMALL_CARD_MARGIN : CARD_MARGIN;\n const visibleDevices = this.filterDevices(filteredDevices);\n\n // Every card is wrapped in a `LazyRender`: the placeholder always occupies the full\n // footprint of a card, but the card itself is only built while it is near the visible\n // area. Without that, 80 devices mean thousands of DOM nodes and several hundred MUI\n // tooltips and buttons at once - which is what makes Safari (and especially iPadOS)\n // hang and finally kill the tab.\n list = visibleDevices.map(device => {\n const key = deviceKey(device);\n return (\n <LazyRender\n key={key}\n observer={this.lazyObserver}\n width={cardWidth}\n minHeight={cardMinHeight}\n margin={cardMargin}\n >\n {() => (\n <DeviceCard\n fillContainer\n smallCards={smallCards}\n alive={!!this.state.alive}\n id={device.id}\n identifierLabel={identifierLabel}\n device={device}\n fields={this.fieldsResolver.getValues(key)}\n stateOrObjectHandler={this.stateOrObjectHandler}\n instanceId={selectedInstance}\n uploadImagesToInstance={this.props.uploadImagesToInstance}\n deviceHandler={this.deviceHandler}\n controlHandler={this.controlHandler}\n controlStateHandler={this.controlStateHandler}\n socket={this.props.socket}\n themeName={this.props.themeName}\n themeType={this.props.themeType}\n theme={this.props.theme}\n isFloatComma={this.props.isFloatComma}\n dateFormat={this.props.dateFormat}\n hiddenIndicators={hiddenIndicators}\n />\n )}\n </LazyRender>\n );\n });\n\n if (this.state.loading) {\n // How many devices are still missing - deliberately not derived from `list`,\n // which only contains the devices that pass the filter\n const loaded = this.state.devices.length;\n const missing = (this.state.totalDevices ?? loaded + 1) - loaded;\n const skeletons = Math.min(missing, MAX_SKELETONS);\n for (let i = 0; i < skeletons; i++) {\n list.push(\n <DeviceCardSkeleton\n key={`skeleton-${i}`}\n smallCards={smallCards}\n theme={this.props.theme}\n />,\n );\n }\n } else if (!visibleDevices.length && this.state.devices.length > 0) {\n // The filter is applied here now, so the list knows that nothing is left instead\n // of having to hide the message with a CSS rule\n list.push(\n <div\n style={emptyStyle}\n key=\"filtered\"\n >\n <span>{getTranslation('allDevicesFilteredOut')}</span>\n </div>,\n );\n }\n } else {\n list = [\n <div\n style={emptyStyle}\n key=\"selectInstance\"\n >\n <span>{getTranslation('selectInstanceText')}</span>\n </div>,\n ];\n }\n }\n\n if (this.props.embedded) {\n return (\n <>\n {this.state.loading ? <LinearProgress style={{ width: '100%' }} /> : null}\n {this.state.apiVersionError ? <div>{I18n.t('apiVersionError')}</div> : list}\n </>\n );\n }\n\n return (\n <div\n style={{ width: '100%', height: '100%', overflow: 'hidden', display: 'flex', flexDirection: 'column' }}\n >\n <Toolbar\n variant=\"dense\"\n sx={TOOLBAR_SX}\n style={{\n display: 'flex',\n flexWrap: 'wrap',\n rowGap: 4,\n alignItems: 'center',\n flexShrink: 0,\n }}\n >\n {this.props.title}\n {this.props.selectedInstance === undefined &&\n this.state.dmInstances &&\n this.state.selectedInstance ? (\n <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n {Object.keys(this.state.dmInstances).length > 1 ? (\n <Tooltip\n title={getTranslation('backToInstancesList')}\n slotProps={{ popper: { sx: { pointerEvents: 'none' } } }}\n >\n <IconButton\n onClick={() => this.backToInstancesList()}\n color=\"inherit\"\n size=\"small\"\n >\n <ArrowBack />\n </IconButton>\n </Tooltip>\n ) : null}\n {this.state.dmInstances[this.state.selectedInstance]?.icon ? (\n <Icon\n src={this.state.dmInstances[this.state.selectedInstance].icon}\n style={{ width: 24, height: 24 }}\n />\n ) : null}\n <span style={{ marginRight: 8 }}>{this.state.selectedInstance}</span>\n </div>\n ) : null}\n {this.props.selectedInstance === undefined && !this.state.selectedInstance ? (\n <Tooltip\n title={getTranslation('refreshInstanceList')}\n slotProps={{ popper: { sx: { pointerEvents: 'none' } } }}\n >\n <span>\n <IconButton\n onClick={() => this.refreshInstanceList()}\n disabled={!this.state.dmInstances}\n color=\"inherit\"\n size=\"small\"\n >\n <Refresh />\n </IconButton>\n </span>\n </Tooltip>\n ) : null}\n {this.state.selectedInstance ? (\n <Tooltip\n title={getTranslation('refreshTooltip')}\n slotProps={{ popper: { sx: { pointerEvents: 'none' } } }}\n >\n <span>\n <IconButton\n onClick={() => this.loadAllData()}\n disabled={!this.state.alive || this.state.apiVersionError}\n color=\"inherit\"\n size=\"small\"\n >\n <Refresh />\n </IconButton>\n </span>\n </Tooltip>\n ) : null}\n {!this.state.apiVersionError && this.state.alive && this.renderInstanceActions()}\n {!this.state.apiVersionError && this.state.alive && this.state.instanceInfo?.indicators?.length ? (\n <StatusIndicators\n indicators={this.state.instanceInfo.indicators.filter(indicator =>\n this.isIndicatorVisible(indicator),\n )}\n theme={this.props.theme}\n stateOrObjectHandler={this.stateOrObjectHandler}\n resolveAction={this.resolveInstanceIndicatorAction}\n defaultColor=\"#fff\"\n style={{ marginLeft: 20 }}\n />\n ) : null}\n\n <div style={{ flexGrow: 1 }} />\n\n {!this.state.apiVersionError && this.renderGroups(deviceGroups)}\n {!this.state.apiVersionError &&\n this.state.alive &&\n this.state.devices.some(device => device.update) ? (\n <Tooltip\n title={getTranslation('onlyUpdatableTooltip')}\n slotProps={{ popper: { sx: { pointerEvents: 'none' } } }}\n >\n <IconButton\n color=\"inherit\"\n sx={this.state.onlyUpdatable ? TOOLBAR_TOGGLE_ACTIVE_SX : undefined}\n onClick={() => {\n const onlyUpdatable = !this.state.onlyUpdatable;\n this.setState({ onlyUpdatable });\n window.localStorage.setItem('dm_onlyUpdatable', onlyUpdatable ? 'true' : 'false');\n }}\n size=\"small\"\n >\n <SystemUpdateAlt />\n </IconButton>\n </Tooltip>\n ) : null}\n {!this.state.apiVersionError &&\n this.state.alive &&\n this.state.devices.some(device => hasBatteryStatus(device.status)) ? (\n <Tooltip\n title={getTranslation('onlyBatteryProblemTooltip')}\n slotProps={{ popper: { sx: { pointerEvents: 'none' } } }}\n >\n <IconButton\n color=\"inherit\"\n sx={this.state.onlyBatteryProblem ? TOOLBAR_TOGGLE_ACTIVE_SX : undefined}\n onClick={() => {\n const onlyBatteryProblem = !this.state.onlyBatteryProblem;\n this.setState({ onlyBatteryProblem });\n window.localStorage.setItem(\n 'dm_onlyBatteryProblem',\n onlyBatteryProblem ? 'true' : 'false',\n );\n }}\n size=\"small\"\n >\n <BatteryAlert />\n </IconButton>\n </Tooltip>\n ) : null}\n {!this.state.apiVersionError && this.state.alive ? this.renderIndicatorSettings() : null}\n {!this.state.apiVersionError && this.state.alive ? (\n <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>\n <FilterAlt />\n {this.renderFilterFields()}\n {this.renderFilterValue()}\n </div>\n ) : null}\n <Typography\n sx={{ display: { xs: 'none', md: 'block' } }}\n style={{\n marginLeft: 16,\n fontWeight: 'bold',\n whiteSpace: 'nowrap',\n }}\n >\n {I18n.t('configManager')}\n </Typography>\n </Toolbar>\n <div\n ref={this.containerRef}\n style={{\n width: '100%',\n flex: 1,\n minHeight: 0,\n marginTop: 8,\n overflow: 'auto',\n display: 'flex',\n flexWrap: 'wrap',\n alignItems: 'stretch',\n alignContent: 'flex-start',\n ...this.props.style,\n }}\n >\n {this.state.loading ? <LinearProgress style={{ width: '100%' }} /> : null}\n {this.state.apiVersionError ? <div>{I18n.t('apiVersionError')}</div> : list}\n </div>\n </div>\n );\n }\n}\n"]}
@@ -8,6 +8,8 @@ export default function InstanceActionButton(params) {
8
8
  // If the action is rendered as a text button and no icon was explicitly requested,
9
9
  // do not fall back to the "question mark" icon
10
10
  const icon = renderActionIcon(action, !!title && !action.icon);
11
- return (React.createElement(TooltipButton, { style: action.style, variant: action.variant, tooltip: tooltip, label: title, disabled: action.disabled, Icon: icon, onClick: instanceHandler(action), url: 'url' in action ? getTranslation(action.url) : undefined }));
11
+ return (React.createElement(TooltipButton, { style: action.style, variant: action.variant,
12
+ // The toolbar is grey, so the primary color is not readable there. A contained button has its own background
13
+ color: action.variant === 'contained' ? undefined : 'inherit', tooltip: tooltip, label: title, disabled: action.disabled, Icon: icon, onClick: instanceHandler(action), url: 'url' in action ? getTranslation(action.url) : undefined }));
12
14
  }
13
15
  //# sourceMappingURL=InstanceActionButton.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"InstanceActionButton.js","sourceRoot":"./src/","sources":["InstanceActionButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,aAAa,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAO3D,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,MAAiC;IAC1E,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,CAAC;IAE3C,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC9E,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;IAElD,mFAAmF;IACnF,+CAA+C;IAC/C,MAAM,IAAI,GAAG,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAE/D,OAAO,CACH,oBAAC,aAAa,IACV,KAAK,EAAE,MAAM,CAAC,KAAK,EACnB,OAAO,EAAE,MAAM,CAAC,OAAO,EACvB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,MAAM,CAAC,QAAQ,EACzB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,eAAe,CAAC,MAAM,CAAC,EAChC,GAAG,EAAE,KAAK,IAAI,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,GAC/D,CACL,CAAC;AACN,CAAC","sourcesContent":["import React from 'react';\n\nimport type { ActionBase, InstanceAction } from './protocol/api';\n\nimport TooltipButton from './TooltipButton';\nimport { getTranslation, renderActionIcon } from './Utils';\n\ninterface InstanceActionButtonProps {\n action: InstanceAction;\n instanceHandler: (action: ActionBase) => () => void;\n}\n\nexport default function InstanceActionButton(params: InstanceActionButtonProps): React.JSX.Element | null {\n const { action, instanceHandler } = params;\n\n const tooltip = getTranslation(action?.description ? action.description : '');\n const title = getTranslation(action?.title || '');\n\n // If the action is rendered as a text button and no icon was explicitly requested,\n // do not fall back to the \"question mark\" icon\n const icon = renderActionIcon(action, !!title && !action.icon);\n\n return (\n <TooltipButton\n style={action.style}\n variant={action.variant}\n tooltip={tooltip}\n label={title}\n disabled={action.disabled}\n Icon={icon}\n onClick={instanceHandler(action)}\n url={'url' in action ? getTranslation(action.url) : undefined}\n />\n );\n}\n"]}
1
+ {"version":3,"file":"InstanceActionButton.js","sourceRoot":"./src/","sources":["InstanceActionButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,aAAa,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAO3D,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,MAAiC;IAC1E,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,CAAC;IAE3C,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC9E,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;IAElD,mFAAmF;IACnF,+CAA+C;IAC/C,MAAM,IAAI,GAAG,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAE/D,OAAO,CACH,oBAAC,aAAa,IACV,KAAK,EAAE,MAAM,CAAC,KAAK,EACnB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,6GAA6G;QAC7G,KAAK,EAAE,MAAM,CAAC,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAC7D,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,MAAM,CAAC,QAAQ,EACzB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,eAAe,CAAC,MAAM,CAAC,EAChC,GAAG,EAAE,KAAK,IAAI,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,GAC/D,CACL,CAAC;AACN,CAAC","sourcesContent":["import React from 'react';\n\nimport type { ActionBase, InstanceAction } from './protocol/api';\n\nimport TooltipButton from './TooltipButton';\nimport { getTranslation, renderActionIcon } from './Utils';\n\ninterface InstanceActionButtonProps {\n action: InstanceAction;\n instanceHandler: (action: ActionBase) => () => void;\n}\n\nexport default function InstanceActionButton(params: InstanceActionButtonProps): React.JSX.Element | null {\n const { action, instanceHandler } = params;\n\n const tooltip = getTranslation(action?.description ? action.description : '');\n const title = getTranslation(action?.title || '');\n\n // If the action is rendered as a text button and no icon was explicitly requested,\n // do not fall back to the \"question mark\" icon\n const icon = renderActionIcon(action, !!title && !action.icon);\n\n return (\n <TooltipButton\n style={action.style}\n variant={action.variant}\n // The toolbar is grey, so the primary color is not readable there. A contained button has its own background\n color={action.variant === 'contained' ? undefined : 'inherit'}\n tooltip={tooltip}\n label={title}\n disabled={action.disabled}\n Icon={icon}\n onClick={instanceHandler(action)}\n url={'url' in action ? getTranslation(action.url) : undefined}\n />\n );\n}\n"]}
@@ -110,7 +110,7 @@ export default function StatusIndicator(props) {
110
110
  if (!tooltip) {
111
111
  return element;
112
112
  }
113
- return (React.createElement(Tooltip, { title: tooltip, slotProps: { popper: { sx: styles.tooltip } } },
113
+ return (React.createElement(Tooltip, { title: React.createElement("span", { style: { whiteSpace: 'pre-line' } }, tooltip), slotProps: { popper: { sx: styles.tooltip } } },
114
114
  React.createElement("span", { style: { display: 'inline-flex' } }, element)));
115
115
  }
116
116
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"StatusIndicator.js","sourceRoot":"./src/","sources":["StatusIndicator.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { IconButton, Tooltip } from '@mui/material';\n\nimport type { IobTheme } from '@iobroker/gui-components';\n\nimport { useStateOrObject } from './hooks';\nimport type { StatusIndicator as StatusIndicatorConfig, StatusIndicatorLevel } from './protocol/api';\nimport type { StateOrObjectHandler } from './StateOrObjectHandler';\nimport { getIndicatorColor, getTranslation, renderIcon } from './Utils';\n\nconst styles: Record<string, React.CSSProperties> = {\n tooltip: {\n pointerEvents: 'none',\n },\n content: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n lineHeight: 1,\n },\n text: {\n fontSize: 'small',\n margin: 0,\n whiteSpace: 'nowrap',\n },\n row: {\n display: 'flex',\n alignItems: 'center',\n flexWrap: 'wrap',\n gap: 8,\n },\n};\n\n/**\n * Find the first matching level for the given value.\n *\n * A level matches if its `value` equals the current value, if the numeric value lies within\n * `min`/`max` (both inclusive) or if the level defines no condition at all (catch-all).\n */\nfunction findLevel(\n levels: StatusIndicatorLevel[],\n value: string | number | boolean | undefined,\n): StatusIndicatorLevel | undefined {\n for (const level of levels) {\n if (level.value !== undefined) {\n if (level.value === value) {\n return level;\n }\n continue;\n }\n if (level.min !== undefined || level.max !== undefined) {\n if (typeof value !== 'number') {\n continue;\n }\n if (level.min !== undefined && value < level.min) {\n continue;\n }\n if (level.max !== undefined && value > level.max) {\n continue;\n }\n return level;\n }\n // no condition => catch-all\n return level;\n }\n\n return undefined;\n}\n\ninterface StatusIndicatorProps {\n indicator: StatusIndicatorConfig;\n theme: IobTheme;\n stateOrObjectHandler: StateOrObjectHandler;\n /** Called when the indicator is clicked. If not provided, the indicator is not clickable */\n onClick?: () => void;\n /** If the referenced action opens a URL instead of calling the backend */\n url?: string;\n disabled?: boolean;\n /** Color used if the indicator does not define one itself (e.g. white in the toolbar) */\n defaultColor?: string;\n}\n\n/**\n * A single custom status indicator.\n *\n * Every visual property may be bound to a state or an object, so the indicator follows its value\n * live. The optional `levels` list maps value ranges to icon, color and text.\n */\nexport default function StatusIndicator(props: StatusIndicatorProps): React.JSX.Element | null {\n const { indicator, stateOrObjectHandler } = props;\n\n const value = useStateOrObject<string | number | boolean>(indicator.value, stateOrObjectHandler);\n const icon = useStateOrObject<string>(indicator.icon, stateOrObjectHandler);\n const iconOn = useStateOrObject<string>(indicator.iconOn, stateOrObjectHandler);\n const color = useStateOrObject<string>(indicator.color, stateOrObjectHandler);\n const colorOn = useStateOrObject<string>(indicator.colorOn, stateOrObjectHandler);\n const text = useStateOrObject<ioBroker.StringOrTranslated>(indicator.text, stateOrObjectHandler);\n\n // An indicator without a value is a static icon and is always visible. With a value, it is hidden\n // while the value is \"empty\" - the numeric 0 counts as a value and stays visible.\n if (indicator.value !== undefined && indicator.hideIfEmpty !== false) {\n if (value === undefined || value === null || value === '' || value === false) {\n return null;\n }\n }\n\n const on = !!value;\n const level = indicator.levels ? findLevel(indicator.levels, value) : undefined;\n\n const iconName = level?.icon ?? (on ? (iconOn ?? icon) : icon);\n const colorName = level?.color ?? (on ? (colorOn ?? color) : color);\n const resolvedColor = getIndicatorColor(colorName, props.theme) || props.defaultColor;\n\n const levelText = level?.text ?? text;\n let label = levelText !== undefined ? getTranslation(levelText) : indicator.showValue ? String(value ?? '') : '';\n if (label && indicator.unit) {\n label += ` ${indicator.unit}`;\n }\n\n const tooltipSource = level?.tooltip ?? indicator.tooltip;\n const tooltip = tooltipSource ? getTranslation(tooltipSource) : '';\n\n // Only fall back to the \"question mark\" icon if the indicator shows nothing else at all\n const iconElement = iconName || !label ? renderIcon(iconName, resolvedColor) : null;\n\n const content = (\n <div style={styles.content}>\n {iconElement}\n {label ? <p style={{ ...styles.text, color: resolvedColor }}>{label}</p> : null}\n </div>\n );\n\n let element: React.JSX.Element;\n if (props.url) {\n element = (\n <IconButton\n size=\"small\"\n style={{ padding: 2, borderRadius: 4 }}\n href={props.url}\n target=\"_blank\"\n disabled={props.disabled}\n >\n {content}\n </IconButton>\n );\n } else if (props.onClick) {\n element = (\n <IconButton\n size=\"small\"\n style={{ padding: 2, borderRadius: 4 }}\n disabled={props.disabled}\n onClick={e => {\n // The card itself may react on clicks, so the event must not bubble\n e.stopPropagation();\n props.onClick?.();\n }}\n >\n {content}\n </IconButton>\n );\n } else {\n element = content;\n }\n\n if (!tooltip) {\n return element;\n }\n\n return (\n <Tooltip\n title={tooltip}\n slotProps={{ popper: { sx: styles.tooltip } }}\n >\n <span style={{ display: 'inline-flex' }}>{element}</span>\n </Tooltip>\n );\n}\n\ninterface StatusIndicatorsProps {\n indicators?: StatusIndicatorConfig[];\n theme: IobTheme;\n stateOrObjectHandler: StateOrObjectHandler;\n /**\n * Resolves the click handler for an indicator that references an action. Returns `undefined`\n * if the referenced action does not exist - the indicator stays a pure display element then.\n */\n resolveAction?: (actionId: string) => { onClick?: () => void; url?: string; disabled?: boolean } | undefined;\n disabled?: boolean;\n defaultColor?: string;\n style?: React.CSSProperties;\n /** Additional elements rendered in the same line (e.g. actions with `placement: 'status'`) */\n children?: React.ReactNode;\n}\n\n/**\n * The line of custom status indicators.\n *\n * The line wraps if it does not fit, so an arbitrary number of indicators can be shown without\n * cutting anything off.\n */\nexport function StatusIndicators(props: StatusIndicatorsProps): React.JSX.Element | null {\n const indicators = props.indicators?.length\n ? [...props.indicators].sort((a, b) => (a.order ?? 100) - (b.order ?? 100))\n : [];\n\n if (!indicators.length && !props.children) {\n return null;\n }\n\n return (\n <div style={{ ...styles.row, ...props.style }}>\n {indicators.map(indicator => {\n const action = indicator.actionId ? props.resolveAction?.(indicator.actionId) : undefined;\n\n return (\n <StatusIndicator\n key={indicator.id}\n indicator={indicator}\n theme={props.theme}\n stateOrObjectHandler={props.stateOrObjectHandler}\n onClick={action?.onClick}\n url={action?.url}\n disabled={props.disabled || action?.disabled}\n defaultColor={props.defaultColor}\n />\n );\n })}\n {props.children}\n </div>\n );\n}\n"]}
1
+ {"version":3,"file":"StatusIndicator.js","sourceRoot":"./src/","sources":["StatusIndicator.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\nimport { IconButton, Tooltip } from '@mui/material';\n\nimport type { IobTheme } from '@iobroker/gui-components';\n\nimport { useStateOrObject } from './hooks';\nimport type { StatusIndicator as StatusIndicatorConfig, StatusIndicatorLevel } from './protocol/api';\nimport type { StateOrObjectHandler } from './StateOrObjectHandler';\nimport { getIndicatorColor, getTranslation, renderIcon } from './Utils';\n\nconst styles: Record<string, React.CSSProperties> = {\n tooltip: {\n pointerEvents: 'none',\n },\n content: {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n lineHeight: 1,\n },\n text: {\n fontSize: 'small',\n margin: 0,\n whiteSpace: 'nowrap',\n },\n row: {\n display: 'flex',\n alignItems: 'center',\n flexWrap: 'wrap',\n gap: 8,\n },\n};\n\n/**\n * Find the first matching level for the given value.\n *\n * A level matches if its `value` equals the current value, if the numeric value lies within\n * `min`/`max` (both inclusive) or if the level defines no condition at all (catch-all).\n */\nfunction findLevel(\n levels: StatusIndicatorLevel[],\n value: string | number | boolean | undefined,\n): StatusIndicatorLevel | undefined {\n for (const level of levels) {\n if (level.value !== undefined) {\n if (level.value === value) {\n return level;\n }\n continue;\n }\n if (level.min !== undefined || level.max !== undefined) {\n if (typeof value !== 'number') {\n continue;\n }\n if (level.min !== undefined && value < level.min) {\n continue;\n }\n if (level.max !== undefined && value > level.max) {\n continue;\n }\n return level;\n }\n // no condition => catch-all\n return level;\n }\n\n return undefined;\n}\n\ninterface StatusIndicatorProps {\n indicator: StatusIndicatorConfig;\n theme: IobTheme;\n stateOrObjectHandler: StateOrObjectHandler;\n /** Called when the indicator is clicked. If not provided, the indicator is not clickable */\n onClick?: () => void;\n /** If the referenced action opens a URL instead of calling the backend */\n url?: string;\n disabled?: boolean;\n /** Color used if the indicator does not define one itself (e.g. white in the toolbar) */\n defaultColor?: string;\n}\n\n/**\n * A single custom status indicator.\n *\n * Every visual property may be bound to a state or an object, so the indicator follows its value\n * live. The optional `levels` list maps value ranges to icon, color and text.\n */\nexport default function StatusIndicator(props: StatusIndicatorProps): React.JSX.Element | null {\n const { indicator, stateOrObjectHandler } = props;\n\n const value = useStateOrObject<string | number | boolean>(indicator.value, stateOrObjectHandler);\n const icon = useStateOrObject<string>(indicator.icon, stateOrObjectHandler);\n const iconOn = useStateOrObject<string>(indicator.iconOn, stateOrObjectHandler);\n const color = useStateOrObject<string>(indicator.color, stateOrObjectHandler);\n const colorOn = useStateOrObject<string>(indicator.colorOn, stateOrObjectHandler);\n const text = useStateOrObject<ioBroker.StringOrTranslated>(indicator.text, stateOrObjectHandler);\n\n // An indicator without a value is a static icon and is always visible. With a value, it is hidden\n // while the value is \"empty\" - the numeric 0 counts as a value and stays visible.\n if (indicator.value !== undefined && indicator.hideIfEmpty !== false) {\n if (value === undefined || value === null || value === '' || value === false) {\n return null;\n }\n }\n\n const on = !!value;\n const level = indicator.levels ? findLevel(indicator.levels, value) : undefined;\n\n const iconName = level?.icon ?? (on ? (iconOn ?? icon) : icon);\n const colorName = level?.color ?? (on ? (colorOn ?? color) : color);\n const resolvedColor = getIndicatorColor(colorName, props.theme) || props.defaultColor;\n\n const levelText = level?.text ?? text;\n let label = levelText !== undefined ? getTranslation(levelText) : indicator.showValue ? String(value ?? '') : '';\n if (label && indicator.unit) {\n label += ` ${indicator.unit}`;\n }\n\n const tooltipSource = level?.tooltip ?? indicator.tooltip;\n const tooltip = tooltipSource ? getTranslation(tooltipSource) : '';\n\n // Only fall back to the \"question mark\" icon if the indicator shows nothing else at all\n const iconElement = iconName || !label ? renderIcon(iconName, resolvedColor) : null;\n\n const content = (\n <div style={styles.content}>\n {iconElement}\n {label ? <p style={{ ...styles.text, color: resolvedColor }}>{label}</p> : null}\n </div>\n );\n\n let element: React.JSX.Element;\n if (props.url) {\n element = (\n <IconButton\n size=\"small\"\n style={{ padding: 2, borderRadius: 4 }}\n href={props.url}\n target=\"_blank\"\n disabled={props.disabled}\n >\n {content}\n </IconButton>\n );\n } else if (props.onClick) {\n element = (\n <IconButton\n size=\"small\"\n style={{ padding: 2, borderRadius: 4 }}\n disabled={props.disabled}\n onClick={e => {\n // The card itself may react on clicks, so the event must not bubble\n e.stopPropagation();\n props.onClick?.();\n }}\n >\n {content}\n </IconButton>\n );\n } else {\n element = content;\n }\n\n if (!tooltip) {\n return element;\n }\n\n return (\n <Tooltip\n title={<span style={{ whiteSpace: 'pre-line' }}>{tooltip}</span>}\n slotProps={{ popper: { sx: styles.tooltip } }}\n >\n <span style={{ display: 'inline-flex' }}>{element}</span>\n </Tooltip>\n );\n}\n\ninterface StatusIndicatorsProps {\n indicators?: StatusIndicatorConfig[];\n theme: IobTheme;\n stateOrObjectHandler: StateOrObjectHandler;\n /**\n * Resolves the click handler for an indicator that references an action. Returns `undefined`\n * if the referenced action does not exist - the indicator stays a pure display element then.\n */\n resolveAction?: (actionId: string) => { onClick?: () => void; url?: string; disabled?: boolean } | undefined;\n disabled?: boolean;\n defaultColor?: string;\n style?: React.CSSProperties;\n /** Additional elements rendered in the same line (e.g. actions with `placement: 'status'`) */\n children?: React.ReactNode;\n}\n\n/**\n * The line of custom status indicators.\n *\n * The line wraps if it does not fit, so an arbitrary number of indicators can be shown without\n * cutting anything off.\n */\nexport function StatusIndicators(props: StatusIndicatorsProps): React.JSX.Element | null {\n const indicators = props.indicators?.length\n ? [...props.indicators].sort((a, b) => (a.order ?? 100) - (b.order ?? 100))\n : [];\n\n if (!indicators.length && !props.children) {\n return null;\n }\n\n return (\n <div style={{ ...styles.row, ...props.style }}>\n {indicators.map(indicator => {\n const action = indicator.actionId ? props.resolveAction?.(indicator.actionId) : undefined;\n\n return (\n <StatusIndicator\n key={indicator.id}\n indicator={indicator}\n theme={props.theme}\n stateOrObjectHandler={props.stateOrObjectHandler}\n onClick={action?.onClick}\n url={action?.url}\n disabled={props.disabled || action?.disabled}\n defaultColor={props.defaultColor}\n />\n );\n })}\n {props.children}\n </div>\n );\n}\n"]}
@@ -7,6 +7,8 @@ interface TooltipButtonProps {
7
7
  onClick?: () => void;
8
8
  url?: string;
9
9
  variant?: 'text' | 'outlined' | 'contained';
10
+ /** `inherit` takes the text color of the parent, e.g. on a colored toolbar. Default is the primary color */
11
+ color?: 'inherit' | 'primary';
10
12
  style?: Record<string, any>;
11
13
  }
12
14
  export default function TooltipButton(props: TooltipButtonProps): React.JSX.Element;
@@ -1,11 +1,11 @@
1
1
  import React from 'react';
2
2
  import { Button, IconButton, Tooltip, Typography } from '@mui/material';
3
3
  export default function TooltipButton(props) {
4
- const { tooltip, label, disabled, Icon, onClick, url } = props;
4
+ const { tooltip, label, disabled, Icon, onClick, url, color } = props;
5
5
  const text = label ? (React.createElement(Typography, { variant: "button", sx: props.style,
6
6
  // The gap is only required if an icon is shown in front of the text
7
7
  style: { marginLeft: Icon ? 4 : undefined } }, label)) : null;
8
- const btnProps = url ? { href: url, disabled, target: '_blank' } : { onClick, disabled };
8
+ const btnProps = url ? { href: url, disabled, target: '_blank', color } : { onClick, disabled, color };
9
9
  if (tooltip) {
10
10
  return (React.createElement(Tooltip, { title: tooltip, slotProps: { popper: { sx: { pointerEvents: 'none' } } } },
11
11
  React.createElement("span", null, text ? (React.createElement(Button, { ...btnProps, sx: props.style, variant: props.variant, startIcon: Icon }, text)) : (React.createElement(IconButton, { ...btnProps, sx: props.style, size: "small" }, Icon)))));
@@ -1 +1 @@
1
- {"version":3,"file":"TooltipButton.js","sourceRoot":"./src/","sources":["TooltipButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAaxE,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,KAAyB;IAC3D,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC;IAE/D,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CACjB,oBAAC,UAAU,IACP,OAAO,EAAC,QAAQ,EAChB,EAAE,EAAE,KAAK,CAAC,KAAK;QACf,oEAAoE;QACpE,KAAK,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,IAE1C,KAAK,CACG,CAChB,CAAC,CAAC,CAAC,IAAI,CAAC;IAET,MAAM,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC;IAEzF,IAAI,OAAO,EAAE,CAAC;QACV,OAAO,CACH,oBAAC,OAAO,IACJ,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE;YAExD,kCACK,IAAI,CAAC,CAAC,CAAC,CACJ,oBAAC,MAAM,OACC,QAAQ,EACZ,EAAE,EAAE,KAAK,CAAC,KAAK,EACf,OAAO,EAAE,KAAK,CAAC,OAAO,EACtB,SAAS,EAAE,IAAI,IAEd,IAAI,CACA,CACZ,CAAC,CAAC,CAAC,CACA,oBAAC,UAAU,OACH,QAAQ,EACZ,EAAE,EAAE,KAAK,CAAC,KAAK,EACf,IAAI,EAAC,OAAO,IAEX,IAAI,CACI,CAChB,CACE,CACD,CACb,CAAC;IACN,CAAC;IAED,OAAO,IAAI,CAAC,CAAC,CAAC,CACV,oBAAC,MAAM,OACC,QAAQ,EACZ,EAAE,EAAE,KAAK,CAAC,KAAK,EACf,OAAO,EAAE,KAAK,CAAC,OAAO,EACtB,SAAS,EAAE,IAAI,IAEd,IAAI,CACA,CACZ,CAAC,CAAC,CAAC,CACA,oBAAC,UAAU,OACH,QAAQ,EACZ,EAAE,EAAE,KAAK,CAAC,KAAK,EACf,IAAI,EAAC,OAAO,IAEX,IAAI,CACI,CAChB,CAAC;AACN,CAAC","sourcesContent":["import React from 'react';\nimport { Button, IconButton, Tooltip, Typography } from '@mui/material';\n\ninterface TooltipButtonProps {\n tooltip?: string;\n label?: string;\n disabled?: boolean;\n Icon: React.JSX.Element | null;\n onClick?: () => void;\n url?: string;\n variant?: 'text' | 'outlined' | 'contained';\n style?: Record<string, any>;\n}\n\nexport default function TooltipButton(props: TooltipButtonProps): React.JSX.Element {\n const { tooltip, label, disabled, Icon, onClick, url } = props;\n\n const text = label ? (\n <Typography\n variant=\"button\"\n sx={props.style}\n // The gap is only required if an icon is shown in front of the text\n style={{ marginLeft: Icon ? 4 : undefined }}\n >\n {label}\n </Typography>\n ) : null;\n\n const btnProps = url ? { href: url, disabled, target: '_blank' } : { onClick, disabled };\n\n if (tooltip) {\n return (\n <Tooltip\n title={tooltip}\n slotProps={{ popper: { sx: { pointerEvents: 'none' } } }}\n >\n <span>\n {text ? (\n <Button\n {...btnProps}\n sx={props.style}\n variant={props.variant}\n startIcon={Icon}\n >\n {text}\n </Button>\n ) : (\n <IconButton\n {...btnProps}\n sx={props.style}\n size=\"small\"\n >\n {Icon}\n </IconButton>\n )}\n </span>\n </Tooltip>\n );\n }\n\n return text ? (\n <Button\n {...btnProps}\n sx={props.style}\n variant={props.variant}\n startIcon={Icon}\n >\n {text}\n </Button>\n ) : (\n <IconButton\n {...btnProps}\n sx={props.style}\n size=\"small\"\n >\n {Icon}\n </IconButton>\n );\n}\n"]}
1
+ {"version":3,"file":"TooltipButton.js","sourceRoot":"./src/","sources":["TooltipButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAexE,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,KAAyB;IAC3D,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;IAEtE,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CACjB,oBAAC,UAAU,IACP,OAAO,EAAC,QAAQ,EAChB,EAAE,EAAE,KAAK,CAAC,KAAK;QACf,oEAAoE;QACpE,KAAK,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,IAE1C,KAAK,CACG,CAChB,CAAC,CAAC,CAAC,IAAI,CAAC;IAET,MAAM,QAAQ,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAEvG,IAAI,OAAO,EAAE,CAAC;QACV,OAAO,CACH,oBAAC,OAAO,IACJ,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE;YAExD,kCACK,IAAI,CAAC,CAAC,CAAC,CACJ,oBAAC,MAAM,OACC,QAAQ,EACZ,EAAE,EAAE,KAAK,CAAC,KAAK,EACf,OAAO,EAAE,KAAK,CAAC,OAAO,EACtB,SAAS,EAAE,IAAI,IAEd,IAAI,CACA,CACZ,CAAC,CAAC,CAAC,CACA,oBAAC,UAAU,OACH,QAAQ,EACZ,EAAE,EAAE,KAAK,CAAC,KAAK,EACf,IAAI,EAAC,OAAO,IAEX,IAAI,CACI,CAChB,CACE,CACD,CACb,CAAC;IACN,CAAC;IAED,OAAO,IAAI,CAAC,CAAC,CAAC,CACV,oBAAC,MAAM,OACC,QAAQ,EACZ,EAAE,EAAE,KAAK,CAAC,KAAK,EACf,OAAO,EAAE,KAAK,CAAC,OAAO,EACtB,SAAS,EAAE,IAAI,IAEd,IAAI,CACA,CACZ,CAAC,CAAC,CAAC,CACA,oBAAC,UAAU,OACH,QAAQ,EACZ,EAAE,EAAE,KAAK,CAAC,KAAK,EACf,IAAI,EAAC,OAAO,IAEX,IAAI,CACI,CAChB,CAAC;AACN,CAAC","sourcesContent":["import React from 'react';\nimport { Button, IconButton, Tooltip, Typography } from '@mui/material';\n\ninterface TooltipButtonProps {\n tooltip?: string;\n label?: string;\n disabled?: boolean;\n Icon: React.JSX.Element | null;\n onClick?: () => void;\n url?: string;\n variant?: 'text' | 'outlined' | 'contained';\n /** `inherit` takes the text color of the parent, e.g. on a colored toolbar. Default is the primary color */\n color?: 'inherit' | 'primary';\n style?: Record<string, any>;\n}\n\nexport default function TooltipButton(props: TooltipButtonProps): React.JSX.Element {\n const { tooltip, label, disabled, Icon, onClick, url, color } = props;\n\n const text = label ? (\n <Typography\n variant=\"button\"\n sx={props.style}\n // The gap is only required if an icon is shown in front of the text\n style={{ marginLeft: Icon ? 4 : undefined }}\n >\n {label}\n </Typography>\n ) : null;\n\n const btnProps = url ? { href: url, disabled, target: '_blank', color } : { onClick, disabled, color };\n\n if (tooltip) {\n return (\n <Tooltip\n title={tooltip}\n slotProps={{ popper: { sx: { pointerEvents: 'none' } } }}\n >\n <span>\n {text ? (\n <Button\n {...btnProps}\n sx={props.style}\n variant={props.variant}\n startIcon={Icon}\n >\n {text}\n </Button>\n ) : (\n <IconButton\n {...btnProps}\n sx={props.style}\n size=\"small\"\n >\n {Icon}\n </IconButton>\n )}\n </span>\n </Tooltip>\n );\n }\n\n return text ? (\n <Button\n {...btnProps}\n sx={props.style}\n variant={props.variant}\n startIcon={Icon}\n >\n {text}\n </Button>\n ) : (\n <IconButton\n {...btnProps}\n sx={props.style}\n size=\"small\"\n >\n {Icon}\n </IconButton>\n );\n}\n"]}
@@ -6,6 +6,7 @@
6
6
  "batteryTooltip": "Batterie",
7
7
  "cancelButtonText": "Abbrechen",
8
8
  "closeButtonText": "Schließen",
9
+ "configManager": "Konfig-Manager",
9
10
  "connectedIconTooltip": "Verbunden",
10
11
  "copied": "Kopiert",
11
12
  "ctcButtonText": "In die Zwischenablage kopieren",
@@ -6,6 +6,7 @@
6
6
  "batteryTooltip": "Battery",
7
7
  "cancelButtonText": "Cancel",
8
8
  "closeButtonText": "Close",
9
+ "configManager": "Config manager",
9
10
  "connectedIconTooltip": "Connected",
10
11
  "copied": "Copied",
11
12
  "ctcButtonText": "Copy to clipboard",
@@ -6,6 +6,7 @@
6
6
  "batteryTooltip": "Batería",
7
7
  "cancelButtonText": "Cancelar",
8
8
  "closeButtonText": "Cerca",
9
+ "configManager": "Administrador de configuración",
9
10
  "connectedIconTooltip": "Conectado",
10
11
  "copied": "copiado",
11
12
  "ctcButtonText": "Copiar al portapapeles",
@@ -6,6 +6,7 @@
6
6
  "batteryTooltip": "Batterie",
7
7
  "cancelButtonText": "Annuler",
8
8
  "closeButtonText": "Fermer",
9
+ "configManager": "Gestionnaire de configuration",
9
10
  "connectedIconTooltip": "Connecté",
10
11
  "copied": "Copié",
11
12
  "ctcButtonText": "Copier dans le presse-papier",
@@ -6,6 +6,7 @@
6
6
  "batteryTooltip": "Batteria",
7
7
  "cancelButtonText": "Annulla",
8
8
  "closeButtonText": "Vicino",
9
+ "configManager": "Gestore configurazioni",
9
10
  "connectedIconTooltip": "Connesso",
10
11
  "copied": "Copiato",
11
12
  "ctcButtonText": "Copia negli appunti",
@@ -6,6 +6,7 @@
6
6
  "batteryTooltip": "Batterij",
7
7
  "cancelButtonText": "Annuleren",
8
8
  "closeButtonText": "Dichtbij",
9
+ "configManager": "Configuratiebeheer",
9
10
  "connectedIconTooltip": "Verbonden",
10
11
  "copied": "Gekopieerd",
11
12
  "ctcButtonText": "Kopiëren naar klembord",
@@ -6,6 +6,7 @@
6
6
  "batteryTooltip": "Bateria",
7
7
  "cancelButtonText": "Anulować",
8
8
  "closeButtonText": "Zamknąć",
9
+ "configManager": "Menedżer konfiguracji",
9
10
  "connectedIconTooltip": "Połączono",
10
11
  "copied": "Skopiowano",
11
12
  "ctcButtonText": "Kopiuj do schowka",
@@ -6,6 +6,7 @@
6
6
  "batteryTooltip": "Bateria",
7
7
  "cancelButtonText": "Cancelar",
8
8
  "closeButtonText": "Fechar",
9
+ "configManager": "Gerenciador de configurações",
9
10
  "connectedIconTooltip": "Conectado",
10
11
  "copied": "Copiado",
11
12
  "ctcButtonText": "Copiar para área de transferência",
@@ -6,6 +6,7 @@
6
6
  "batteryTooltip": "Батарея",
7
7
  "cancelButtonText": "Отмена",
8
8
  "closeButtonText": "Закрыть",
9
+ "configManager": "Менеджер конфигураций",
9
10
  "connectedIconTooltip": "Подключено",
10
11
  "copied": "Скопировано",
11
12
  "ctcButtonText": "Копировать в буфер обмена",
@@ -6,6 +6,7 @@
6
6
  "batteryTooltip": "Батарея",
7
7
  "cancelButtonText": "Скасувати",
8
8
  "closeButtonText": "Закрити",
9
+ "configManager": "Менеджер конфігурацій",
9
10
  "connectedIconTooltip": "Підключено",
10
11
  "copied": "Скопійовано",
11
12
  "ctcButtonText": "Копіювати в буфер обміну",
@@ -6,6 +6,7 @@
6
6
  "batteryTooltip": "电池",
7
7
  "cancelButtonText": "取消",
8
8
  "closeButtonText": "关闭",
9
+ "configManager": "配置管理器",
9
10
  "connectedIconTooltip": "已连接",
10
11
  "copied": "已复制",
11
12
  "ctcButtonText": "复制到剪贴板",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iobroker/dm-gui-components",
3
- "version": "10.0.21",
3
+ "version": "10.0.23",
4
4
  "description": "ReactJS components to develop admin interface for ioBroker device manager.",
5
5
  "author": {
6
6
  "name": "Jey Cee",
@@ -25,7 +25,8 @@
25
25
  "release-patch": "release-script patch --yes --no-update-lockfile --publishAll",
26
26
  "release-minor": "release-script minor --yes --no-update-lockfile --publishAll",
27
27
  "release-major": "release-script major --yes --no-update-lockfile --publishAll",
28
- "update-packages": "npx -y npm-check-updates --upgrade"
28
+ "update-packages": "npx -y npm-check-updates --upgrade && cd src-test && npx -y npm-check-updates --upgrade",
29
+ "npm": "npm i && cd src-test && npm i"
29
30
  },
30
31
  "repository": {
31
32
  "type": "git",
@@ -52,29 +53,29 @@
52
53
  },
53
54
  "homepage": "https://github.com/ioBroker/dm-gui-components#readme",
54
55
  "dependencies": {
55
- "@iobroker/gui-components": "^10.2.0",
56
- "@iobroker/json-config": "^9.1.0",
56
+ "@iobroker/gui-components": "^10.3.1",
57
+ "@iobroker/json-config": "^10.0.6",
57
58
  "@mui/icons-material": "^9.4.0",
58
59
  "@mui/material": "^9.4.0"
59
60
  },
60
61
  "devDependencies": {
61
62
  "@alcalzone/release-script": "^5.2.1",
62
63
  "@alcalzone/release-script-plugin-license": "^5.2.2",
63
- "@iobroker/build-tools": "^3.0.1",
64
- "@iobroker/dm-utils": "^3.2.0",
64
+ "@iobroker/build-tools": "^3.0.3",
65
+ "@iobroker/dm-utils": "^3.2.1",
65
66
  "@iobroker/dm-utils-v1": "npm:@iobroker/dm-utils@^1.0.16",
66
67
  "@iobroker/eslint-config": "^2.3.4",
67
- "@types/react": "^19.2.18",
68
- "@types/react-dom": "^19.2.5",
69
- "react": "^19.2.8",
70
- "react-dom": "^19.2.8",
71
- "tsc-alias": "^1.9.2",
68
+ "@types/react": "^19.3.0",
69
+ "@types/react-dom": "^19.3.0",
70
+ "react": "^19.3.0",
71
+ "react-dom": "^19.3.0",
72
+ "tsc-alias": "^1.9.5",
72
73
  "typescript": "~6.0.3"
73
74
  },
74
75
  "overrides": {
75
- "react": "^19.2.8",
76
- "react-dom": "^19.2.8",
77
- "@types/react": "^19.2.18",
78
- "@types/react-dom": "^19.2.5"
76
+ "react": "^19.3.0",
77
+ "react-dom": "^19.3.0",
78
+ "@types/react": "^19.3.0",
79
+ "@types/react-dom": "^19.3.0"
79
80
  }
80
81
  }