diff --git a/nymea-app/images.qrc b/nymea-app/images.qrc
index 3782deca..91925329 100644
--- a/nymea-app/images.qrc
+++ b/nymea-app/images.qrc
@@ -249,5 +249,7 @@
ui/images/facebook.svg
ui/images/help.svg
ui/images/discord.svg
+ ui/images/media/equalizer.svg
+ ui/images/media/ambeo.svg
diff --git a/nymea-app/ui/components/MeaDialog.qml b/nymea-app/ui/components/MeaDialog.qml
index 2415bbcc..3ef50105 100644
--- a/nymea-app/ui/components/MeaDialog.qml
+++ b/nymea-app/ui/components/MeaDialog.qml
@@ -46,6 +46,11 @@ Dialog {
onClosed: root.destroy()
+ Connections {
+ target: root.parent
+ onDestroyed: root.destroy()
+ }
+
MouseArea {
parent: app.overlay
anchors.fill: parent
@@ -56,13 +61,14 @@ Dialog {
header: Item {
implicitHeight: headerRow.height + app.margins * 2
implicitWidth: parent.width
+ visible: root.title.length > 0
RowLayout {
id: headerRow
anchors { left: parent.left; right: parent.right; top: parent.top; margins: app.margins }
spacing: app.margins
ColorIcon {
id: headerColorIcon
- Layout.preferredHeight: app.iconSize * 2
+ Layout.preferredHeight: app.hugeIconSize
Layout.preferredWidth: height
color: app.accentColor
visible: name.length > 0
diff --git a/nymea-app/ui/components/MediaPlayer.qml b/nymea-app/ui/components/MediaPlayer.qml
index feb64c20..af8b820f 100644
--- a/nymea-app/ui/components/MediaPlayer.qml
+++ b/nymea-app/ui/components/MediaPlayer.qml
@@ -35,6 +35,7 @@ import QtQuick.Layouts 1.2
import Nymea 1.0
import QtGraphicalEffects 1.0
import "../delegates"
+import "../utils"
Item {
id: root
@@ -56,8 +57,13 @@ Item {
readonly property State volumeState: thing.stateByName("volume")
readonly property State muteState: thing.stateByName("mute")
+ readonly property State equalizerPresetState: thing.stateByName("equalizerPreset")
+ readonly property State nightModeState: thing.stateByName("nightMode")
readonly property State likeState: thing.stateByName("like")
+ // NOTE: This is not in any interface, special feature just for AMBEO
+ readonly property State ambeoModeState: thing.stateByName("ambeoMode")
+
readonly property bool hasNavigationPatd: thing.thingClass.interfaces.indexOf("navigationpad") >= 0
clip: true
@@ -65,20 +71,21 @@ Item {
QtObject {
id: d
property var browser: null
- property int pendingInputSourceSelectId: -1
+ property int pendingCallId: -1
}
Connections {
target: engine.thingManager
onExecuteActionReply: {
- if (commandId == d.pendingInputSourceSelectId) {
+ if (commandId == d.pendingCallId) {
if (params.deviceError !== "DeviceErrorNoError") {
var errorDialog = Qt.createComponent(Qt.resolvedUrl("../components/ErrorDialog.qml"));
- var text
- if (params.displayMessage.length > 0) {
- text = params.displayMessage
+ var dialogParams = {}
+ dialogParams.errorCode = params.deviceError
+ if (params.displayMessage && params.displayMessage.length > 0) {
+ dialogParams.text = params.displayMessage
}
- var popup = errorDialog.createObject(app, {text: text})
+ var popup = errorDialog.createObject(app, dialogParams)
popup.open()
}
}
@@ -231,8 +238,17 @@ Item {
d.browser.show();
}
}
+ ProgressButton {
+ Layout.preferredHeight: app.iconSize
+ Layout.preferredWidth: app.iconSize
+ longpressEnabled: false
+ visible: root.hasNavigationPatd
+ imageSource: "../images/navigationpad.svg"
+ onClicked: pageStack.push(navigationPadPage)
+ }
RowLayout {
ProgressButton {
+ id: inputSourceButton
Layout.preferredHeight: app.iconSize
Layout.preferredWidth: app.iconSize
longpressEnabled: false
@@ -246,23 +262,52 @@ Item {
Label {
Layout.fillWidth: true
text: root.inputSourceState ? root.inputSourceState.value : ""
+ wrapMode: Text.WordWrap
+ elide: Text.ElideRight
font.pixelSize: app.smallFont
+ MouseArea { anchors.fill: parent; onClicked: inputSourceButton.clicked() }
+ }
+ }
+ ColorIcon {
+ Layout.preferredHeight: app.iconSize
+ Layout.preferredWidth: app.iconSize * 3
+ visible: root.ambeoModeState !== null
+ name: "../images/media/ambeo.svg"
+ color: root.ambeoModeState && root.ambeoModeState.value !== "Off" ? app.accentColor : keyColor
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ var popup = ambeoModeDialogComponent.createObject(root)
+ popup.open()
+ }
}
}
ProgressButton {
Layout.preferredHeight: app.iconSize
Layout.preferredWidth: app.iconSize
longpressEnabled: false
- visible: root.hasNavigationPatd
- imageSource: "../images/navigationpad.svg"
- onClicked: pageStack.push(navigationPadPage)
+ visible: root.nightModeState !== null
+ imageSource: "../images/weathericons/weather-clear-night.svg"
+ color: root.nightModeState && root.nightModeState.value === true ? app.accentColor : keyColor
+ onClicked: d.pendingCallId = engine.thingManager.executeAction(root.thing.id, root.nightModeState.stateTypeId, [{paramTypeId: root.nightModeState.stateTypeId, value: !root.nightModeState.value}])
+ }
+ ProgressButton {
+ Layout.preferredHeight: app.iconSize
+ Layout.preferredWidth: app.iconSize
+ longpressEnabled: false
+ visible: root.equalizerPresetState !== null
+ imageSource: "../images/media/equalizer.svg"
+ onClicked: {
+ var dialog = equalizerComponent.createObject(root)
+ dialog.open()
+ }
}
-
ProgressButton {
id: volumeButton
Layout.preferredHeight: app.iconSize
Layout.preferredWidth: app.iconSize
visible: root.hasVolumeControl
+ longpressEnabled: false
imageSource: root.muteState && root.muteState.value === true ?
"../images/audio-speakers-muted-symbolic.svg"
: "../images/audio-speakers-symbolic.svg"
@@ -279,9 +324,6 @@ Item {
var sliderPane = volumeSliderPaneComponent.createObject(root, props)
sliderPane.open()
}
- onLongpressed: {
-
- }
}
}
}
@@ -297,7 +339,11 @@ Item {
bottomPadding: app.margins / 2
modal: true
- property int pendingVolumeValue: -1
+ ActionQueue {
+ id: volumeActionQueue
+ thing: root.thing
+ stateType: root.thing.thingClass.stateTypes.findByName("volume")
+ }
contentItem: ColumnLayout {
ProgressButton {
@@ -315,14 +361,14 @@ Item {
onClicked: engine.thingManager.executeAction(root.thing.id, root.thing.thingClass.actionTypes.findByName("decreaseVolume").id);
}
- ThrottledSlider {
+ Slider {
Layout.fillHeight: true
visible: root.volumeState !== null
from: 0
to: 100
- value: root.volumeState.value
+ value: volumeActionQueue.pendingValue || root.volumeState.value
orientation: Qt.Vertical
- onMoved: engine.thingManager.executeAction(root.thing.id, root.volumeState.stateTypeId, [{paramTypeId: root.volumeState.stateTypeId, value: value}])
+ onMoved: volumeActionQueue.sendValue(value)
}
ProgressButton {
@@ -442,6 +488,7 @@ Item {
id: inputSourceSelectDialogComponent
MeaDialog {
id: inputSourceSelectDialog
+ headerIcon: "../images/state-in.svg"
title: qsTr("Select input")
standardButtons: Dialog.NoButton
@@ -457,7 +504,7 @@ Item {
text: modelData
checked: root.inputSourceState.value === modelData
onClicked: {
- d.pendingInputSourceSelectId = engine.thingManager.executeAction(root.thing.id, root.inputSourceState.stateTypeId, [{paramTypeId: root.inputSourceState.stateTypeId, value: modelData}])
+ d.pendingCallId = engine.thingManager.executeAction(root.thing.id, root.inputSourceState.stateTypeId, [{paramTypeId: root.inputSourceState.stateTypeId, value: modelData}])
inputSourceSelectDialog.close();
}
}
@@ -465,4 +512,62 @@ Item {
}
}
+ Component {
+ id: equalizerComponent
+ MeaDialog {
+ id: equalizer
+ headerIcon: "../images/media/equalizer.svg"
+ title: qsTr("Equalizer preset")
+ standardButtons: Dialog.NoButton
+ ListView {
+ id: inputSourceListView
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.preferredHeight: 200
+ clip: true
+ model: root.thing.thingClass.stateTypes.findByName("equalizerPreset").allowedValues
+ delegate: RadioDelegate {
+ width: inputSourceListView.width
+ text: modelData
+ checked: root.equalizerPresetState.value === modelData
+ onClicked: {
+ d.pendingCallId = engine.thingManager.executeAction(root.thing.id, root.equalizerPresetState.stateTypeId, [{paramTypeId: root.equalizerPresetState.stateTypeId, value: modelData}])
+ equalizer.close();
+ }
+ }
+ }
+ }
+ }
+ Component {
+ id: ambeoModeDialogComponent
+ MeaDialog {
+ id: ambeoModeDialog
+ standardButtons: Dialog.NoButton
+ ColorIcon {
+ Layout.preferredHeight: app.hugeIconSize
+ Layout.preferredWidth: app.hugeIconSize * 3
+ Layout.alignment: Qt.AlignHCenter
+ name: "../images/media/ambeo.svg"
+ color: app.accentColor
+ }
+
+ ListView {
+ id: ambeoModeListView
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+ Layout.preferredHeight: 200
+ clip: true
+ model: root.thing.thingClass.stateTypes.findByName("ambeoMode").allowedValues
+ delegate: RadioDelegate {
+ width: ambeoModeListView.width
+ text: modelData
+ checked: root.ambeoModeState.value === modelData
+ onClicked: {
+ d.pendingCallId = engine.thingManager.executeAction(root.thing.id, root.ambeoModeState.stateTypeId, [{paramTypeId: root.ambeoModeState.stateTypeId, value: modelData}])
+ ambeoModeDialog.close();
+ }
+ }
+ }
+ }
+ }
}
diff --git a/nymea-app/ui/images/media/ambeo.svg b/nymea-app/ui/images/media/ambeo.svg
new file mode 100644
index 00000000..c5d6f609
--- /dev/null
+++ b/nymea-app/ui/images/media/ambeo.svg
@@ -0,0 +1,77 @@
+
+
diff --git a/nymea-app/ui/images/media/equalizer.svg b/nymea-app/ui/images/media/equalizer.svg
new file mode 100644
index 00000000..fe0300ce
--- /dev/null
+++ b/nymea-app/ui/images/media/equalizer.svg
@@ -0,0 +1,174 @@
+
+
+
+