Skip to content

Commit

Permalink
Implemented progress dialog: #199
Browse files Browse the repository at this point in the history
  • Loading branch information
GermanBluefox committed Dec 11, 2024
1 parent adfd7e4 commit 63aa230
Show file tree
Hide file tree
Showing 18 changed files with 121 additions and 19 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"dependencies": {
"@iobroker/adapter-core": "^3.2.3",
"@iobroker/i18n": "^0.3.1",
"@iobroker/dm-utils": "^0.6.10",
"@iobroker/dm-utils": "^0.6.11",
"@iobroker/type-detector": "^4.1.0",
"@matter/main": "0.11.9-alpha.0-20241208-09ad57f78",
"@matter/nodejs": "0.11.9-alpha.0-20241208-09ad57f78",
Expand Down
4 changes: 2 additions & 2 deletions src-admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
},
"dependencies": {
"@foxriver76/iob-component-lib": "^0.2.0",
"@iobroker/adapter-react-v5": "^7.4.4",
"@iobroker/dm-gui-components": "~7.4.4",
"@iobroker/adapter-react-v5": "^7.4.5",
"@iobroker/dm-gui-components": "~7.4.5",
"@iobroker/type-detector": "^4.1.0",
"@types/react-dom": "^18.3.3",
"@types/uuid": "^10.0.0",
Expand Down
82 changes: 76 additions & 6 deletions src-admin/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,17 @@ import { StyledEngineProvider, ThemeProvider } from '@mui/material/styles';
import React from 'react';

import { IconButton } from '@foxriver76/iob-component-lib';
import { AppBar, Tab, Tabs, Tooltip } from '@mui/material';
import {
AppBar,
Dialog,
DialogContent,
DialogContentText,
DialogTitle,
LinearProgress,
Tab,
Tabs,
Tooltip
} from '@mui/material';

import { SignalCellularOff as IconNotAlive } from '@mui/icons-material';

Expand All @@ -15,7 +25,7 @@ import {
type GenericAppState,
type IobTheme,
} from '@iobroker/adapter-react-v5';
import { clone } from './Utils';
import {clone, getText} from './Utils';

import ConfigHandler from './components/ConfigHandler';
import BridgesTab from './Tabs/Bridges';
Expand Down Expand Up @@ -83,6 +93,12 @@ interface AppState extends GenericAppState {
/** Undefined if no detection ran yet */
detectedDevices?: DetectedRoom[];
ready: boolean;
progress: {
title?: ioBroker.StringOrTranslated;
text?: ioBroker.StringOrTranslated;
indeterminate?: boolean;
value?: number;
} | null;
}

class App extends GenericApp<GenericAppProps, AppState> {
Expand Down Expand Up @@ -138,6 +154,7 @@ class App extends GenericApp<GenericAppProps, AppState> {
devices: {},
},
ready: false,
progress: null,
});

this.alert = window.alert;
Expand Down Expand Up @@ -253,9 +270,11 @@ class App extends GenericApp<GenericAppProps, AppState> {
this.setState({ alive: true });
this.refreshBackendSubscription(true);
} else if (!state?.val && this.state.alive) {
this.refreshTimer && clearTimeout(this.refreshTimer);
this.refreshTimer = null;
this.setState({ alive: false });
if (this.refreshTimer) {
clearTimeout(this.refreshTimer);
this.refreshTimer = null;
}
this.setState({ alive: false, progress: null });
}
};

Expand All @@ -264,7 +283,32 @@ class App extends GenericApp<GenericAppProps, AppState> {
return;
}

