Build the Home accessory shelf
This commit is contained in:
@@ -8,6 +8,9 @@ Item {
|
||||
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 {
|
||||
@@ -18,46 +21,50 @@ Item {
|
||||
ControlSectionHeader {
|
||||
width: parent.width
|
||||
label: "Home"
|
||||
action: HomeAssistant.entities.length > 0
|
||||
? HomeAssistant.entities.length + " accessories " + (root.expanded ? "⌃" : "›")
|
||||
: "Retry"
|
||||
action: root.headerAction()
|
||||
actionEnabled: HomeAssistant.phase !== "loading"
|
||||
onActionTriggered: {
|
||||
if (HomeAssistant.entities.length > 0)
|
||||
if (root.hasSelection) {
|
||||
root.toggleExpanded();
|
||||
else
|
||||
} else if (root.showSetup) {
|
||||
root.openHomeSettings();
|
||||
} else {
|
||||
HomeAssistant.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: homeCard
|
||||
id: restingCard
|
||||
width: parent.width
|
||||
height: visible ? homeGrid.implicitHeight + 20 : 0
|
||||
visible: HomeAssistant.entities.length > 0
|
||||
height: visible ? restingGrid.implicitHeight + 20 : 0
|
||||
visible: root.hasSelection && !root.expanded
|
||||
radius: Theme.cardRadius + 2
|
||||
color: Theme.alpha(Theme.accent, 0.045)
|
||||
color: Theme.alpha(Theme.warn, 0.028)
|
||||
border.width: 1
|
||||
border.color: Theme.alpha(Theme.accent, 0.12)
|
||||
border.color: Theme.alpha(Theme.warn, 0.095)
|
||||
|
||||
Grid {
|
||||
id: homeGrid
|
||||
id: restingGrid
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.margins: 10
|
||||
columns: 4
|
||||
spacing: 7
|
||||
columns: 2
|
||||
spacing: 8
|
||||
|
||||
Repeater {
|
||||
model: HomeAssistant.visibleEntities
|
||||
|
||||
HomeTile {
|
||||
required property var modelData
|
||||
width: (homeGrid.width - homeGrid.spacing * 3) / 4
|
||||
width: (restingGrid.width - restingGrid.spacing) / 2
|
||||
entity: modelData
|
||||
busy: HomeAssistant.busyEntityId === modelData.id
|
||||
onActivated: HomeAssistant.toggleEntity(modelData.id)
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,28 +72,32 @@ Item {
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: visible ? 66 : 0
|
||||
visible: HomeAssistant.entities.length === 0
|
||||
height: visible ? 72 : 0
|
||||
visible: !root.hasSelection
|
||||
radius: Theme.cardRadius
|
||||
color: Theme.alpha(Theme.fg, 0.05)
|
||||
color: root.showSetup
|
||||
? Theme.alpha(Theme.accent, 0.055)
|
||||
: Theme.alpha(Theme.fg, 0.045)
|
||||
border.width: 1
|
||||
border.color: Theme.alpha(Theme.fg, 0.045)
|
||||
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: 12
|
||||
anchors.leftMargin: 13
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: HomeAssistant.phase === "loading" ? "\u{F0772}" : "\u{F02DC}"
|
||||
color: HomeAssistant.phase === "loading" ? Theme.accent : Theme.fgDim
|
||||
text: root.showSetup ? "\u{F0335}" : "\u{F02DC}"
|
||||
color: root.showSetup ? Theme.accent : Theme.fgDim
|
||||
font.family: Theme.fontMono
|
||||
font.pixelSize: 16
|
||||
font.pixelSize: 17
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.left: stateIcon.right
|
||||
anchors.leftMargin: 11
|
||||
anchors.right: openHome.left
|
||||
anchors.right: emptyAction.left
|
||||
anchors.rightMargin: 10
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: 3
|
||||
@@ -111,61 +122,66 @@ Item {
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: openHome
|
||||
id: emptyAction
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 10
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 48
|
||||
height: 28
|
||||
radius: 9
|
||||
width: root.showSetup ? 68 : 52
|
||||
height: 30
|
||||
radius: 10
|
||||
visible: HomeAssistant.phase !== "loading"
|
||||
color: openMouse.containsMouse
|
||||
color: emptyActionMouse.containsMouse
|
||||
? Theme.alpha(Theme.accent, 0.20)
|
||||
: Theme.alpha(Theme.accent, 0.11)
|
||||
: Theme.alpha(Theme.accent, 0.105)
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "Open"
|
||||
text: root.showSetup ? "Manage" : "Open"
|
||||
color: Theme.accent
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
font.weight: Font.DemiBold
|
||||
}
|
||||
MouseArea {
|
||||
id: openMouse
|
||||
id: emptyActionMouse
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: HomeAssistant.open()
|
||||
onClicked: {
|
||||
if (root.showSetup)
|
||||
root.openHomeSettings();
|
||||
else
|
||||
HomeAssistant.open();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: visible ? 30 : 0
|
||||
height: visible ? 34 : 0
|
||||
visible: HomeAssistant.stale
|
||||
radius: 9
|
||||
color: Theme.alpha(Theme.warn, 0.08)
|
||||
radius: 10
|
||||
color: Theme.alpha(Theme.warn, 0.075)
|
||||
|
||||
Text {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 10
|
||||
anchors.leftMargin: 11
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "Showing the last known state"
|
||||
text: "Last known state · " + root.countSummary()
|
||||
color: Theme.warn
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
}
|
||||
Text {
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 10
|
||||
anchors.rightMargin: 11
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "Retry"
|
||||
color: Theme.accent
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.Medium
|
||||
font.weight: Font.DemiBold
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
anchors.margins: -6
|
||||
@@ -177,88 +193,66 @@ Item {
|
||||
|
||||
Section {
|
||||
width: parent.width
|
||||
expanded: root.expanded && HomeAssistant.entities.length > 0
|
||||
expanded: root.expanded && root.hasSelection
|
||||
|
||||
ScrollColumn {
|
||||
width: parent.width
|
||||
maxHeight: 270
|
||||
spacing: 2
|
||||
maxHeight: 324
|
||||
spacing: 8
|
||||
|
||||
Repeater {
|
||||
model: HomeAssistant.entities
|
||||
Grid {
|
||||
id: expandedGrid
|
||||
width: parent.width
|
||||
columns: 2
|
||||
spacing: 8
|
||||
|
||||
Rectangle {
|
||||
id: entityRow
|
||||
required property var modelData
|
||||
width: parent.width
|
||||
height: 44
|
||||
radius: 10
|
||||
color: entityMouse.containsMouse
|
||||
? Theme.alpha(Theme.fg, 0.09)
|
||||
: "transparent"
|
||||
Repeater {
|
||||
model: HomeAssistant.selectedEntities
|
||||
|
||||
Text {
|
||||
id: entityGlyph
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 11
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "\u{F0335}"
|
||||
color: entityRow.modelData.active ? Theme.warn : Theme.fgDim
|
||||
font.family: Theme.fontMono
|
||||
font.pixelSize: 14
|
||||
}
|
||||
Column {
|
||||
anchors.left: entityGlyph.right
|
||||
anchors.leftMargin: 10
|
||||
anchors.right: entityState.left
|
||||
anchors.rightMargin: 8
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
spacing: 2
|
||||
Text {
|
||||
width: parent.width
|
||||
text: entityRow.modelData.name
|
||||
color: Theme.fg
|
||||
elide: Text.ElideRight
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: Theme.fontSize
|
||||
}
|
||||
Text {
|
||||
width: parent.width
|
||||
text: !entityRow.modelData.available ? "Unavailable" : entityRow.modelData.state
|
||||
color: Theme.fgMuted
|
||||
elide: Text.ElideRight
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
}
|
||||
}
|
||||
Text {
|
||||
id: entityState
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 11
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: HomeAssistant.busyEntityId === entityRow.modelData.id
|
||||
? "Working"
|
||||
: (entityRow.modelData.active ? "On" : "Off")
|
||||
color: entityRow.modelData.active ? Theme.warn : Theme.fgMuted
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.DemiBold
|
||||
}
|
||||
MouseArea {
|
||||
id: entityMouse
|
||||
anchors.fill: parent
|
||||
enabled: entityRow.modelData.available && HomeAssistant.busyEntityId === ""
|
||||
hoverEnabled: true
|
||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
onClicked: HomeAssistant.toggleEntity(entityRow.modelData.id)
|
||||
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")
|
||||
@@ -269,12 +263,23 @@ Item {
|
||||
}
|
||||
|
||||
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 "Reading configured favourites";
|
||||
return "Finding your selected lights";
|
||||
if (HomeAssistant.lastError === "authentication-required")
|
||||
return "Update the long-lived access token";
|
||||
if (HomeAssistant.lastError === "not-configured")
|
||||
return "Add a URL, token and favourites";
|
||||
return "Check the connection and retry";
|
||||
return "Connect Home Assistant in Settings";
|
||||
return "Check the connection, then retry";
|
||||
}
|
||||
|
||||
function openHomeSettings(): void {
|
||||
ShellState.close();
|
||||
ShellState.openSettings("home-phone");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user