diff --git a/nymea-app/resources.qrc b/nymea-app/resources.qrc
index 500749b6..7db7c353 100644
--- a/nymea-app/resources.qrc
+++ b/nymea-app/resources.qrc
@@ -138,5 +138,6 @@
ui/system/MqttPolicyPage.qml
ui/devicepages/DeviceLogPage.qml
ui/components/Led.qml
+ ui/devicelistpages/ClosablesDeviceListPage.qml
diff --git a/nymea-app/ui/devicelistpages/ClosablesDeviceListPage.qml b/nymea-app/ui/devicelistpages/ClosablesDeviceListPage.qml
new file mode 100644
index 00000000..2eb852d5
--- /dev/null
+++ b/nymea-app/ui/devicelistpages/ClosablesDeviceListPage.qml
@@ -0,0 +1,114 @@
+import QtQuick 2.5
+import QtQuick.Controls 2.1
+import QtQuick.Controls.Material 2.1
+import QtQuick.Layouts 1.1
+import QtGraphicalEffects 1.0
+import Nymea 1.0
+import "../components"
+
+DeviceListPageBase {
+ id: root
+
+ header: GuhHeader {
+ id: header
+ onBackPressed: pageStack.pop()
+ text: root.title
+
+ HeaderButton {
+ imageSource: "../images/system-shutdown.svg"
+ onClicked: {
+ for (var i = 0; i < devicesProxy.count; i++) {
+ var device = devicesProxy.get(i);
+ var deviceClass = engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
+ var actionType = deviceClass.actionTypes.findByName("close");
+ engine.deviceManager.executeAction(device.id, actionType.id)
+ }
+ }
+ }
+ }
+
+ ListView {
+ anchors.fill: parent
+ model: devicesProxy
+ spacing: app.margins
+
+ delegate: Pane {
+ id: itemDelegate
+ width: parent.width
+
+ property bool inline: width > 500
+
+ property Device device: devicesProxy.get(index);
+ property DeviceClass deviceClass: engine.deviceManager.deviceClasses.getDeviceClass(device.deviceClassId);
+
+ property var connectedStateType: deviceClass.stateTypes.findByName("connected");
+ property var connectedState: connectedStateType ? device.states.getState(connectedStateType.id) : null
+
+ property StateType percentageStateType: deviceClass.stateTypes.findByName("percentage");
+ property ActionType percentageActionType: deviceClass.actionTypes.findByName("percentage");
+ property State percentageState: percentageStateType ? device.states.getState(percentageStateType.id) : null
+
+ property StateType movingStateType: deviceClass.stateTypes.findByName("moving");
+ property ActionType movingActionType: deviceClass.actionTypes.findByName("moving");
+ property State movingState: movingStateType ? device.states.getState(movingStateType.id) : null
+
+ Material.elevation: 1
+ topPadding: 0
+ bottomPadding: 0
+ leftPadding: 0
+ rightPadding: 0
+ contentItem: ItemDelegate {
+ id: contentItem
+ implicitHeight: nameRow.implicitHeight
+
+ topPadding: 0
+
+ contentItem: ColumnLayout {
+ spacing: 0
+ RowLayout {
+ enabled: itemDelegate.connectedState === null || itemDelegate.connectedState.value === true
+ id: nameRow
+ z: 2 // make sure the switch in here is on top of the slider, given we cheated a bit and made them overlap
+ spacing: app.margins
+ Item {
+ Layout.preferredHeight: app.iconSize
+ Layout.preferredWidth: height
+ Layout.alignment: Qt.AlignVCenter
+
+ ColorIcon {
+ id: icon
+ anchors.fill: parent
+ color: itemDelegate.movingStateType && itemDelegate.movingState.value === true
+ ? app.accentColor
+ : keyColor
+ name: itemDelegate.percentageStateType
+ ? "../images/shutter/shutter-" + app.pad(Math.round(itemDelegate.percentageState.value / 10) * 10, 3) + ".svg"
+ : "../images/shutter/shutter-050.svg"
+ }
+ }
+
+ Label {
+ Layout.fillWidth: true
+ text: itemDelegate.device.name
+ elide: Text.ElideRight
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ Item {
+ Layout.preferredWidth: shutterControls.implicitWidth
+ Layout.preferredHeight: app.iconSize * 2
+ ShutterControls {
+ id: shutterControls
+ height: parent.height
+ device: itemDelegate.device
+ }
+ }
+ }
+ }
+ onClicked: {
+ enterPage(index, false)
+ }
+ }
+ }
+ }
+}
diff --git a/nymea-app/ui/devicepages/ShutterDevicePage.qml b/nymea-app/ui/devicepages/ShutterDevicePage.qml
index a8149c1c..8813a5fb 100644
--- a/nymea-app/ui/devicepages/ShutterDevicePage.qml
+++ b/nymea-app/ui/devicepages/ShutterDevicePage.qml
@@ -10,7 +10,7 @@ DevicePageBase {
id: root
readonly property bool landscape: width > height
- readonly property bool isExtended: deviceClass.interfaces.indexOf("extendedshutter") >= 0
+ readonly property bool isExtended: deviceClass.interfaces.indexOf("extendedclosable") >= 0
readonly property var percentageState: isExtended ? device.states.getState(deviceClass.stateTypes.findByName("percentage").id) : 0
readonly property var movingState: isExtended ? device.states.getState(deviceClass.stateTypes.findByName("moving").id) : 0
diff --git a/nymea-app/ui/mainviews/DevicesPageDelegate.qml b/nymea-app/ui/mainviews/DevicesPageDelegate.qml
index fa8845b6..4c080f07 100644
--- a/nymea-app/ui/mainviews/DevicesPageDelegate.qml
+++ b/nymea-app/ui/mainviews/DevicesPageDelegate.qml
@@ -28,6 +28,15 @@ MainPageTile {
case "smartmeter":
page ="SmartMeterDeviceListPage.qml";
break;
+ case "awning":
+ case "blind":
+ case "shutter":
+ case "garagegate":
+ case "extendedAwning":
+ case "extendedBlind":
+ case "extendedShutter":
+ page = "ClosablesDeviceListPage.qml";
+ break;
default:
page = "GenericDeviceListPage.qml"
}