import QtQuick import qs.config import qs.services Item { id: root property bool expanded: false signal toggleExpanded readonly property bool hasSelection: HomeAssistant.selectedEntities.length > 0 readonly property bool showSetup: HomeAssistant.phase === "ready" && !root.hasSelection implicitHeight: content.implicitHeight Column { id: content width: parent.width spacing: 6 ControlSectionHeader { width: parent.width label: "Home" action: root.headerAction() actionEnabled: HomeAssistant.phase !== "loading" onActionTriggered: { if (root.hasSelection) { root.toggleExpanded(); } else if (root.showSetup) { root.openHomeSettings(); } else { HomeAssistant.refresh(); } } } Rectangle { id: restingCard width: parent.width height: visible ? restingGrid.implicitHeight + 20 : 0 visible: root.hasSelection && !root.expanded radius: Theme.cardRadius + 2 color: Theme.alpha(Theme.warn, 0.028) border.width: 1 border.color: Theme.alpha(Theme.warn, 0.095) Grid { id: restingGrid anchors.left: parent.left anchors.right: parent.right anchors.top: parent.top anchors.margins: 10 columns: 2 spacing: 8 Repeater { model: HomeAssistant.visibleEntities HomeTile { required property var modelData width: (restingGrid.width - restingGrid.spacing) / 2 entity: modelData busy: HomeAssistant.isBusy(modelData.id) pendingBrightness: HomeAssistant.pendingFor(modelData.id) actionError: HomeAssistant.errorFor(modelData.id) onPowerRequested: HomeAssistant.toggleEntity(modelData.id) onBrightnessRequested: value => HomeAssistant.setBrightness(modelData.id, value) } } } } Rectangle { width: parent.width height: visible ? 72 : 0 visible: !root.hasSelection radius: Theme.cardRadius color: root.showSetup ? Theme.alpha(Theme.accent, 0.055) : Theme.alpha(Theme.fg, 0.045) border.width: 1 border.color: root.showSetup ? Theme.alpha(Theme.accent, 0.12) : Theme.alpha(Theme.fg, 0.055) Text { id: stateIcon anchors.left: parent.left anchors.leftMargin: 13 anchors.verticalCenter: parent.verticalCenter text: root.showSetup ? "\u{F0335}" : "\u{F02DC}" color: root.showSetup ? Theme.accent : Theme.fgDim font.family: Theme.fontMono font.pixelSize: 17 } Column { anchors.left: stateIcon.right anchors.leftMargin: 11 anchors.right: emptyAction.left anchors.rightMargin: 10 anchors.verticalCenter: parent.verticalCenter spacing: 3 Text { width: parent.width text: root.emptyTitle() color: Theme.fg elide: Text.ElideRight font.family: Theme.fontFamily font.pixelSize: Theme.fontSize font.weight: Font.DemiBold } Text { width: parent.width text: root.emptyDetail() color: Theme.fgDim elide: Text.ElideRight font.family: Theme.fontFamily font.pixelSize: Theme.fontSizeSmall } } Rectangle { id: emptyAction anchors.right: parent.right anchors.rightMargin: 10 anchors.verticalCenter: parent.verticalCenter width: root.showSetup ? 68 : 52 height: 30 radius: 10 visible: HomeAssistant.phase !== "loading" color: emptyActionMouse.containsMouse ? Theme.alpha(Theme.accent, 0.20) : Theme.alpha(Theme.accent, 0.105) Text { anchors.centerIn: parent text: root.showSetup ? "Manage" : "Open" color: Theme.accent font.family: Theme.fontFamily font.pixelSize: Theme.fontSizeSmall font.weight: Font.DemiBold } MouseArea { id: emptyActionMouse anchors.fill: parent hoverEnabled: true cursorShape: Qt.PointingHandCursor onClicked: { if (root.showSetup) root.openHomeSettings(); else HomeAssistant.open(); } } } } Rectangle { width: parent.width height: visible ? 34 : 0 visible: HomeAssistant.stale radius: 10 color: Theme.alpha(Theme.warn, 0.075) Text { anchors.left: parent.left anchors.leftMargin: 11 anchors.verticalCenter: parent.verticalCenter text: "Last known state · " + root.countSummary() color: Theme.warn font.family: Theme.fontFamily font.pixelSize: Theme.fontSizeSmall } Text { anchors.right: parent.right anchors.rightMargin: 11 anchors.verticalCenter: parent.verticalCenter text: "Retry" color: Theme.accent font.family: Theme.fontFamily font.pixelSize: Theme.fontSizeSmall font.weight: Font.DemiBold MouseArea { anchors.fill: parent anchors.margins: -6 cursorShape: Qt.PointingHandCursor onClicked: HomeAssistant.refresh() } } } Section { width: parent.width expanded: root.expanded && root.hasSelection ScrollColumn { width: parent.width maxHeight: 324 spacing: 8 Grid { id: expandedGrid width: parent.width columns: 2 spacing: 8 Repeater { model: HomeAssistant.selectedEntities HomeTile { required property var modelData width: (expandedGrid.width - expandedGrid.spacing) / 2 entity: modelData busy: HomeAssistant.isBusy(modelData.id) pendingBrightness: HomeAssistant.pendingFor(modelData.id) actionError: HomeAssistant.errorFor(modelData.id) onPowerRequested: HomeAssistant.toggleEntity(modelData.id) onBrightnessRequested: value => HomeAssistant.setBrightness(modelData.id, value) } } } RowButton { width: parent.width icon: "preferences-system-symbolic" label: "Manage in Settings" sublabel: root.countSummary() onClicked: root.openHomeSettings() } } } } function headerAction(): string { if (root.hasSelection) { const noun = HomeAssistant.configuredCount === 1 ? "accessory" : "accessories"; return HomeAssistant.configuredCount + " " + noun + (root.expanded ? " ⌃" : " ›"); } if (HomeAssistant.phase === "loading") return "Loading"; if (root.showSetup) return "Manage"; return "Retry"; } function countSummary(): string { return HomeAssistant.configuredCount + " selected · " + HomeAssistant.discoveredCount + " discovered"; } function emptyTitle(): string { if (root.showSetup) return "Choose your accessories"; if (HomeAssistant.phase === "loading") return "Loading your home"; if (HomeAssistant.lastError === "authentication-required") return "Authentication required"; if (HomeAssistant.lastError === "not-configured") return "Home Assistant is not configured"; return "Home Assistant is unavailable"; } function emptyDetail(): string { if (root.showSetup) { if (HomeAssistant.discoveredCount === 0) return "No lights discovered yet"; const noun = HomeAssistant.discoveredCount === 1 ? "light" : "lights"; return HomeAssistant.discoveredCount + " " + noun + " ready to add"; } if (HomeAssistant.phase === "loading") return "Finding your selected lights"; if (HomeAssistant.lastError === "authentication-required") return "Update the long-lived access token"; if (HomeAssistant.lastError === "not-configured") return "Connect Home Assistant in Settings"; return "Check the connection, then retry"; } function openHomeSettings(): void { ShellState.close(); ShellState.openSettings("home-phone"); } }