Build the Home accessory shelf
This commit is contained in:
@@ -6,76 +6,164 @@ Rectangle {
|
||||
|
||||
required property var entity
|
||||
property bool busy: false
|
||||
signal activated
|
||||
property int pendingBrightness: -1
|
||||
property string actionError: ""
|
||||
|
||||
implicitHeight: 72
|
||||
radius: Theme.cardRadius
|
||||
signal powerRequested
|
||||
signal brightnessRequested(int value)
|
||||
|
||||
readonly property int confirmedBrightness: root.clamp(root.entity.brightnessPct ?? 0)
|
||||
readonly property int displayedBrightness: brightnessSlider.previewValue
|
||||
readonly property bool powerEnabled: root.entity.available && !root.busy
|
||||
readonly property bool dimmerEnabled: root.entity.available
|
||||
&& root.entity.dimmable
|
||||
&& !root.busy
|
||||
|
||||
implicitHeight: 124
|
||||
radius: 14
|
||||
color: {
|
||||
if (root.entity.active)
|
||||
return Theme.alpha(Theme.warn, tileMouse.containsMouse ? 0.20 : 0.14);
|
||||
return Theme.alpha(Theme.fg, tileMouse.containsMouse ? 0.10 : 0.055);
|
||||
return Theme.alpha(Theme.warn, powerArea.containsMouse ? 0.145 : 0.095);
|
||||
return Theme.alpha(Theme.fg, powerArea.containsMouse ? 0.078 : 0.045);
|
||||
}
|
||||
border.width: 1
|
||||
border.color: root.entity.active
|
||||
? Theme.alpha(Theme.warn, 0.20)
|
||||
: Theme.alpha(Theme.fg, 0.045)
|
||||
border.color: {
|
||||
if (root.activeFocus)
|
||||
return Theme.alpha(Theme.accent, 0.72);
|
||||
if (root.entity.active)
|
||||
return Theme.alpha(Theme.warn, 0.17);
|
||||
return Theme.alpha(Theme.fg, 0.065);
|
||||
}
|
||||
activeFocusOnTab: root.powerEnabled
|
||||
|
||||
Behavior on color { ColorAnimation { duration: Theme.durFast } }
|
||||
Behavior on border.color { ColorAnimation { duration: Theme.durFast } }
|
||||
|
||||
Text {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 10
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 9
|
||||
text: root.busy ? "\u{F0772}" : root.glyphFor(root.entity.domain)
|
||||
color: root.entity.active ? Theme.warn : Theme.fgDim
|
||||
font.family: Theme.fontMono
|
||||
font.pixelSize: 15
|
||||
Keys.onSpacePressed: {
|
||||
if (root.powerEnabled)
|
||||
root.powerRequested();
|
||||
}
|
||||
Keys.onReturnPressed: {
|
||||
if (root.powerEnabled)
|
||||
root.powerRequested();
|
||||
}
|
||||
|
||||
Column {
|
||||
Rectangle {
|
||||
id: bulb
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 10
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 8
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 8
|
||||
spacing: 1
|
||||
anchors.leftMargin: 13
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 13
|
||||
width: 30
|
||||
height: 30
|
||||
radius: 10
|
||||
color: root.entity.active
|
||||
? Theme.alpha(Theme.warn, 0.16)
|
||||
: Theme.alpha(Theme.fg, 0.065)
|
||||
|
||||
Text {
|
||||
width: parent.width
|
||||
text: root.entity.name
|
||||
color: Theme.fg
|
||||
elide: Text.ElideRight
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.DemiBold
|
||||
}
|
||||
Text {
|
||||
width: parent.width
|
||||
text: !root.entity.available ? "Unavailable" : (root.entity.active ? "On" : "Off")
|
||||
color: root.entity.active ? Theme.warn : Theme.fgMuted
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: 9
|
||||
anchors.centerIn: parent
|
||||
text: root.busy ? "\u{F0772}" : "\u{F0335}"
|
||||
color: root.entity.active ? Theme.warn : Theme.fgDim
|
||||
font.family: Theme.fontMono
|
||||
font.pixelSize: 15
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 13
|
||||
anchors.verticalCenter: bulb.verticalCenter
|
||||
text: root.entity.dimmable ? root.displayedBrightness + "%" : "—"
|
||||
color: root.entity.active || root.pendingBrightness >= 0
|
||||
? Theme.warn
|
||||
: Theme.fgDim
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.weight: Font.DemiBold
|
||||
font.features: Theme.tabularFigures
|
||||
}
|
||||
|
||||
Text {
|
||||
id: aliasLabel
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 13
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 13
|
||||
anchors.top: bulb.bottom
|
||||
anchors.topMargin: 8
|
||||
text: root.entity.name
|
||||
color: Theme.fg
|
||||
elide: Text.ElideRight
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: Theme.fontSize
|
||||
font.weight: Font.DemiBold
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.left: aliasLabel.left
|
||||
anchors.right: aliasLabel.right
|
||||
anchors.top: aliasLabel.bottom
|
||||
anchors.topMargin: 2
|
||||
text: root.secondaryText()
|
||||
color: root.actionError !== ""
|
||||
? Theme.warn
|
||||
: (root.entity.active ? Theme.warn : Theme.fgMuted)
|
||||
elide: Text.ElideRight
|
||||
font.family: Theme.fontFamily
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: tileMouse
|
||||
anchors.fill: parent
|
||||
enabled: root.entity.available && !root.busy
|
||||
id: powerArea
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: brightnessSlider.top
|
||||
anchors.bottomMargin: 1
|
||||
enabled: root.powerEnabled
|
||||
hoverEnabled: true
|
||||
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
onClicked: root.activated()
|
||||
onPressed: root.forceActiveFocus()
|
||||
onClicked: root.powerRequested()
|
||||
}
|
||||
|
||||
function glyphFor(domain: string): string {
|
||||
if (domain === "light")
|
||||
return "\u{F0335}";
|
||||
if (domain === "switch")
|
||||
return "\u{F0521}";
|
||||
if (domain === "scene")
|
||||
return "\u{F0FCE}";
|
||||
return "\u{F02DC}";
|
||||
HomeBrightnessSlider {
|
||||
id: brightnessSlider
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 13
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 13
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 5
|
||||
value: root.pendingBrightness >= 0
|
||||
? root.pendingBrightness
|
||||
: root.confirmedBrightness
|
||||
enabled: root.dimmerEnabled
|
||||
onCommitted: value => root.brightnessRequested(value)
|
||||
}
|
||||
|
||||
function clamp(candidate: real): int {
|
||||
return Math.max(0, Math.min(100, Math.round(candidate)));
|
||||
}
|
||||
|
||||
function secondaryText(): string {
|
||||
if (root.actionError !== "")
|
||||
return root.errorText(root.actionError);
|
||||
if (!root.entity.available)
|
||||
return "Unavailable";
|
||||
if (root.busy && root.pendingBrightness >= 0)
|
||||
return "Setting " + root.pendingBrightness + "%";
|
||||
if (root.busy)
|
||||
return "Updating";
|
||||
return root.entity.active ? "On" : "Off";
|
||||
}
|
||||
|
||||
function errorText(code: string): string {
|
||||
if (code === "authentication-required")
|
||||
return "Authentication required";
|
||||
if (code === "entity-not-discovered")
|
||||
return "Light is unavailable";
|
||||
return "Couldn’t update light";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user