This repository has been archived on 2026-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
powersync-app/nymea-app/ui/devicelistpages/MediaDeviceListPage.qml

201 lines
12 KiB
QML

import QtQuick 2.5
import QtQuick.Controls 2.1
import QtQuick.Controls.Material 2.1
import QtQuick.Layouts 1.1
import Nymea 1.0
import QtGraphicalEffects 1.0
import "../components"
DeviceListPageBase {
id: root
header: NymeaHeader {
text: qsTr("Media")
onBackPressed: pageStack.pop()
}
Flickable {
anchors.fill: parent
contentHeight: contentGrid.implicitHeight
GridLayout {
id: contentGrid
width: parent.width
columns: Math.ceil(width / 500)
rowSpacing: 0
columnSpacing: 0
Repeater {
model: root.devicesProxy
delegate: ItemDelegate {
id: itemDelegate
Layout.preferredWidth: contentGrid.width / contentGrid.columns
property bool inline: width > 500
property Device device: devicesProxy.getDevice(model.id)
property DeviceClass deviceClass: device.deviceClass
readonly property StateType playbackStateType: deviceClass.stateTypes.findByName("playbackStatus")
readonly property State playbackState: playbackStateType ? device.states.getState(playbackStateType.id) : null
readonly property StateType playerTypeStateType: deviceClass.stateTypes.findByName("playerType")
readonly property State playerTypeState: playerTypeStateType ? device.states.getState(playerTypeStateType.id) : null
bottomPadding: index === root.devicesProxy.count - 1 ? topPadding : 0
contentItem: Pane {
id: contentItem
Material.elevation: 2
leftPadding: 0
rightPadding: 0
topPadding: 0
bottomPadding: 0
contentItem: ItemDelegate {
leftPadding: 0
rightPadding: 0
topPadding: 0
bottomPadding: 0
contentItem: ColumnLayout {
spacing: 0
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: app.mediumFont + app.margins
color: Qt.rgba(app.foregroundColor.r, app.foregroundColor.g, app.foregroundColor.b, .05)
RowLayout {
anchors { verticalCenter: parent.verticalCenter; left: parent.left; right: parent.right; margins: app.margins }
Label {
Layout.fillWidth: true
text: model.name
elide: Text.ElideRight
}
ColorIcon {
Layout.preferredHeight: app.iconSize * .5
Layout.preferredWidth: height
name: "../images/battery/battery-020.svg"
visible: itemDelegate.deviceClass.interfaces.indexOf("battery") >= 0 && itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("batteryCritical").id).value === true
}
ColorIcon {
Layout.preferredHeight: app.iconSize * .5
Layout.preferredWidth: height
name: "../images/dialog-warning-symbolic.svg"
visible: itemDelegate.deviceClass.interfaces.indexOf("connectable") >= 0 && itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("connected").id).value === false
color: "red"
}
}
}
RowLayout {
ColumnLayout {
id: leftColummn
Layout.margins: app.margins
Label {
Layout.fillWidth: true
text: itemDelegate.playbackState.value === "Stopped" ?
qsTr("No playback")
: itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("title").id).value
horizontalAlignment: Text.AlignHCenter
// font.pixelSize: app.largeFont
elide: Text.ElideRight
}
Label {
Layout.fillWidth: true
text: itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("artist").id).value
font.pixelSize: app.smallFont
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
}
Label {
Layout.fillWidth: true
text: itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("collection").id).value
horizontalAlignment: Text.AlignHCenter
font.pixelSize: app.smallFont
elide: Text.ElideRight
}
MediaControls {
visible: itemDelegate.deviceClass.interfaces.indexOf("mediacontroller") >= 0
device: itemDelegate.device
}
}
Item {
Layout.preferredHeight: leftColummn.height + app.margins * 2
Layout.preferredWidth: height * .7
Item {
id: artworkContainer
anchors.fill: parent
Image {
id: artworkImage
width: artworkImage.sourceSize.width * height / artworkImage.sourceSize.height
anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
readonly property StateType artworkStateType: device ? device.deviceClass.stateTypes.findByName("artwork") : null
readonly property State artworkState: artworkStateType ? device.states.getState(artworkStateType.id) : null
source: artworkState ? artworkState.value : ""
}
Rectangle {
visible: artworkImage.status !== Image.Ready || artworkImage.source === ""
anchors.fill: parent
color: "black"
}
ColorIcon {
width: Math.min(parent.width, parent.height) - app.margins * 2
height: width
anchors.centerIn: parent
name: itemDelegate.playerTypeState && itemDelegate.playerTypeState.value === "video" ? "../images/stock_video.svg" : "../images/stock_music.svg"
visible: artworkImage.status !== Image.Ready || artworkImage.source === ""
color: "white"
}
}
Rectangle {
id: maskRect
anchors.centerIn: parent
height: parent.width
width: parent.height
gradient: Gradient {
GradientStop { position: 0; color: "#00FF0000" }
GradientStop { position: 0.2; color: "#15FF0000" }
GradientStop { position: 1; color: "#FFFF0000" }
}
}
ShaderEffect {
anchors.fill: parent
property variant source: ShaderEffectSource {
sourceItem: artworkContainer
hideSource: true
}
property variant mask: ShaderEffectSource {
sourceItem: maskRect
hideSource: true
}
fragmentShader: "
varying highp vec2 qt_TexCoord0;
uniform sampler2D source;
uniform sampler2D mask;
void main(void)
{
highp vec4 sourceColor = texture2D(source, qt_TexCoord0);
highp float alpha = texture2D(mask, vec2(qt_TexCoord0.y, qt_TexCoord0.x)).a;
sourceColor *= alpha;
gl_FragColor = sourceColor;
}
"
}
}
}
}
onClicked: {
enterPage(index, false)
}
}
}
}
}
}
}
}