150 lines
5.2 KiB
QML
150 lines
5.2 KiB
QML
// One light on the My Home page: power square, name, state, and a brightness
|
|
// slider when the light dims. The slider is Control Center's — one dimmer
|
|
// implementation everywhere, covered by home-brightness-slider-contract.
|
|
|
|
import QtQuick
|
|
import qs.config
|
|
import qs.services
|
|
import qs.modules.quicksettings
|
|
|
|
Rectangle {
|
|
id: root
|
|
|
|
// A catalog entity: { id, sourceName, name, state, available, active,
|
|
// dimmable, brightnessPct }.
|
|
property var entity: ({})
|
|
// Whether this light sits in the first four favorites, and therefore in
|
|
// Control Center.
|
|
property bool featured: false
|
|
|
|
readonly property string entityId: String(root.entity.id ?? "")
|
|
readonly property bool busy: HomeAssistant.isBusy(root.entityId)
|
|
readonly property int pending: HomeAssistant.pendingFor(root.entityId)
|
|
readonly property string entityError: HomeAssistant.errorFor(root.entityId)
|
|
readonly property bool showsSlider: root.entity.dimmable === true && root.entity.available === true
|
|
|
|
radius: 14
|
|
color: Theme.alpha(Theme.fg, 0.05)
|
|
border.width: 1
|
|
border.color: Theme.alpha(Theme.fg, 0.07)
|
|
implicitHeight: header.implicitHeight + (showsSlider ? 36 : 0)
|
|
+ (entityError !== "" ? errorLine.implicitHeight + 4 : 0) + 22
|
|
|
|
Row {
|
|
id: header
|
|
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.top: parent.top
|
|
anchors.margins: 11
|
|
spacing: 11
|
|
|
|
Rectangle {
|
|
id: power
|
|
|
|
width: 30
|
|
height: 29
|
|
radius: 10
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
color: root.entity.active === true
|
|
? Theme.alpha(Theme.warn, 0.16)
|
|
: Theme.alpha(Theme.fg, 0.07)
|
|
border.width: 1
|
|
border.color: root.entity.active === true
|
|
? Theme.alpha(Theme.warn, 0.4)
|
|
: Theme.alpha(Theme.fg, 0.09)
|
|
opacity: root.entity.available === true && !root.busy ? 1 : 0.45
|
|
|
|
Text {
|
|
anchors.centerIn: parent
|
|
text: "\u{F0335}"
|
|
color: root.entity.active === true ? Theme.warn : Theme.fgDim
|
|
font.family: Theme.fontMono
|
|
font.pixelSize: 14
|
|
}
|
|
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
enabled: root.entity.available === true && !root.busy
|
|
cursorShape: Qt.PointingHandCursor
|
|
onClicked: HomeAssistant.toggleEntity(root.entityId)
|
|
}
|
|
|
|
Accessible.role: Accessible.Button
|
|
Accessible.name: (root.entity.active === true ? "Turn off " : "Turn on ")
|
|
+ String(root.entity.name ?? root.entity.sourceName ?? "")
|
|
}
|
|
|
|
Column {
|
|
width: parent.width - power.width - parent.spacing
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
spacing: 2
|
|
|
|
Row {
|
|
width: parent.width
|
|
spacing: 8
|
|
|
|
Text {
|
|
text: String(root.entity.name ?? root.entity.sourceName ?? "")
|
|
color: Theme.fg
|
|
font.family: Theme.fontFamily
|
|
font.pixelSize: Theme.fontSize
|
|
font.weight: Font.DemiBold
|
|
elide: Text.ElideRight
|
|
}
|
|
|
|
StatusBadge {
|
|
visible: root.featured
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
text: "Control Center"
|
|
tone: Theme.accent
|
|
}
|
|
}
|
|
|
|
Text {
|
|
width: parent.width
|
|
text: {
|
|
if (root.entity.available !== true)
|
|
return "Unavailable";
|
|
if (root.entity.active !== true)
|
|
return "Off";
|
|
const pct = root.pending >= 0 ? root.pending : Number(root.entity.brightnessPct ?? 0);
|
|
return root.entity.dimmable === true ? "On · " + pct + "%" : "On";
|
|
}
|
|
color: Theme.fgDim
|
|
font.family: Theme.fontFamily
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
elide: Text.ElideRight
|
|
}
|
|
}
|
|
}
|
|
|
|
HomeBrightnessSlider {
|
|
visible: root.showsSlider
|
|
anchors.left: parent.left
|
|
anchors.leftMargin: 11
|
|
anchors.right: parent.right
|
|
anchors.rightMargin: 11
|
|
anchors.top: header.bottom
|
|
accessibleName: String(root.entity.name ?? root.entity.sourceName ?? "Light") + " brightness"
|
|
value: root.pending >= 0 ? root.pending : Number(root.entity.brightnessPct ?? 0)
|
|
onCommitted: value => HomeAssistant.setBrightness(root.entityId, value)
|
|
}
|
|
|
|
Text {
|
|
id: errorLine
|
|
visible: root.entityError !== ""
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.bottom: parent.bottom
|
|
anchors.margins: 11
|
|
text: root.entityError === "unreachable"
|
|
? "Home Assistant did not respond"
|
|
: "That change did not apply"
|
|
color: Theme.warn
|
|
font.family: Theme.fontFamily
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
wrapMode: Text.WordWrap
|
|
}
|
|
}
|