Skip to content

Commit

Permalink
started working on devices design optimizations (#48)
Browse files Browse the repository at this point in the history
* started working on devices design optimizations

* apply new lines correctly

* rework the two add buttons on the devices tab to a single one with a dialog to select further options

* make the add buttons in primary color

* format the pairing code

* added info text on qr code dialog

* fix build

* fix rest of types imports

* another

* show only one + button for bridges too

- fix problem that auto detect and from state was reverted

* do not limit bridges/devices list to 600px

* move re-announce button for devices and bridges into qr code dialog
  • Loading branch information
foxriver76 authored Jul 26, 2024
1 parent cdabca0 commit 36d567e
Show file tree
Hide file tree
Showing 19 changed files with 272 additions and 151 deletions.
174 changes: 99 additions & 75 deletions src-admin/src/Tabs/Bridges.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ import { v4 as uuidv4 } from 'uuid';

import {
Add,
AutoMode,
Close,
Delete,
DomainDisabled,
Edit,
FormatListBulleted,
KeyboardArrowDown,
KeyboardArrowUp,
QuestionMark,
Save,
SettingsInputAntenna,
UnfoldLess,
UnfoldMore,
} from '@mui/icons-material';
Expand Down Expand Up @@ -41,15 +42,15 @@ import {

import { I18n, SelectID, type IobTheme } from '@iobroker/adapter-react-v5';

import DeviceDialog, { DEVICE_ICONS, SUPPORTED_DEVICES } from '../components/DeviceDialog';
import type {
BridgeDescription,
BridgeDeviceDescription,
DetectedDevice,
DetectedRoom,
DeviceDescription,
MatterConfig,
} from '@/types';
import DeviceDialog, { DEVICE_ICONS, SUPPORTED_DEVICES } from '../components/DeviceDialog';
} from '../types';
import { clone, detectDevices, getText } from '../Utils';
import BridgesAndDevices, {
STYLES,
Expand Down Expand Up @@ -129,6 +130,21 @@ interface BridgesProps extends BridgesAndDevicesProps {
}

interface BridgesState extends BridgesAndDevicesState {
/** Open Dialog to select further options to add a device */
addDevicePreDialog:
| {
/** If dialog open */
open: true;
bridge: {
name: string;
bridgeIndex: number;
devices: BridgeDeviceDescription[];
};
}
| {
/** If dialog open */
open: false;
};
editBridgeDialog: {
type: 'bridge';
name: string;
Expand Down Expand Up @@ -199,6 +215,7 @@ export class Bridges extends BridgesAndDevices<BridgesProps, BridgesState> {
}

Object.assign(this.state, {
addDevicePreDialog: { open: false },
addDeviceDialog: null,
editBridgeDialog: null,
editDeviceDialog: null,
Expand Down Expand Up @@ -729,6 +746,69 @@ export class Bridges extends BridgesAndDevices<BridgesProps, BridgesState> {
);
}

/**
* Render dialog to select if devices should be added from state or detected automatically
*/
renderAddDevicesPreDialog(): React.JSX.Element {
if (!this.state.addDevicePreDialog.open) {
return null;
}

return (
<Dialog open={!0} onClose={() => this.setState({ addDevicePreDialog: { open: false } })}>
<DialogTitle>{I18n.t('Add device')}</DialogTitle>
<DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
<Button
onClick={() => {
if (!this.state.addDevicePreDialog.open) {
return;
}

this.setState({
addDevicePreDialog: { open: false },
addDeviceDialog: {
noAutoDetect: false,
name: getText(this.state.addDevicePreDialog.bridge.name),
bridgeIndex: this.state.addDevicePreDialog.bridge.bridgeIndex,
devices: this.state.addDevicePreDialog.bridge.devices,
},
});
}}
startIcon={<AutoMode />}
color="primary"
variant="contained"
sx={{ justifyContent: 'flex-start' }}
>
{I18n.t('Add device with auto-detection')}
</Button>
<Button
onClick={() => {
if (!this.state.addDevicePreDialog.open) {
return;
}

this.setState({
addDevicePreDialog: { open: false },
addDeviceDialog: {
noAutoDetect: true,
name: getText(this.state.addDevicePreDialog.bridge.name),
bridgeIndex: this.state.addDevicePreDialog.bridge.bridgeIndex,
devices: this.state.addDevicePreDialog.bridge.devices,
},
});
}}
startIcon={<FormatListBulleted />}
color="primary"
variant="contained"
sx={{ justifyContent: 'flex-start' }}
>
{I18n.t('Add device from one state')}
</Button>
</DialogContent>
</Dialog>
);
}

renderAddCustomDeviceDialog() {
if (!this.state.addCustomDeviceDialog) {
return null;
Expand Down Expand Up @@ -1083,43 +1163,22 @@ export class Bridges extends BridgesAndDevices<BridgesProps, BridgesState> {
>
{I18n.t('Devices')}
</TableCell>
<TableCell
style={{
fontWeight: 'bold',
opacity: bridge.enabled ? 1 : 0.5,
paddingLeft: 8,
}}
sx={styles.devicesHeader}
/>
<TableCell
style={{
width: 0,
textAlign: 'center',
opacity: bridge.enabled ? 1 : 0.5,
}}
sx={styles.devicesHeader}
>
{this.props.alive &&
bridge.enabled &&
this.props.nodeStates[bridge.uuid]?.status === 'waitingForCommissioning' ? (
<Tooltip
title={I18n.t('Re-announce')}
componentsProps={{ popper: { sx: styles.tooltip } }}
>
<IconButton
onClick={() => {
this.props.socket
.sendTo(`matter.${this.props.instance}`, 'deviceReAnnounce', {
uuid: bridge.uuid,
})
.then(result => {
if (result.error) {
window.alert(`Cannot re-announce: ${result.error}`);
} else {
this.props.updateNodeStates({
[bridge.uuid]: result.result,
});
}
});
}}
>
<SettingsInputAntenna />
</IconButton>
</Tooltip>
) : null}
</TableCell>
/>
<TableCell
style={{
width: 0,
Expand Down Expand Up @@ -1150,45 +1209,10 @@ export class Bridges extends BridgesAndDevices<BridgesProps, BridgesState> {
sx={styles.devicesHeader}
>
<Tooltip
title={I18n.t('Add device with auto-detection')}
componentsProps={{ popper: { sx: styles.tooltip } }}
>
<IconButton
onClick={async () => {
const isLicenseOk = await this.props.checkLicenseOnAdd('addDeviceToBridge');
if (!isLicenseOk) {
this.props.alive &&
this.props.showToast(
I18n.t(
'You need ioBroker.pro assistant or remote subscription to have more than 5 devices in bridge',
),
);
return;
}
this.setState({
addDeviceDialog: {
noAutoDetect: false,
name: getText(bridge.name),
bridgeIndex,
devices: bridge.list,
},
});
}}
>
<Add />
</IconButton>
</Tooltip>
</TableCell>
<TableCell
style={{ width: 0, opacity: bridge.enabled ? 1 : 0.5 }}
sx={styles.devicesHeader}
>
<Tooltip
title={I18n.t('Add device from one state')}
title={I18n.t('Add device')}
componentsProps={{ popper: { sx: styles.tooltip } }}
>
<IconButton
style={{ color: 'gray' }}
onClick={async () => {
const isLicenseOk = await this.props.checkLicenseOnAdd('addDeviceToBridge');
if (!isLicenseOk) {
Expand All @@ -1201,11 +1225,9 @@ export class Bridges extends BridgesAndDevices<BridgesProps, BridgesState> {
return;
}
this.setState({
addDeviceDialog: {
noAutoDetect: true,
name: getText(bridge.name),
bridgeIndex,
devices: bridge.list,
addDevicePreDialog: {
open: true,
bridge: { devices: bridge.list, name: bridge.name, bridgeIndex },
},
});
}}
Expand All @@ -1228,6 +1250,7 @@ export class Bridges extends BridgesAndDevices<BridgesProps, BridgesState> {
return (
<div>
{this.renderAddDeviceDialog()}
{this.renderAddDevicesPreDialog()}
{this.renderAddCustomDeviceDialog()}
{this.renderDeleteDialog()}
{this.renderBridgeEditDialog()}
Expand All @@ -1237,6 +1260,7 @@ export class Bridges extends BridgesAndDevices<BridgesProps, BridgesState> {
{this.renderResetDialog()}
<Tooltip title={I18n.t('Add bridge')} componentsProps={{ popper: { sx: styles.tooltip } }}>
<Fab
color="primary"
size="small"
onClick={async () => {
const isLicenseOk = await this.props.checkLicenseOnAdd('addBridge');
Expand Down Expand Up @@ -1316,7 +1340,7 @@ export class Bridges extends BridgesAndDevices<BridgesProps, BridgesState> {
) : (
I18n.t('No bridges created. Create one, by clicking on the "+" button in the bottom right corner.')
)}
<Table size="small" style={{ width: '100%', maxWidth: 600 }} padding="none" sx={styles.table}>
<Table size="small" style={{ width: '100%' }} padding="none" sx={styles.table}>
<TableBody>
{this.props.matter.bridges.map((bridge, bridgeIndex) => this.renderBridge(bridge, bridgeIndex))}
</TableBody>
Expand Down
Loading

0 comments on commit 36d567e

Please sign in to comment.