better controls

acca0da · gmorell · 2025-06-23 22:05

6 files +422 -27

Files changed

modified contents/ui/EntityControl.qml
+345 −16
@@ -3,6 +3,7 @@ import QtQuick.Controls as QQC2
3 3 import QtQuick.Layouts
4 4 import org.kde.plasma.components as PlasmaComponents3
5 5 import org.kde.kirigami as Kirigami
6 +import org.kde.plasma.core as PlasmaCore
6 7
7 8 Item {
8 9 id: entityControl
@@ -15,8 +16,30 @@ Item {
15 16 property string buttonSize: "medium"
16 17 property var entityState: null
17 18 property bool isOn: entityState ? (entityState.state === "on" || entityState.state === "home" || entityState.state === "open") : false
19 + property bool isLoadingState: false
20 + property bool hasValidState: entityState !== null && entityState !== undefined
21 + property bool showExpandedControls: false
22 +
23 + // Light-specific properties
24 + readonly property bool isLight: entityId.split('.')[0] === 'light'
25 + readonly property bool supportsRgb: entityState && entityState.attributes && entityState.attributes.supported_color_modes &&
26 + (entityState.attributes.supported_color_modes.indexOf('rgb') !== -1 ||
27 + entityState.attributes.supported_color_modes.indexOf('rgbw') !== -1 ||
28 + entityState.attributes.supported_color_modes.indexOf('rgbww') !== -1)
29 + readonly property bool supportsCct: entityState && entityState.attributes && entityState.attributes.supported_color_modes &&
30 + (entityState.attributes.supported_color_modes.indexOf('color_temp') !== -1)
31 + readonly property bool supportsBrightness: entityState && entityState.attributes && entityState.attributes.supported_color_modes &&
32 + (entityState.attributes.supported_color_modes.indexOf('brightness') !== -1 ||
33 + entityState.attributes.brightness !== undefined)
34 + readonly property int currentBrightness: entityState && entityState.attributes && entityState.attributes.brightness ?
35 + Math.round(entityState.attributes.brightness / 255 * 100) : 0
36 + readonly property var currentRgbColor: entityState && entityState.attributes && entityState.attributes.rgb_color ?
37 + entityState.attributes.rgb_color : [255, 255, 255]
38 + readonly property int currentColorTemp: entityState && entityState.attributes && entityState.attributes.color_temp ?
39 + entityState.attributes.color_temp : 370
18 40
19 41 signal controlActivated(string entityId, string action, var data)
42 + signal stateRequested(string entityId)
20 43
21 44 readonly property int buttonSizePixels: {
22 45 switch (buttonSize) {
@@ -26,8 +49,12 @@ Item {
26 49 }
27 50 }
28 51
29 − width: buttonSizePixels + (showLabel ? Kirigami.Units.smallSpacing : 0)
30 − height: buttonSizePixels + (showLabel ? Kirigami.Units.gridUnit : 0)
52 + readonly property bool hasExpandedControls: isLight && controlType === "light" && showExpandedControls && (supportsRgb || supportsCct || supportsBrightness)
53 +
54 + width: hasExpandedControls ? Math.max(buttonSizePixels * 4, Kirigami.Units.gridUnit * 8) :
55 + buttonSizePixels + (showLabel ? Kirigami.Units.smallSpacing : 0)
56 + height: hasExpandedControls ? buttonSizePixels + Kirigami.Units.gridUnit * 10 + (showLabel ? Kirigami.Units.gridUnit : 0) :
57 + buttonSizePixels + (showLabel ? Kirigami.Units.gridUnit : 0)
31 58
32 59 ColumnLayout {
33 60 anchors.fill: parent
@@ -42,7 +69,7 @@ Item {
42 69
43 70 // Visual state based on entity state
44 71 property color normalColor: Kirigami.Theme.buttonBackgroundColor
45 − property color activeColor: isOn ? Kirigami.Theme.positiveBackgroundColor : normalColor
72 + property color activeColor: isOn ? (supportsRgb ? Qt.rgba(currentRgbColor[0]/255, currentRgbColor[1]/255, currentRgbColor[2]/255, 0.3) : Kirigami.Theme.positiveBackgroundColor) : normalColor
46 73
47 74 background: Rectangle {
48 75 radius: Kirigami.Units.cornerRadius
@@ -55,13 +82,41 @@ Item {
55 82
56 83 Behavior on color { ColorAnimation { duration: 150 } }
57 84 Behavior on border.color { ColorAnimation { duration: 150 } }
85 +
86 + // Advanced controls indicator for lights
87 + Rectangle {
88 + visible: isLight && controlType === "light" && (supportsRgb || supportsCct || supportsBrightness)
89 + anchors.top: parent.top
90 + anchors.right: parent.right
91 + anchors.margins: 2
92 + width: 6
93 + height: 6
94 + radius: 3
95 + color: showExpandedControls ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.disabledTextColor
96 +
97 + Behavior on color { ColorAnimation { duration: 150 } }
98 + }
58 99 }
59 100
60 − contentItem: Kirigami.Icon {
61 − source: getIconName()
62 − color: isOn ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.textColor
101 + contentItem: RowLayout {
102 + spacing: 0
63 103
64 − Behavior on color { ColorAnimation { duration: 150 } }
104 + Kirigami.Icon {
105 + source: getIconName()
106 + color: isOn ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.textColor
107 + Layout.fillWidth: true
108 + Layout.fillHeight: true
109 +
110 + Behavior on color { ColorAnimation { duration: 150 } }
111 + }
112 +
113 + // Loading indicator
114 + PlasmaComponents3.BusyIndicator {
115 + visible: isLoadingState
116 + Layout.preferredWidth: Kirigami.Units.iconSizes.small
117 + Layout.preferredHeight: Kirigami.Units.iconSizes.small
118 + Layout.alignment: Qt.AlignCenter
119 + }
65 120 }
66 121
67 122 PlasmaComponents3.ToolTip {
@@ -69,6 +124,17 @@ Item {
69 124 }
70 125
71 126 onClicked: handleControlClick()
127 +
128 + // Right-click to toggle expanded controls for lights
129 + MouseArea {
130 + anchors.fill: parent
131 + acceptedButtons: Qt.RightButton
132 + onClicked: {
133 + if (isLight && controlType === "light" && (supportsRgb || supportsCct || supportsBrightness)) {
134 + showExpandedControls = !showExpandedControls
135 + }
136 + }
137 + }
72 138 }
73 139
74 140 // Entity label
@@ -84,6 +150,212 @@ Item {
84 150
85 151 Behavior on color { ColorAnimation { duration: 150 } }
86 152 }
153 +
154 + // Expanded Light Controls
155 + Rectangle {
156 + visible: hasExpandedControls
157 + Layout.fillWidth: true
158 + Layout.preferredHeight: Kirigami.Units.gridUnit * 7
159 + color: Kirigami.Theme.backgroundColor
160 + border.color: Kirigami.Theme.separatorColor
161 + border.width: 1
162 + radius: Kirigami.Units.cornerRadius
163 +
164 + ColumnLayout {
165 + anchors.fill: parent
166 + anchors.margins: Kirigami.Units.smallSpacing
167 + spacing: Kirigami.Units.smallSpacing
168 +
169 + // Brightness Control
170 + RowLayout {
171 + visible: supportsBrightness && isOn
172 + Layout.fillWidth: true
173 + Layout.preferredHeight: Kirigami.Units.gridUnit * 1.2
174 +
175 + Kirigami.Icon {
176 + source: "brightness-low"
177 + Layout.preferredWidth: Kirigami.Units.iconSizes.small
178 + Layout.preferredHeight: Kirigami.Units.iconSizes.small
179 + }
180 +
181 + QQC2.Slider {
182 + id: brightnessSlider
183 + Layout.fillWidth: true
184 + Layout.preferredHeight: Kirigami.Units.gridUnit * 1.2
185 + from: 1
186 + to: 100
187 + value: currentBrightness
188 + stepSize: 1
189 +
190 + onMoved: {
191 + // Send brightness command on slider move
192 + var brightnessValue = Math.round(value * 255 / 100)
193 + controlActivated(entityId, "turn_on", { brightness: brightnessValue })
194 + }
195 +
196 + background: Rectangle {
197 + x: brightnessSlider.leftPadding
198 + y: brightnessSlider.topPadding + brightnessSlider.availableHeight / 2 - height / 2
199 + implicitWidth: 200
200 + implicitHeight: 8
201 + width: brightnessSlider.availableWidth
202 + height: implicitHeight
203 + radius: 4
204 + color: Kirigami.Theme.backgroundColor
205 + border.color: Kirigami.Theme.separatorColor
206 +
207 + Rectangle {
208 + width: brightnessSlider.visualPosition * parent.width
209 + height: parent.height
210 + color: Kirigami.Theme.highlightColor
211 + radius: 4
212 + }
213 + }
214 +
215 + handle: Rectangle {
216 + x: brightnessSlider.leftPadding + brightnessSlider.visualPosition * (brightnessSlider.availableWidth - width)
217 + y: brightnessSlider.topPadding + brightnessSlider.availableHeight / 2 - height / 2
218 + implicitWidth: 20
219 + implicitHeight: 20
220 + radius: 10
221 + color: brightnessSlider.pressed ? Qt.darker(Kirigami.Theme.highlightColor, 1.1) : Kirigami.Theme.highlightColor
222 + border.color: Kirigami.Theme.backgroundColor
223 + border.width: 2
224 + }
225 + }
226 +
227 + PlasmaComponents3.Label {
228 + text: currentBrightness + "%"
229 + font.pointSize: Kirigami.Theme.smallFont.pointSize
230 + Layout.preferredWidth: Kirigami.Units.gridUnit * 1.5
231 + }
232 + }
233 +
234 + // Color Temperature Control
235 + RowLayout {
236 + visible: supportsCct && isOn // Show alongside RGB controls
237 + Layout.fillWidth: true
238 + Layout.preferredHeight: Kirigami.Units.gridUnit * 1.2
239 +
240 + Kirigami.Icon {
241 + source: "weather-clear-night"
242 + Layout.preferredWidth: Kirigami.Units.iconSizes.small
243 + Layout.preferredHeight: Kirigami.Units.iconSizes.small
244 + }
245 +
246 + QQC2.Slider {
247 + id: colorTempSlider
248 + Layout.fillWidth: true
249 + Layout.preferredHeight: Kirigami.Units.gridUnit * 1.2
250 + from: 153 // ~6500K (cool)
251 + to: 500 // ~2000K (warm)
252 + value: currentColorTemp
253 + stepSize: 1
254 +
255 + onMoved: {
256 + controlActivated(entityId, "turn_on", { color_temp: Math.round(value) })
257 + }
258 +
259 + background: Rectangle {
260 + x: colorTempSlider.leftPadding
261 + y: colorTempSlider.topPadding + colorTempSlider.availableHeight / 2 - height / 2
262 + implicitWidth: 200
263 + implicitHeight: 8
264 + width: colorTempSlider.availableWidth
265 + height: implicitHeight
266 + radius: 4
267 +
268 + gradient: Gradient {
269 + orientation: Gradient.Horizontal
270 + GradientStop { position: 0.0; color: "#87CEEB" } // Cool blue
271 + GradientStop { position: 1.0; color: "#FFA500" } // Warm orange
272 + }
273 +
274 + border.color: Kirigami.Theme.separatorColor
275 + border.width: 1
276 + }
277 +
278 + handle: Rectangle {
279 + x: colorTempSlider.leftPadding + colorTempSlider.visualPosition * (colorTempSlider.availableWidth - width)
280 + y: colorTempSlider.topPadding + colorTempSlider.availableHeight / 2 - height / 2
281 + implicitWidth: 20
282 + implicitHeight: 20
283 + radius: 10
284 + color: colorTempSlider.pressed ? Qt.darker(Kirigami.Theme.highlightColor, 1.1) : Kirigami.Theme.highlightColor
285 + border.color: Kirigami.Theme.backgroundColor
286 + border.width: 2
287 + }
288 + }
289 +
290 + PlasmaComponents3.Label {
291 + text: Math.round(1000000 / currentColorTemp) + "K"
292 + font.pointSize: Kirigami.Theme.smallFont.pointSize
293 + Layout.preferredWidth: Kirigami.Units.gridUnit * 1.5
294 + }
295 + }
296 +
297 + // RGB Color Control
298 + RowLayout {
299 + visible: supportsRgb && isOn
300 + Layout.fillWidth: true
301 + Layout.preferredHeight: Kirigami.Units.gridUnit * 1.5
302 + spacing: Kirigami.Units.smallSpacing
303 +
304 + // Color preset buttons
305 + Repeater {
306 + model: [
307 + { color: "#FF0000", name: "Red" },
308 + { color: "#00FF00", name: "Green" },
309 + { color: "#0000FF", name: "Blue" },
310 + { color: "#FFFF00", name: "Yellow" },
311 + { color: "#FF00FF", name: "Magenta" },
312 + { color: "#00FFFF", name: "Cyan" },
313 + { color: "#FFFFFF", name: "White" }
314 + ]
315 +
316 + PlasmaComponents3.Button {
317 + Layout.preferredWidth: Kirigami.Units.gridUnit * 1.2
318 + Layout.preferredHeight: Kirigami.Units.gridUnit * 1.2
319 +
320 + background: Rectangle {
321 + radius: Kirigami.Units.cornerRadius
322 + color: modelData.color
323 + border.color: Qt.rgba(currentRgbColor[0]/255, currentRgbColor[1]/255, currentRgbColor[2]/255, 1.0) === color ?
324 + Kirigami.Theme.highlightColor : Kirigami.Theme.separatorColor
325 + border.width: Qt.rgba(currentRgbColor[0]/255, currentRgbColor[1]/255, currentRgbColor[2]/255, 1.0) === color ? 2 : 1
326 + }
327 +
328 + PlasmaComponents3.ToolTip {
329 + text: modelData.name
330 + }
331 +
332 + onClicked: {
333 + var rgb = hexToRgb(modelData.color)
334 + controlActivated(entityId, "turn_on", { rgb_color: [rgb.r, rgb.g, rgb.b] })
335 + }
336 + }
337 + }
338 + }
339 +
340 + // Current color indicator
341 + Rectangle {
342 + visible: supportsRgb && isOn
343 + Layout.fillWidth: true
344 + Layout.preferredHeight: Kirigami.Units.gridUnit * 0.8
345 + radius: Kirigami.Units.cornerRadius
346 + color: Qt.rgba(currentRgbColor[0]/255, currentRgbColor[1]/255, currentRgbColor[2]/255, 1.0)
347 + border.color: Kirigami.Theme.separatorColor
348 + border.width: 1
349 +
350 + PlasmaComponents3.Label {
351 + anchors.centerIn: parent
352 + text: "RGB: " + currentRgbColor[0] + ", " + currentRgbColor[1] + ", " + currentRgbColor[2]
353 + font.pointSize: Kirigami.Theme.smallFont.pointSize
354 + color: (currentRgbColor[0] + currentRgbColor[1] + currentRgbColor[2]) > 384 ? "black" : "white"
355 + }
356 + }
357 + }
358 + }
87 359 }
88 360
89 361 function getIconName() {
@@ -116,21 +388,61 @@ Item {
116 388 }
117 389
118 390 function getTooltipText() {
119 − var stateText = entityState ? entityState.state : "unknown"
120 − var tooltip = displayName + "\nState: " + stateText
391 + var tooltip = displayName
121 392
122 − if (entityState && entityState.attributes) {
123 − if (entityState.attributes.friendly_name) {
124 − tooltip = entityState.attributes.friendly_name + "\nState: " + stateText
125 − }
126 −
127 − // Add additional info for specific entity types
393 + if (isLoadingState) {
394 + tooltip += "\nState: Loading..."
395 + return tooltip
396 + }
397 +
398 + if (!hasValidState) {
399 + tooltip += "\nState: Unavailable"
400 + tooltip += "\nClick to refresh"
401 + return tooltip
402 + }
403 +
404 + var stateText = entityState.state || "unknown"
405 +
406 + // Use friendly name if available
407 + if (entityState.attributes && entityState.attributes.friendly_name) {
408 + tooltip = entityState.attributes.friendly_name
409 + }
410 +
411 + tooltip += "\nState: " + stateText
412 +
413 + // Add additional info for specific entity types
414 + if (entityState.attributes) {
128 415 if (entityState.attributes.brightness) {
129 416 tooltip += "\nBrightness: " + Math.round(entityState.attributes.brightness / 255 * 100) + "%"
130 417 }
418 + if (entityState.attributes.rgb_color) {
419 + tooltip += "\nRGB: " + entityState.attributes.rgb_color.join(", ")
420 + }
421 + if (entityState.attributes.color_temp) {
422 + tooltip += "\nColor Temp: " + Math.round(1000000 / entityState.attributes.color_temp) + "K"
423 + }
424 + if (entityState.attributes.supported_color_modes && isLight) {
425 + tooltip += "\nSupported: " + entityState.attributes.supported_color_modes.join(", ")
426 + }
131 427 if (entityState.attributes.temperature) {
132 428 tooltip += "\nTemperature: " + entityState.attributes.temperature + "°"
133 429 }
430 + if (entityState.attributes.humidity) {
431 + tooltip += "\nHumidity: " + entityState.attributes.humidity + "%"
432 + }
433 + if (entityState.attributes.battery_level) {
434 + tooltip += "\nBattery: " + entityState.attributes.battery_level + "%"
435 + }
436 + // Add last updated time
437 + if (entityState.last_updated) {
438 + var lastUpdated = new Date(entityState.last_updated)
439 + tooltip += "\nLast updated: " + lastUpdated.toLocaleTimeString()
440 + }
441 + }
442 +
443 + // Add instruction for light controls
444 + if (isLight && controlType === "light" && (supportsRgb || supportsCct || supportsBrightness)) {
445 + tooltip += "\n\nRight-click for advanced controls"
134 446 }
135 447
136 448 return tooltip
@@ -149,11 +461,28 @@ Item {
149 461 controlActivated(entityId, "toggle", {})
150 462 break
151 463 case "status":
152 − // Status displays don't perform actions, just show state
464 + // Status displays don't perform actions, just refresh state
465 + stateRequested(entityId)
153 466 break
154 467 default:
155 468 controlActivated(entityId, "toggle", {})
156 469 break
157 470 }
471 +
472 + // Always try to refresh state after any action (or for status entities)
473 + if (controlType !== "status") {
474 + Qt.callLater(function() {
475 + stateRequested(entityId)
476 + })
477 + }
478 + }
479 +
480 + function hexToRgb(hex) {
481 + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
482 + return result ? {
483 + r: parseInt(result[1], 16),
484 + g: parseInt(result[2], 16),
485 + b: parseInt(result[3], 16)
486 + } : null;
158 487 }
159 488 }
modified contents/ui/HomeAssistantAPI.qml
+43 −2
@@ -59,6 +59,7 @@ QtObject {
59 59 function getState(entityId, callback) {
60 60 if (!baseUrl || !accessToken) {
61 61 error("Home Assistant URL and access token must be configured")
62 + if (callback) callback(false, null)
62 63 return
63 64 }
64 65
@@ -77,16 +78,39 @@ QtObject {
77 78 stateChanged(entityId, state)
78 79 if (callback) callback(true, state)
79 80 } catch (e) {
80 − console.log("Error parsing state response:", e)
81 + console.log("Error parsing state response for", entityId, ":", e)
82 + error("Failed to parse state response for " + entityId)
81 83 if (callback) callback(false, null)
82 84 }
85 + } else if (xhr.status === 404) {
86 + console.log("Entity not found:", entityId)
87 + error("Entity not found: " + entityId)
88 + if (callback) callback(false, null)
89 + } else if (xhr.status === 401) {
90 + console.log("Authentication failed - check access token")
91 + error("Authentication failed - check access token")
92 + if (callback) callback(false, null)
83 93 } else {
84 − console.log("Failed to get state for", entityId, ":", xhr.status)
94 + console.log("Failed to get state for", entityId, ":", xhr.status, xhr.responseText)
95 + error("Failed to get state for " + entityId + ": " + xhr.status)
85 96 if (callback) callback(false, null)
86 97 }
87 98 }
88 99 }
89 100
101 + xhr.onerror = function() {
102 + console.log("Network error getting state for", entityId)
103 + error("Network error getting state for " + entityId)
104 + if (callback) callback(false, null)
105 + }
106 +
107 + xhr.ontimeout = function() {
108 + console.log("Timeout getting state for", entityId)
109 + error("Timeout getting state for " + entityId)
110 + if (callback) callback(false, null)
111 + }
112 +
113 + xhr.timeout = 10000 // 10 second timeout
90 114 xhr.send()
91 115 }
92 116
@@ -250,4 +274,21 @@ QtObject {
250 274 var domain = entityId.split('.')[0]
251 275 callService(domain, 'turn_off', entityId)
252 276 }
277 +
278 + // Enhanced light control functions
279 + function setLightBrightness(entityId, brightness) {
280 + callService('light', 'turn_on', entityId, { brightness: brightness })
281 + }
282 +
283 + function setLightColor(entityId, rgbColor) {
284 + callService('light', 'turn_on', entityId, { rgb_color: rgbColor })
285 + }
286 +
287 + function setLightColorTemp(entityId, colorTemp) {
288 + callService('light', 'turn_on', entityId, { color_temp: colorTemp })
289 + }
290 +
291 + function setLightAdvanced(entityId, serviceData) {
292 + callService('light', 'turn_on', entityId, serviceData)
293 + }
253 294 }
modified contents/ui/configEntities.qml
+6 −0
@@ -90,6 +90,7 @@ KCM.SimpleKCM {
90 90 entityBrowser.editText = ""
91 91 entityBrowser.selectedEntityId = ""
92 92 entityBrowser.selectedEntityName = ""
93 + entityBrowser.selectedEntity = null
93 94 newEntityIdField.text = ""
94 95 newEntityNameField.text = ""
95 96 newEntityIconField.text = ""
@@ -234,6 +235,8 @@ KCM.SimpleKCM {
234 235 Layout.fillWidth: true
235 236
236 237 onEntitySelected: function(entity) {
238 + // Fill the entity ID field
239 + newEntityIdField.text = entity.entity_id
237 240 newEntityNameField.text = entity.friendly_name
238 241 newEntityIconField.text = entity.icon ? entity.icon.replace("mdi:", "") : ""
239 242
@@ -277,8 +280,11 @@ KCM.SimpleKCM {
277 280
278 281 onTextChanged: {
279 282 if (text.trim()) {
283 + // Clear entity browser selection when manually typing
280 284 entityBrowser.editText = ""
281 285 entityBrowser.selectedEntityId = text.trim()
286 + entityBrowser.selectedEntityName = ""
287 + entityBrowser.selectedEntity = null
282 288 }
283 289 }
284 290 }
modified contents/ui/main.qml
+28 −9
@@ -28,6 +28,7 @@ PlasmoidItem {
28 28 property string buttonSize: plasmoid.configuration.buttonSize
29 29
30 30 property var configuredEntities: []
31 + property var entityStates: ({}) // Store entity states here
31 32 property bool hasValidConfig: homeAssistantUrl && accessToken
32 33 property bool hasEntities: configuredEntities.length > 0
33 34
@@ -62,14 +63,13 @@ PlasmoidItem {
62 63 accessToken: root.accessToken
63 64
64 65 onStateChanged: function(entityId, state) {
65 − // Update the entity state in the grid
66 − for (var i = 0; i < entityGrid.children.length; i++) {
67 − var control = entityGrid.children[i]
68 − if (control.entityId === entityId) {
69 − control.entityState = state
70 − break
71 − }
72 − }
66 + // Store the state in our central state store
67 + var newStates = root.entityStates
68 + newStates[entityId] = state
69 + root.entityStates = newStates
70 +
71 + // Trigger a change notification
72 + root.entityStatesChanged()
73 73 }
74 74
75 75 onError: function(message) {
@@ -165,6 +165,7 @@ PlasmoidItem {
165 165 iconName: modelData.icon || "home-assistant"
166 166 showLabel: root.showEntityLabels
167 167 buttonSize: root.buttonSize
168 + entityState: root.entityStates[entityId] || null
168 169
169 170 onControlActivated: function(entityId, action, data) {
170 171 switch (action) {
@@ -185,9 +186,27 @@ PlasmoidItem {
185 186 })
186 187 }
187 188
189 + onStateRequested: function(entityId) {
190 + if (root.hasValidConfig) {
191 + isLoadingState = true
192 + homeAssistantAPI.getState(entityId, function(success, state) {
193 + isLoadingState = false
194 + if (!success) {
195 + console.log("Failed to refresh state for:", entityId)
196 + }
197 + })
198 + }
199 + }
200 +
188 201 Component.onCompleted: {
189 202 if (root.hasValidConfig) {
190 − homeAssistantAPI.getState(entityId)
203 + isLoadingState = true
204 + homeAssistantAPI.getState(entityId, function(success, state) {
205 + isLoadingState = false
206 + if (!success) {
207 + console.log("Failed to get initial state for:", entityId)
208 + }
209 + })
191 210 }
192 211 }
193 212 }

Parents: 05507c6