diff --git a/client/brewpi_gui.py b/client/brewpi_gui.py index 722d012..d577205 100755 --- a/client/brewpi_gui.py +++ b/client/brewpi_gui.py @@ -421,6 +421,7 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): self.sud_empty = True self.sud_state = None self.sud_user_message = None + self._confirm_box = None # Mirrors the server's TempController.enabled - gates the # temp/heatrate setpoint controls (see on_tempctrl_changed()). self.tc_enabled = False @@ -732,6 +733,7 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): self.sud_empty = True self.sud_state = None self.sud_user_message = None + self._close_confirm_dialog() self.tc_enabled = False self.checkbox_tc_enable.blockSignals(True) self.checkbox_tc_enable.setChecked(False) @@ -875,11 +877,23 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): self.msg_sud.send({'Stop': True}) def show_user_message(self, message): - # on_sud_changed() already runs on the GUI thread (via recv_signal), - # so this can show the dialog directly. The Sud is already blocked - # in WAIT_USER server-side; closing this dialog is what unblocks it. - QtWidgets.QMessageBox.information(self, "Sud", message) - self.msg_sud.send({'Confirm': True}) + if self._confirm_box is not None: + return + dlg = QtWidgets.QDialog(self) + dlg.setWindowTitle("Sud") + dlg.setWindowModality(QtCore.Qt.NonModal) + layout = QtWidgets.QVBoxLayout(dlg) + layout.addWidget(QtWidgets.QLabel(message)) + btn = QtWidgets.QPushButton("OK") + btn.clicked.connect(lambda: self.msg_sud.send({'Confirm': True})) + layout.addWidget(btn) + self._confirm_box = dlg + dlg.show() + + def _close_confirm_dialog(self): + if self._confirm_box is not None: + self._confirm_box.close() + self._confirm_box = None def on_action_sud_new(self): # Sends an empty schedule via the same Load path Load Sud uses, with @@ -1088,6 +1102,8 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): if self.sud_state == SUD_WAIT_USER_STATE and prev_state != SUD_WAIT_USER_STATE and self.sud_user_message: self.show_user_message(self.sud_user_message) + elif prev_state == SUD_WAIT_USER_STATE and self.sud_state != SUD_WAIT_USER_STATE: + self._close_confirm_dialog() self._update_step_plates() elif "UserMessage" in key: self.sud_user_message = msg['UserMessage'] diff --git a/web/app.js b/web/app.js index 4b729ae..062897e 100644 --- a/web/app.js +++ b/web/app.js @@ -483,6 +483,9 @@ function onSudChanged(msg) { sudState = newState; if (newState === WAIT_USER_STATE && prevState !== WAIT_USER_STATE && sudUserMessage) { showUserMessage(sudUserMessage); + } else if (prevState === WAIT_USER_STATE && newState !== WAIT_USER_STATE) { + const dlg = document.getElementById('sud-message-dialog'); + if (dlg.open) dlg.close(); } updateStepPlates(); updateSudActions(); @@ -678,7 +681,8 @@ document.getElementById('btn-sud-pause').addEventListener('click', () => { document.getElementById('btn-sud-stop').addEventListener('click', () => { sendMsg('Sud', {Stop: true}); }); -document.getElementById('sud-message-dialog').addEventListener('close', () => { +document.getElementById('sud-message-dialog').addEventListener('cancel', e => e.preventDefault()); +document.getElementById('sud-message-ok').addEventListener('click', () => { sendMsg('Sud', {Confirm: true}); }); diff --git a/web/index.html b/web/index.html index 1e29e38..f9fd52f 100644 --- a/web/index.html +++ b/web/index.html @@ -100,8 +100,8 @@

-
- + +
diff --git a/ws/client/ws_client.py b/ws/client/ws_client.py index 40876fa..5b8307b 100644 --- a/ws/client/ws_client.py +++ b/ws/client/ws_client.py @@ -17,7 +17,7 @@ class WsClient: def bg_run(self, uri): print("bg_run: started") asyncio.set_event_loop(self.loop) - fut = asyncio.ensure_future(self.run_client(uri), loop=self.loop) + fut = asyncio.ensure_future(self.run_client(uri)) self.loop.run_until_complete(fut) self.stop = None print("bg_run: terminated") @@ -38,7 +38,7 @@ class WsClient: async def run_client(self, uri): try: - websocket = await websockets.connect(uri, loop=self.loop) + websocket = await websockets.connect(uri) except Exception as exc: print(f"Failed to connect to {uri}: {exc}.") return @@ -47,8 +47,8 @@ class WsClient: await self.listener.on_connect() try: path = "/" - consumer_task = asyncio.ensure_future(self.handler_recv(websocket, path), loop=self.loop) - producer_task = asyncio.ensure_future(self.handler_send(websocket, path), loop=self.loop) + consumer_task = asyncio.ensure_future(self.handler_recv(websocket, path)) + producer_task = asyncio.ensure_future(self.handler_send(websocket, path)) done, pending = await asyncio.wait([consumer_task, producer_task, self.stop], return_when=asyncio.FIRST_COMPLETED,) for task in pending: task.cancel()