if (update.command === 'bridgeStates') {
if (update.command === 'progress') {
if (update.progress) {
if (update.progress.close) {
if (this.state.progress) {
this.setState({ progress: null });
}
} else {
const progress = { ...this.state.progress };
if (update.progress.title !== undefined) {
progress.title = update.progress.title;
}
if (update.progress.value !== undefined) {
progress.value = update.progress.value;
}
if (update.progress.text !== undefined) {
progress.text = update.progress.text;
}
if (update.progress.indeterminate !== undefined) {
progress.indeterminate = update.progress.indeterminate;
}
this.setState({ progress });
}
} else if (this.state.progress) {
this.setState({ progress: null });
}
} else if (update.command === 'bridgeStates') {
// all states at once
const nodeStates: { [uuid: string]: NodeStateResponse } = {};
if (update.states) {
Expand Down Expand Up @@ -420,6 +464,7 @@ class App extends GenericApp<GenericAppProps, AppState> {
this.setState({ nodeStates: _nodeStates });
}}
nodeStates={this.state.nodeStates}
themeName={this.state.themeName}
themeType={this.state.themeType}
theme={this.state.theme}
detectedDevices={this.state.detectedDevices}
Expand Down Expand Up @@ -454,6 +499,7 @@ class App extends GenericApp<GenericAppProps, AppState> {
nodeStates={this.state.nodeStates}
commissioning={this.state.commissioning?.devices || {}}
socket={this.socket}
themeName={this.state.themeName}
themeType={this.state.themeType}
theme={this.state.theme}
detectedDevices={this.state.detectedDevices}
Expand Down Expand Up @@ -538,6 +584,29 @@ class App extends GenericApp<GenericAppProps, AppState> {
}
}

renderProgressDialog(): React.JSX.Element | null {
if (!this.state.progress) {
return null;
}

return (
<Dialog
open={!0}
onClose={() => {}}
maxWidth="md"
>
{this.state.progress.title ? <DialogTitle>{getText(this.state.progress.title)}</DialogTitle> : null}
<DialogContent>
<LinearProgress
variant={this.state.progress.indeterminate ? 'indeterminate' : 'determinate'}
value={this.state.progress.value}
/>
{this.state.progress.text ? <DialogContentText>{getText(this.state.progress.text)}</DialogContentText> : null}
</DialogContent>
</Dialog>
);
}

render(): React.JSX.Element {
if (!this.state.ready) {
return (
Expand All @@ -553,6 +622,7 @@ class App extends GenericApp<GenericAppProps, AppState> {
<StyledEngineProvider injectFirst>
<ThemeProvider theme={this.state.theme}>
{this.renderToast()}
{this.renderProgressDialog()}
<div
className="App"
style={{
Expand Down
9 changes: 9 additions & 0 deletions src-admin/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,18 @@ export interface GUIMessage {
| 'updateStates'
| 'discoveredDevice'
| 'reconnect'
| 'progress'
| 'updateController';
states?: { [uuid: string]: NodeStateResponse };
device?: CommissionableDevice;

progress?: {
close?: boolean;
title?: string;
text?: string;
indeterminate?: boolean;
value?: number;
};
}

export interface CommissioningInfo {
Expand Down
22 changes: 18 additions & 4 deletions src/lib/DeviceManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,14 @@ class MatterAdapterDeviceManagement extends DeviceManagement<MatterAdapter> {
}
}

const progress = await context.openProgress(this.#adapter.t('Unpairing node...'), { label: '0%' });
await this.#adapter.sendToGui({
command: 'progress',
progress: {
title: this.#adapter.t('Unpairing node...'),
text: '0%',
value: 0,
},
});

// Start an interval that normally covers 30s and with each update the number gets slower increased for the percentage
let finished = false;
Expand All @@ -275,13 +282,20 @@ class MatterAdapterDeviceManagement extends DeviceManagement<MatterAdapter> {
const updateProgress = async (): Promise<void> => {
iteration++;
const progressValue = Math.min(99.9 * (1 - Math.exp(-iteration / (33 / 2))), 99.9); // Max 33 usually, scale factor 2
await progress.update({ value: progressValue, label: `${progressValue.toFixed(0)}%` });
await this.#adapter.sendToGui({
command: 'progress',
progress: {
value: progressValue,
text: `${progressValue.toFixed(0)}%`,
},
});
if (finished) {
return;
}
timeout = setTimeout(updateProgress, 1000);
};
timeout = setTimeout(updateProgress, 1000);
setTimeout(updateProgress, 1000);

let errorHappened = false;
try {
Expand All @@ -296,7 +310,7 @@ class MatterAdapterDeviceManagement extends DeviceManagement<MatterAdapter> {
if (timeout) {
clearTimeout(timeout);
}
await progress.close();
await this.#adapter.sendToGui({ command: 'progress' });
if (errorHappened) {
await context.showMessage(this.#adapter.t('Error happened during unpairing. Please check the log.'));
}
Expand Down Expand Up @@ -433,7 +447,7 @@ class MatterAdapterDeviceManagement extends DeviceManagement<MatterAdapter> {
): Promise<{ refresh: DeviceRefresh }> {
const obj = await this.adapter.getObjectAsync(baseId);

//const node = nodeOrDevice instanceof GeneralMatterNode ? nodeOrDevice : undefined;
// const node = nodeOrDevice instanceof GeneralMatterNode ? nodeOrDevice : undefined;
const device = nodeOrDevice instanceof GenericDeviceToIoBroker ? nodeOrDevice : undefined;

const items: Record<string, ConfigItemAny> = {
Expand Down
1 change: 1 addition & 0 deletions src/lib/i18n/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"The device should now identify itself for 30 seconds.": "Das Gerät sollte sich nun 30 Sekunden lang identifizieren.",
"The node is currently not connected. When you unpair it now you need to factory reset the node to commission again. Are you sure?": "Der Knoten ist derzeit nicht verbunden. Wenn Sie das Pairing jetzt aufheben, müssen Sie den Knoten auf die Werkseinstellungen zurücksetzen, um ihn wieder in Betrieb zu nehmen. Sind Sie sicher?",
"Unpair this node": "Diesen Knoten entkoppeln",
"Unpairing node...": "Knoten wird entkoppelt...",
"Use the following pairing code to commission the device": "Verwenden Sie den folgenden Pairing-Code, um das Gerät in Betrieb zu nehmen",
"Use the following pairing code to commission the device: %s": "Den folgenden Pairing-Code verwenden, um das Gerät in Betrieb zu nehmen: %s",
"Yes": "Ja",
Expand Down
1 change: 1 addition & 0 deletions src/lib/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"The device should now identify itself for 30 seconds.": "The device should now identify itself for 30 seconds.",
"The node is currently not connected. When you unpair it now you need to factory reset the node to commission again. Are you sure?": "The node is currently not connected. When you unpair it now you need to factory reset the node to commission again. Are you sure?",
"Unpair this node": "Unpair this node",
"Unpairing node...": "Unpairing node...",
"Use the following pairing code to commission the device": "Use the following pairing code to commission the device",
"Use the following pairing code to commission the device: %s": "Use the following pairing code to commission the device: %s",
"Yes": "Yes",
Expand Down
1 change: 1 addition & 0 deletions src/lib/i18n/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"The device should now identify itself for 30 seconds.": "El dispositivo ahora debería identificarse durante 30 segundos.",
"The node is currently not connected. When you unpair it now you need to factory reset the node to commission again. Are you sure?": "El nodo no está conectado actualmente. Cuando lo desemparejes ahora tendrás que restablecer de fábrica el nodo para volver a ponerlo en funcionamiento. ¿Está seguro?",
"Unpair this node": "Desemparejar este nodo",
"Unpairing node...": "Desvinculando nodo...",
"Use the following pairing code to commission the device": "Utilice el siguiente código de emparejamiento para poner en funcionamiento el dispositivo",
"Use the following pairing code to commission the device: %s": "Utilice el siguiente código de emparejamiento para poner en marcha el dispositivo: %s",
"Yes": "",
Expand Down
1 change: 1 addition & 0 deletions src/lib/i18n/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"The device should now identify itself for 30 seconds.": "L'appareil devrait maintenant s'identifier pendant 30 secondes.",
"The node is currently not connected. When you unpair it now you need to factory reset the node to commission again. Are you sure?": "Le nœud n'est actuellement pas connecté. Lorsque vous le désassemblez, vous devez réinitialiser le nœud pour qu'il soit à nouveau opérationnel. Êtes-vous sûr ?",
"Unpair this node": "Désappariement de ce nœud",
"Unpairing node...": "Nœud dissocié...",
"Use the following pairing code to commission the device": "Utilisez le code d'appairage suivant pour mettre en service l'appareil",
"Use the following pairing code to commission the device: %s": "Utilisez le code d'appairage suivant pour mettre l'appareil en service : %s",
"Yes": "Oui",
Expand Down
1 change: 1 addition & 0 deletions src/lib/i18n/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"The device should now identify itself for 30 seconds.": "Ora il dispositivo dovrebbe identificarsi per 30 secondi.",
"The node is currently not connected. When you unpair it now you need to factory reset the node to commission again. Are you sure?": "Il nodo non è attualmente collegato. Quando lo si disaccoppia, è necessario ripristinare le impostazioni di fabbrica del nodo per metterlo nuovamente in funzione. È sicuro?",
"Unpair this node": "Disaccoppiamento di questo nodo",
"Unpairing node...": "Disaccoppiamento del nodo in corso...",
"Use the following pairing code to commission the device": "Utilizzare il seguente codice di associazione per mettere in funzione il dispositivo",
"Use the following pairing code to commission the device: %s": "Utilizzare il seguente codice di accoppiamento per mettere in funzione il dispositivo: %s",
"Yes": "",
Expand Down
1 change: 1 addition & 0 deletions src/lib/i18n/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"The device should now identify itself for 30 seconds.": "Het apparaat zou zichzelf nu 30 seconden lang moeten identificeren.",
"The node is currently not connected. When you unpair it now you need to factory reset the node to commission again. Are you sure?": "De node is momenteel niet verbonden. Als je hem nu ontkoppelt, moet je de node een fabrieksreset geven om hem weer in gebruik te kunnen nemen. Weet je het zeker?",
"Unpair this node": "Ontkoppel dit knooppunt",
"Unpairing node...": "Knooppunt ontkoppelen...",
"Use the following pairing code to commission the device": "Gebruik de volgende koppelingscode om het apparaat in gebruik te nemen",
"Use the following pairing code to commission the device: %s": "Gebruik de volgende koppelcode om het apparaat in gebruik te nemen: %s",
"Yes": "Ja",
Expand Down
1 change: 1 addition & 0 deletions src/lib/i18n/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"The device should now identify itself for 30 seconds.": "Urządzenie powinno teraz identyfikować się przez 30 sekund.",
"The node is currently not connected. When you unpair it now you need to factory reset the node to commission again. Are you sure?": "Węzeł nie jest obecnie podłączony. Po rozparowaniu należy przywrócić ustawienia fabryczne, aby ponownie uruchomić węzeł. Czy na pewno?",
"Unpair this node": "Rozparuj ten węzeł",
"Unpairing node...": "Rozparowywanie węzła...",
"Use the following pairing code to commission the device": "Użyj poniższego kodu parowania, aby uruchomić urządzenie",
"Use the following pairing code to commission the device: %s": "Użyj następującego kodu parowania, aby uruchomić urządzenie: %s",
"Yes": "Tak",
Expand Down
1 change: 1 addition & 0 deletions src/lib/i18n/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"The device should now identify itself for 30 seconds.": "O dispositivo agora deve se identificar por 30 segundos.",
"The node is currently not connected. When you unpair it now you need to factory reset the node to commission again. Are you sure?": "O nó não está atualmente ligado. Quando o desemparelhar, terá de repor as predefinições do nó para o colocar novamente em funcionamento. Tem a certeza?",
"Unpair this node": "Desemparelhar este nó",
"Unpairing node...": "Desemparelhando nó...",
"Use the following pairing code to commission the device": "Use o seguinte código de pareamento para comissionar o dispositivo",
"Use the following pairing code to commission the device: %s": "Utilize o seguinte código de emparelhamento para ativar o dispositivo: %s",
"Yes": "Sim",
Expand Down
1 change: 1 addition & 0 deletions src/lib/i18n/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"The device should now identify itself for 30 seconds.": "Теперь устройство должно идентифицировать себя в течение 30 секунд.",
"The node is currently not connected. When you unpair it now you need to factory reset the node to commission again. Are you sure?": "В настоящее время узел не подключен. При снятии сопряжения необходимо выполнить заводской сброс узла, чтобы он снова начал работать. Вы уверены?",
"Unpair this node": "Отсоедините этот узел",
"Unpairing node...": "Отсоединение узла...",
"Use the following pairing code to commission the device": "Используйте следующий код сопряжения для ввода устройства в эксплуатацию.",
"Use the following pairing code to commission the device: %s": "Используйте следующий код сопряжения для ввода устройства в эксплуатацию: %s",
"Yes": "Да",
Expand Down
1 change: 1 addition & 0 deletions src/lib/i18n/uk.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"The device should now identify itself for 30 seconds.": "Тепер пристрій має ідентифікувати себе протягом 30 секунд.",
"The node is currently not connected. When you unpair it now you need to factory reset the node to commission again. Are you sure?": "Наразі вузол не підключено. Коли ви від'єднаєте його зараз, вам потрібно буде скинути до заводських налаштувань, щоб знову ввести вузол в експлуатацію. Ви впевнені?",
"Unpair this node": "Від'єднайте цей вузол від пари",
"Unpairing node...": "Відключення вузла...",
"Use the following pairing code to commission the device": "Використовуйте наведений нижче код сполучення, щоб ввести пристрій у дію",
"Use the following pairing code to commission the device: %s": "Для введення пристрою в експлуатацію використовуйте такий код сполучення: %s",
"Yes": "Так",
Expand Down
Loading

0 comments on commit 63aa230

Please sign in to comment.