Skip to content

Commit a8f8ef1

Browse files
committed
fix(*): Fixed connections and Style issues from last commit.
1 parent 73b6d70 commit a8f8ef1

5 files changed

Lines changed: 56 additions & 36 deletions

File tree

hassio/BarWidget.qml

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,24 @@ NIconButton {
1616

1717
property var main: pluginApi?.mainInstance ?? null
1818

19-
// "Connected" authenticated and live
20-
// "Disconnected" — was connected, now dropped (reconnecting)
21-
// "Connecting" — socket open but not yet authed (token present)
22-
// "Unconfigured" no token set, nothing to attempt
23-
// "AuthFailed" token rejected by HA
19+
// "Connected" - authenticated and live
20+
// "Connecting" - socket opening or authenticating (first attempt or after settings change)
21+
// "Disconnected" - dropped after a successful connection; reconnect backoff in progress
22+
// "Unconfigured" - no token set, nothing to attempt
23+
// "AuthFailed" - token rejected by HA
2424
readonly property string _status: {
2525
if (!root.main)
2626
return "Unconfigured";
2727
if (root.main.haToken === "")
2828
return "Unconfigured";
2929
if (root.main.authFailed)
3030
return "AuthFailed";
31-
if (!root.main.connected)
31+
if (root.main.authenticated)
32+
return "Connected";
33+
// Not yet authenticated - distinguish first-time connect from a drop-and-retry
34+
if (root.main.isReconnecting)
3235
return "Disconnected";
33-
if (!root.main.authenticated)
34-
return "Connecting";
35-
return "Connected";
36+
return "Connecting";
3637
}
3738

3839
readonly property string _statusLabel: {

hassio/BrowserView.qml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ Item {
133133
delegate: Rectangle {
134134
id: entityRow
135135
width: ListView.view.width
136-
height: Style.rowHeightM
136+
height: Math.round(56 * Style.uiScaleRatio)
137137
color: Color.mSurfaceVariant
138138
radius: Style.radiusM
139139

@@ -151,7 +151,7 @@ Item {
151151

152152
ColumnLayout {
153153
Layout.fillWidth: true
154-
spacing: Style.spacingXXS
154+
spacing: Style.marginXXS
155155

156156
NText {
157157
text: model.friendly_name

hassio/Main.qml

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import QtQuick
22
import QtWebSockets
3+
import qs.Commons
34

45
QtObject {
56
id: root
@@ -14,21 +15,22 @@ QtObject {
1415

1516
property ListModel entities: ListModel {}
1617

17-
// Fast entity_id → ListModel index lookup — rebuilt on every _populateEntities call
1818
property var _entityIndex: ({})
1919

20+
// True while a drop-and-retry cycle is in progress; cleared only on successful auth
21+
property bool isReconnecting: false
22+
2023
property int _msgId: 1
2124
property int _initialFetchId: -1
2225
property var _pendingCallbacks: ({})
23-
property string haUrl: pluginApi?.pluginSettings?.haUrl ?? ""
24-
property string haToken: pluginApi?.pluginSettings?.haToken ?? ""
26+
property string haUrl: ""
27+
property string haToken: ""
2528

2629
property int _reconnectAttempts: 0
2730
property int _reconnectBaseInterval: 5000
2831
property int _reconnectMaxInterval: 60000
2932

30-
onHaUrlChanged: _handleSettingsUpdate()
31-
onHaTokenChanged: _handleSettingsUpdate()
33+
Component.onCompleted: _loadSettings()
3234

3335
property WebSocket _socket: WebSocket {
3436
id: _socket
@@ -51,13 +53,15 @@ QtObject {
5153
root.connected = false;
5254
root.authenticated = false;
5355
if (!root.authFailed) {
56+
root.isReconnecting = true;
5457
root._scheduleReconnect();
5558
}
5659
} else if (status === WebSocket.Error) {
5760
Logger.e("HASS", "WebSocket error");
5861
root.connected = false;
5962
root.authenticated = false;
6063
if (!root.authFailed) {
64+
root.isReconnecting = true;
6165
root._scheduleReconnect();
6266
}
6367
}
@@ -73,12 +77,13 @@ QtObject {
7377
case "auth_ok":
7478
Logger.i("HASS", "Authenticated");
7579
root.authenticated = true;
80+
root.isReconnecting = false;
7681
root._resetReconnect();
7782
root._fetchStates();
7883
root._subscribeEvents();
7984
break;
8085
case "auth_invalid":
81-
Logger.e("HASS", "Auth failed check your token");
86+
Logger.e("HASS", "Auth failed - check your token");
8287
root.authenticated = false;
8388
root.authFailed = true;
8489
root._resetReconnect();
@@ -225,13 +230,21 @@ QtObject {
225230
}));
226231
}
227232

228-
function _handleSettingsUpdate() {
233+
function _loadSettings() {
234+
const url = pluginApi?.pluginSettings?.haUrl ?? "";
235+
const token = pluginApi?.pluginSettings?.haToken ?? "";
236+
// Only reconnect if values actually changed
237+
if (url === root.haUrl && token === root.haToken)
238+
return;
239+
root.haUrl = url;
240+
root.haToken = token;
229241
_settingsDebounce.restart();
230242
}
231243

232244
function reconnect() {
233245
Logger.i("HASS", "Manual reconnect initiated");
234246
root.authFailed = false;
247+
root.isReconnecting = false;
235248
root._resetReconnect();
236249
root.connected = false;
237250
root.authenticated = false;
@@ -279,12 +292,18 @@ QtObject {
279292
return modes.some(m => targets.includes(m));
280293
}
281294

295+
// Called from Settings.qml after the user saves
296+
function reloadSettings() {
297+
_loadSettings();
298+
}
299+
282300
property Timer _settingsDebounce: Timer {
283301
interval: 300
284302
repeat: false
285303
onTriggered: {
286304
Logger.i("HASS", "Settings changed, reconnecting...");
287305
root.authFailed = false;
306+
root.isReconnecting = false;
288307
root._resetReconnect();
289308
_socket.active = false;
290309
root.connected = false;

hassio/Panel.qml

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ Item {
3232
}
3333
spacing: Style.marginM
3434

35-
// ── Header ──────────────────────────────────────────────────────
35+
// Header
3636
RowLayout {
3737
Layout.fillWidth: true
3838
spacing: Style.marginS
@@ -59,8 +59,8 @@ Item {
5959

6060
// Connection indicator dot
6161
Rectangle {
62-
width: Style.iconSizeXS
63-
height: Style.iconSizeXS
62+
width: Style.marginS
63+
height: Style.marginS
6464
radius: width / 2
6565
color: {
6666
if (!root.main?.connected)
@@ -86,21 +86,21 @@ Item {
8686
Layout.fillWidth: true
8787
}
8888

89-
// ── List view ────────────────────────────────────────────────────
89+
// List view
9090
Item {
9191
Layout.fillWidth: true
9292
Layout.fillHeight: true
9393
visible: root.view === "list"
9494

95-
// Empty / error states shown only when there is nothing to list
95+
// Empty / error states - shown only when there is nothing to list
9696
ColumnLayout {
9797
anchors.centerIn: parent
9898
spacing: Style.marginM
9999
visible: !(root.main?.entities && root.main.entities.count > 0)
100100

101-
// Connection error
101+
// Connection error - only after a genuine drop, not during initial startup
102102
ColumnLayout {
103-
visible: !!(root.main && !root.main.connected && !root.main.authFailed && root.main.haToken !== "")
103+
visible: !!(root.main && !root.main.connected && !root.main.authFailed && root.main.haToken !== "" && root.main.isReconnecting)
104104
spacing: Style.marginM
105105

106106
NText {
@@ -159,7 +159,7 @@ Item {
159159
}
160160
}
161161

162-
// Entity list only when entities exist
162+
// Entity list - only when entities exist
163163
ListView {
164164
anchors.fill: parent
165165
clip: true
@@ -170,8 +170,7 @@ Item {
170170
delegate: Rectangle {
171171
id: entityDelegate
172172
width: ListView.view.width
173-
// Base row height + optional slider rows (each Style.rowHeightM tall)
174-
height: Style.rowHeightL + (showBrightness ? Style.rowHeightM : 0) + (showColorTemp ? Style.rowHeightM : 0)
173+
height: Math.round(64 * Style.uiScaleRatio) + (showBrightness ? Math.round(56 * Style.uiScaleRatio) : 0) + (showColorTemp ? Math.round(56 * Style.uiScaleRatio) : 0)
175174
color: Color.mSurfaceVariant
176175
radius: Style.radiusM
177176
clip: true
@@ -200,7 +199,7 @@ Item {
200199
}
201200
}
202201

203-
// Single fallback timer resets isWaiting if no state update arrives
202+
// Single fallback timer - resets isWaiting if no state update arrives
204203
Timer {
205204
id: waitingTimeout
206205
running: entityDelegate.isWaiting
@@ -243,7 +242,7 @@ Item {
243242

244243
ColumnLayout {
245244
Layout.fillWidth: true
246-
spacing: Style.spacingXS
245+
spacing: Style.marginXS
247246

248247
NText {
249248
text: model.friendly_name
@@ -352,7 +351,7 @@ Item {
352351
}
353352
}
354353

355-
// ── Brightness slider ────────────────────────────
354+
// Brightness slider
356355
RowLayout {
357356
Layout.fillWidth: true
358357
visible: entityDelegate.showBrightness
@@ -404,11 +403,11 @@ Item {
404403
text: Math.round((model.brightness > 0 ? model.brightness : 255) / 255 * 100) + "%"
405404
color: Color.mOnSurfaceVariant
406405
pointSize: Style.fontSizeS
407-
Layout.preferredWidth: Style.iconSizeL
406+
Layout.preferredWidth: Math.round(44 * Style.uiScaleRatio)
408407
}
409408
}
410409

411-
// ── Color temperature slider ──────────────────────
410+
// Color temperature slider
412411
RowLayout {
413412
Layout.fillWidth: true
414413
visible: entityDelegate.showColorTemp
@@ -460,15 +459,15 @@ Item {
460459
text: Math.round(1000000 / colorTempSlider.value) + "K"
461460
color: Color.mOnSurfaceVariant
462461
pointSize: Style.fontSizeS
463-
Layout.preferredWidth: Style.iconSizeL
462+
Layout.preferredWidth: Math.round(44 * Style.uiScaleRatio)
464463
}
465464
}
466465
}
467466
}
468467
}
469468
}
470469

471-
// ── Browser view ─────────────────────────────────────────────────
470+
// Browser view
472471
BrowserView {
473472
id: browserView
474473
Layout.fillWidth: true
@@ -482,7 +481,7 @@ Item {
482481
}
483482
}
484483

485-
// ── Domain helpers ────────────────────────────────────────────────────────
484+
// Domain helpers
486485

487486
function isControllable(domain) {
488487
return ["light", "switch", "input_boolean", "fan", "cover", "lock"].includes(domain);

hassio/Settings.qml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,6 @@ ColumnLayout {
3333
pluginApi.pluginSettings.haUrl = root.editUrl;
3434
pluginApi.pluginSettings.haToken = root.editToken;
3535
pluginApi.saveSettings();
36+
pluginApi.mainInstance.reloadSettings();
3637
}
3738
}

0 commit comments

Comments
 (0)