diff --git a/libnymea-app-core/devicemanager.cpp b/libnymea-app-core/devicemanager.cpp index 2e59dc56..6e26deed 100644 --- a/libnymea-app-core/devicemanager.cpp +++ b/libnymea-app-core/devicemanager.cpp @@ -464,9 +464,12 @@ void DeviceManager::browseDeviceResponse(const QVariantMap ¶ms) BrowserItem *item = new BrowserItem(itemMap.value("id").toString(), this); item->setDisplayName(itemMap.value("displayName").toString()); item->setDescription(itemMap.value("description").toString()); + item->setIcon(itemMap.value("icon").toString()); item->setThumbnail(itemMap.value("thumbnail").toString()); item->setExecutable(itemMap.value("executable").toBool()); item->setBrowsable(itemMap.value("browsable").toBool()); + + item->setMediaIcon(itemMap.value("mediaIcon").toString()); itemModel->addBrowserItem(item); } diff --git a/libnymea-common/types/browseritem.cpp b/libnymea-common/types/browseritem.cpp index 98250990..ea46d4b4 100644 --- a/libnymea-common/types/browseritem.cpp +++ b/libnymea-common/types/browseritem.cpp @@ -32,6 +32,16 @@ void BrowserItem::setDescription(const QString &description) m_description = description; } +QString BrowserItem::icon() const +{ + return m_icon; +} + +void BrowserItem::setIcon(const QString &icon) +{ + m_icon = icon; +} + QString BrowserItem::thumbnail() const { return m_thumbnail; @@ -61,3 +71,13 @@ void BrowserItem::setBrowsable(bool browsable) { m_browsable = browsable; } + +QString BrowserItem::mediaIcon() const +{ + return m_mediaIcon; +} + +void BrowserItem::setMediaIcon(const QString &mediaIcon) +{ + m_mediaIcon = mediaIcon; +} diff --git a/libnymea-common/types/browseritem.h b/libnymea-common/types/browseritem.h index 14bd51cd..3208bc73 100644 --- a/libnymea-common/types/browseritem.h +++ b/libnymea-common/types/browseritem.h @@ -10,10 +10,13 @@ class BrowserItem : public QObject Q_PROPERTY(QUuid id READ id CONSTANT) Q_PROPERTY(QString displayName READ displayName CONSTANT) Q_PROPERTY(QString description READ description CONSTANT) + Q_PROPERTY(QString icon READ icon CONSTANT) Q_PROPERTY(QString thumbnail READ thumbnail CONSTANT) Q_PROPERTY(bool executable READ executable CONSTANT) Q_PROPERTY(bool browsable READ browsable CONSTANT) + Q_PROPERTY(QString mediaIcon READ mediaIcon CONSTANT) + public: explicit BrowserItem(const QString &id, QObject *parent = nullptr); @@ -25,6 +28,9 @@ public: QString description() const; void setDescription(const QString &description); + QString icon() const; + void setIcon(const QString &icon); + QString thumbnail() const; void setThumbnail(const QString &thumbnail); @@ -34,13 +40,19 @@ public: bool browsable() const; void setBrowsable(bool browsable); + QString mediaIcon() const; + void setMediaIcon(const QString &mediaIcon); + private: QString m_id; QString m_displayName; QString m_description; + QString m_icon; QString m_thumbnail; bool m_executable = false; bool m_browsable = false; + + QString m_mediaIcon; }; #endif // BROWSERITEM_H diff --git a/libnymea-common/types/browseritems.cpp b/libnymea-common/types/browseritems.cpp index bfcae8d4..e5a67509 100644 --- a/libnymea-common/types/browseritems.cpp +++ b/libnymea-common/types/browseritems.cpp @@ -33,12 +33,17 @@ QVariant BrowserItems::data(const QModelIndex &index, int role) const return m_list.at(index.row())->displayName(); case RoleDescription: return m_list.at(index.row())->description(); + case RoleIcon: + return m_list.at(index.row())->icon(); case RoleThumbnail: return m_list.at(index.row())->thumbnail(); case RoleExecutable: return m_list.at(index.row())->executable(); case RoleBrowsable: return m_list.at(index.row())->browsable(); + + case RoleMediaIcon: + return m_list.at(index.row())->mediaIcon(); } return QVariant(); } @@ -49,9 +54,12 @@ QHash BrowserItems::roleNames() const roles.insert(RoleId, "id"); roles.insert(RoleDisplayName, "displayName"); roles.insert(RoleDescription, "description"); + roles.insert(RoleIcon, "icon"); roles.insert(RoleThumbnail, "thumbnail"); roles.insert(RoleExecutable, "executable"); roles.insert(RoleBrowsable, "browsable"); + + roles.insert(RoleMediaIcon, "mediaIcon"); return roles; } diff --git a/libnymea-common/types/browseritems.h b/libnymea-common/types/browseritems.h index 07257942..4429b28e 100644 --- a/libnymea-common/types/browseritems.h +++ b/libnymea-common/types/browseritems.h @@ -15,9 +15,12 @@ public: RoleId, RoleDisplayName, RoleDescription, + RoleIcon, RoleThumbnail, RoleBrowsable, - RoleExecutable + RoleExecutable, + + RoleMediaIcon, }; Q_ENUM(Roles) diff --git a/nymea-app/images.qrc b/nymea-app/images.qrc index 37db3d92..03374bf9 100644 --- a/nymea-app/images.qrc +++ b/nymea-app/images.qrc @@ -182,5 +182,31 @@ ui/images/lock-open.svg ui/images/system-update.svg ui/images/folder-symbolic.svg + ui/images/browser/BrowserIconFile.svg + ui/images/browser/BrowserIconFolder.svg + ui/images/browser/MediaBrowserIconSpotify.svg + ui/images/browser/MediaBrowserIconAirable.svg + ui/images/browser/MediaBrowserIconAmazon.svg + ui/images/browser/MediaBrowserIconAux.svg + ui/images/browser/MediaBrowserIconLibrary.svg + ui/images/browser/MediaBrowserIconMusicLibrary.svg + ui/images/browser/MediaBrowserIconNetwork.svg + ui/images/browser/MediaBrowserIconPictureLibrary.svg + ui/images/browser/MediaBrowserIconPlaylist.svg + ui/images/browser/MediaBrowserIconRecentlyPlayed.svg + ui/images/browser/MediaBrowserIconSiriusXM.svg + ui/images/browser/MediaBrowserIconTidal.svg + ui/images/browser/MediaBrowserIconTuneIn.svg + ui/images/browser/MediaBrowserIconUSB.svg + ui/images/browser/MediaBrowserIconVideoLibrary.svg + ui/images/browser/MediaBrowserIconVTuner.svg + ui/images/browser/MediaBrowserIconDisk.svg + ui/images/browser/BrowserIconFavorites.svg + ui/images/browser/BrowserIconMusic.svg + ui/images/browser/BrowserIconPicture.svg + ui/images/browser/BrowserIconVideo.svg + ui/images/browser/BrowserIconApplication.svg + ui/images/browser/BrowserIconDocument.svg + ui/images/browser/BrowserIconPackage.svg diff --git a/nymea-app/ui/components/MainPageTile.qml b/nymea-app/ui/components/MainPageTile.qml index 9b31d484..cd0a3c0c 100644 --- a/nymea-app/ui/components/MainPageTile.qml +++ b/nymea-app/ui/components/MainPageTile.qml @@ -9,6 +9,7 @@ Item { property alias iconName: colorIcon.name property alias fallbackIconName: fallbackIcon.name property alias iconColor: colorIcon.color + property alias backgroundImage: background.source property string text property bool disconnected: false property bool batteryCritical: false @@ -24,6 +25,19 @@ Item { Material.elevation: 1 padding: 0 + Image { + id: background + anchors.fill: parent + anchors.margins: 1 + z: -1 +// opacity: .5 +// Rectangle { +// anchors.fill: parent +// color: Material.background +// opacity: .5 +// } + } + contentItem: ItemDelegate { padding: 0; topPadding: 0; bottomPadding: 0 onClicked: root.clicked() @@ -35,6 +49,7 @@ Item { Layout.fillHeight: true Layout.margins: app.margins Item { + visible: background.status !== Image.Ready Layout.fillWidth: true Layout.fillHeight: true @@ -55,6 +70,7 @@ Item { Item { Layout.fillWidth: true Layout.fillHeight: true + visible: background.status !== Image.Ready Label { id: label @@ -77,6 +93,11 @@ Item { Layout.preferredHeight: app.iconSize + app.margins * 2 visible: root.contentItem.length > 1 + Rectangle { + anchors.fill: parent + color: Material.background + } + Rectangle { anchors.fill: parent color: Material.foreground diff --git a/nymea-app/ui/components/NymeaListItemDelegate.qml b/nymea-app/ui/components/NymeaListItemDelegate.qml index 1ac96205..b0768229 100644 --- a/nymea-app/ui/components/NymeaListItemDelegate.qml +++ b/nymea-app/ui/components/NymeaListItemDelegate.qml @@ -15,6 +15,7 @@ SwipeDelegate { property bool prominentSubText: true property string iconName + property string fallbackIcon property int iconSize: app.iconSize property color iconColor: app.accentColor property alias iconKeyColor: icon.keyColor @@ -32,14 +33,27 @@ SwipeDelegate { contentItem: RowLayout { id: innerLayout spacing: app.margins - ColorIcon { - id: icon + Item { Layout.preferredHeight: root.iconSize Layout.preferredWidth: height - name: root.iconName - color: root.iconColor - visible: root.iconName + visible: root.iconName || root.fallbackIcon + + ColorIcon { + id: icon + anchors.fill: parent + name: root.iconName + color: root.iconColor + visible: root.iconName + } + + ColorIcon { + anchors.fill: parent + name: root.fallbackIcon + color: root.iconColor + visible: root.fallbackIcon && (!root.iconName || icon.status === Image.Error) + } } + ColumnLayout { Layout.fillWidth: true Layout.fillHeight: true diff --git a/nymea-app/ui/devicepages/DeviceBrowserPage.qml b/nymea-app/ui/devicepages/DeviceBrowserPage.qml index c53a6366..535234cc 100644 --- a/nymea-app/ui/devicepages/DeviceBrowserPage.qml +++ b/nymea-app/ui/devicepages/DeviceBrowserPage.qml @@ -6,7 +6,7 @@ import "../components" Page { id: root - header: GuhHeader { + header: NymeaHeader { text: qsTr("Browse %1").arg(root.device.name) onBackPressed: pageStack.pop() } @@ -26,14 +26,17 @@ Page { id: listView anchors.fill: parent model: d.model + ScrollBar.vertical: ScrollBar {} - delegate: MeaListItemDelegate { + delegate: NymeaListItemDelegate { width: parent.width text: model.displayName progressive: model.browsable subText: model.description prominentSubText: false iconName: model.thumbnail + fallbackIcon: "../images/browser/" + model.icon + ".svg" + enabled: model.browsable || model.executable onClicked: { print("clicked:", model.id) diff --git a/nymea-app/ui/devicepages/DevicePageBase.qml b/nymea-app/ui/devicepages/DevicePageBase.qml index 40621a1c..478e609a 100644 --- a/nymea-app/ui/devicepages/DevicePageBase.qml +++ b/nymea-app/ui/devicepages/DevicePageBase.qml @@ -11,16 +11,25 @@ Page { property bool showLogsButton: true property bool showDetailsButton: true + property bool showBrowserButton: true + property bool popStackOnBackButton: true default property alias data: contentItem.data + signal backPressed() + header: NymeaHeader { text: device.name - onBackPressed: pageStack.pop() + onBackPressed: { + root.backPressed(); + if (root.popStackOnBackButton) { + pageStack.pop() + } + } HeaderButton { imageSource: "../images/folder-symbolic.svg" - visible: root.deviceClass.browsable + visible: root.deviceClass.browsable && root.showBrowserButton onClicked: { pageStack.push(Qt.resolvedUrl("DeviceBrowserPage.qml"), {device: root.device}) } diff --git a/nymea-app/ui/devicepages/MediaDevicePage.qml b/nymea-app/ui/devicepages/MediaDevicePage.qml index 8d0695a6..33b8ec23 100644 --- a/nymea-app/ui/devicepages/MediaDevicePage.qml +++ b/nymea-app/ui/devicepages/MediaDevicePage.qml @@ -9,6 +9,20 @@ import "../customviews" DevicePageBase { id: root + popStackOnBackButton: false + showBrowserButton: false + + onBackPressed: { + if (swipeView.currentIndex > 0) { + if (internalPageStack.depth > 1) { + internalPageStack.pop(); + } else { + swipeView.currentIndex = 0; + } + } else { + pageStack.pop(); + } + } function stateValue(name) { var stateType = root.deviceClass.stateTypes.findByName(name); @@ -24,132 +38,197 @@ DevicePageBase { readonly property State playbackState: device.states.getState(deviceClass.stateTypes.findByName("playbackStatus").id) - GridLayout { - id: contentColumn + SwipeView { + id: swipeView anchors.fill: parent - anchors.margins: app.margins - columns: app.landscape ? 2 : 1 - columnSpacing: app.margins - rowSpacing: app.margins - Pane { - Layout.fillWidth: true - Layout.fillHeight: true - Material.elevation: 2 - padding: 0 + Item { + GridLayout { + id: contentColumn + anchors.fill: parent + anchors.margins: app.margins + columns: app.landscape ? 2 : 1 + columnSpacing: app.margins + rowSpacing: app.margins - contentItem: Rectangle { - color: app.foregroundColor + Pane { + Layout.fillWidth: true + Layout.fillHeight: true + Layout.minimumWidth: parent.width / 2 + Material.elevation: 2 + padding: 0 - Image { - id: artworkImage - anchors.fill: parent - fillMode: Image.PreserveAspectFit - source: root.stateValue("artwork") - } + contentItem: Rectangle { + color: app.foregroundColor - ColorIcon { - id: fallback - anchors.fill: parent - anchors.margins: app.margins * 2 - name: root.stateValue("playerType") === "video" ? "../images/stock_video.svg" : "../images/stock_music.svg" - visible: artworkImage.status !== Image.Ready || artworkImage.source === "" - color: app.primaryColor - } - } - } + Image { + id: artworkImage + anchors.fill: parent + fillMode: Image.PreserveAspectFit + source: root.stateValue("artwork") + } - ColumnLayout { - Layout.fillWidth: true - spacing: app.margins - - Label { - Layout.fillWidth: true - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.WordWrap - maximumLineCount: 2 - elide: Text.ElideRight - font.pixelSize: app.largeFont - font.bold: true - text: root.stateValue("title") - } - Label { - Layout.fillWidth: true - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.WordWrap - maximumLineCount: 2 - elide: Text.ElideRight - text: root.stateValue("artist") - } - Label { - Layout.fillWidth: true - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.WordWrap - maximumLineCount: 2 - elide: Text.ElideRight - text: root.stateValue("collection") - } - - RowLayout { - Layout.fillWidth: true - Item { Layout.fillWidth: true } - - ProgressButton { - Layout.preferredHeight: app.iconSize - Layout.preferredWidth: height - imageSource: "../images/media-skip-backward.svg" - longpressImageSource: "../images/media-seek-backward.svg" - repeat: true - - onClicked: { - root.executeAction("skipBack") - } - onLongpressed: { - root.executeAction("fastRewind") - } - } - - Item { Layout.fillWidth: true } - - ProgressButton { - Layout.preferredHeight: app.iconSize * 2 - Layout.preferredWidth: height - imageSource: root.playbackState.value === "Playing" ? "../images/media-playback-pause.svg" : "../images/media-playback-start.svg" - longpressImageSource: "../images/media-playback-stop.svg" - longpressEnabled: root.playbackState.value !== "Stopped" - - onClicked: { - if (root.playbackState.value === "Playing") { - root.executeAction("pause") - } else { - root.executeAction("play") + ColorIcon { + id: fallback + anchors.fill: parent + anchors.margins: app.margins * 2 + name: root.stateValue("playerType") === "video" ? "../images/stock_video.svg" : "../images/stock_music.svg" + visible: artworkImage.status !== Image.Ready || artworkImage.source === "" + color: app.primaryColor } } - - onLongpressed: { - root.executeAction("stop") - } } - Item { Layout.fillWidth: true } - ProgressButton { - Layout.preferredHeight: app.iconSize - Layout.preferredWidth: height - imageSource: "../images/media-skip-forward.svg" - longpressImageSource: "../images/media-seek-forward.svg" - repeat: true - onClicked: { - root.executeAction("skipNext") + ColumnLayout { + Layout.fillWidth: true + spacing: app.margins + + Label { + Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + maximumLineCount: 2 + elide: Text.ElideRight + font.pixelSize: app.largeFont + font.bold: true + text: root.stateValue("title") } - onLongpressed: { - root.executeAction("fastForward") + Label { + Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + maximumLineCount: 2 + elide: Text.ElideRight + text: root.stateValue("artist") + } + Label { + Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + maximumLineCount: 2 + elide: Text.ElideRight + text: root.stateValue("collection") + } + + RowLayout { + Layout.fillWidth: true + Item { Layout.fillWidth: true } + + ProgressButton { + Layout.preferredHeight: app.iconSize + Layout.preferredWidth: height + imageSource: "../images/media-skip-backward.svg" + longpressImageSource: "../images/media-seek-backward.svg" + repeat: true + + onClicked: { + root.executeAction("skipBack") + } + onLongpressed: { + root.executeAction("fastRewind") + } + } + + Item { Layout.fillWidth: true } + + ProgressButton { + Layout.preferredHeight: app.iconSize * 2 + Layout.preferredWidth: height + imageSource: root.playbackState.value === "Playing" ? "../images/media-playback-pause.svg" : "../images/media-playback-start.svg" + longpressImageSource: "../images/media-playback-stop.svg" + longpressEnabled: root.playbackState.value !== "Stopped" + + onClicked: { + if (root.playbackState.value === "Playing") { + root.executeAction("pause") + } else { + root.executeAction("play") + } + } + + onLongpressed: { + root.executeAction("stop") + } + } + + Item { Layout.fillWidth: true } + ProgressButton { + Layout.preferredHeight: app.iconSize + Layout.preferredWidth: height + imageSource: "../images/media-skip-forward.svg" + longpressImageSource: "../images/media-seek-forward.svg" + repeat: true + onClicked: { + root.executeAction("skipNext") + } + onLongpressed: { + root.executeAction("fastForward") + } + } + Item { Layout.fillWidth: true } } } - Item { Layout.fillWidth: true } } } + + Item { + + StackView { + id: internalPageStack + anchors.fill: parent + initialItem: internalBrowserPage + + Component { + id: internalBrowserPage + ListView { + id: listView + anchors.fill: parent + model: browserItems + ScrollBar.vertical: ScrollBar {} + + property string nodeId: "" + + // Need to keep a explicit property here or the GC will eat it too early + property BrowserItems browserItems: null + Component.onCompleted: { + browserItems = engine.deviceManager.browseDevice(root.device.id, nodeId); + } + + delegate: NymeaListItemDelegate { + width: parent.width + text: model.displayName + progressive: model.browsable + subText: model.description + prominentSubText: false + iconName: model.thumbnail + fallbackIcon: "../images/browser/" + (model.mediaIcon && model.mediaIcon !== "MediaBrowserIconNone" ? model.mediaIcon : model.icon) + ".svg" + enabled: model.browsable || model.executable + + onClicked: { + print("clicked:", model.id) + if (model.executable) { + engine.deviceManager.executeBrowserItem(root.device.id, model.id) + } else if (model.browsable) { + internalPageStack.push(internalBrowserPage, {device: root.device, nodeId: model.id}) + } + } + } + + BusyIndicator { + anchors.centerIn: parent + running: listView.model.busy + visible: running + } + } + } + + } + + + } } + Component { id: volumeSliderPaneComponent Dialog { @@ -158,6 +237,7 @@ DevicePageBase { topPadding: app.margins / 2 rightPadding: 0 bottomPadding: app.margins / 2 + modal: true contentItem: ColumnLayout { Slider { @@ -193,71 +273,102 @@ DevicePageBase { footer: Pane { Material.elevation: 1 - height: 50 + height: 52 padding: 0 - contentItem: RowLayout { -// Item { -// Layout.fillWidth: true; Layout.fillHeight: true -// HeaderButton { -// anchors.centerIn: parent -// imageSource: "../images/media-playlist.svg" -// } -// } + contentItem: ColumnLayout { Item { - Layout.fillWidth: true; Layout.fillHeight: true - visible: root.deviceClass.interfaces.indexOf("shufflerepeat") >= 0 - HeaderButton { - anchors.centerIn: parent - imageSource: root.stateValue("repeat") === "One" ? "../images/media-playlist-repeat-one.svg" : "../images/media-playlist-repeat.svg" - color: root.stateValue("repeat") === "None" ? keyColor : app.accentColor - property var allowedValues: ["None", "All", "One"] - onClicked: { - var params = [] - var param = {} - param["paramTypeId"] = root.deviceClass.actionTypes.findByName("repeat").id; - param["value"] = allowedValues[(allowedValues.indexOf(root.stateValue("repeat")) + 1) % 3] - params.push(param) - root.executeAction("repeat", params) - } + Layout.fillWidth: true + Layout.preferredHeight: 2 + Rectangle { + height: parent.height + width: parent.width / 2 + color: app.accentColor + x: swipeView.currentIndex * width + Behavior on x { NumberAnimation { duration: 150 } } } } - Item { - Layout.fillWidth: true; Layout.fillHeight: true - visible: root.deviceClass.interfaces.indexOf("shufflerepeat") >= 0 - HeaderButton { - anchors.centerIn: parent - imageSource: "../images/media-playlist-shuffle.svg" - color: root.stateValue("shuffle") ? app.accentColor: keyColor - onClicked: { - var params = [] - var param = {} - param["paramTypeId"] = root.deviceClass.actionTypes.findByName("shuffle").id; - param["value"] = !root.stateValue("shuffle") - params.push(param) - root.executeAction("shuffle", params) + + RowLayout { + Item { + Layout.fillHeight: true + Layout.preferredWidth: root.deviceClass.browsable && swipeView.currentIndex > 0 ? parent.width / 4 : 0 + Behavior on Layout.preferredWidth { NumberAnimation {} } + HeaderButton { + anchors.centerIn: parent + imageSource: "../images/back.svg" + opacity: root.deviceClass.browsable && swipeView.currentIndex == 1 ? 1 : 0 + Behavior on opacity { NumberAnimation {} } + onClicked: swipeView.currentIndex = 0 } } - } - Item { - id: volumeButtonContainer - Layout.fillWidth: true; Layout.fillHeight: true - HeaderButton { - id: volumeButton - anchors.centerIn: parent - imageSource: "../images/audio-speakers-symbolic.svg" - onClicked: { - print("..."); - print(volumeButton.x, volumeButton.y) - print(Qt.point(volumeButton.x, volumeButton.y)) - print(volumeButton.mapToItem(root, volumeButton.x,0)) - var buttonPosition = root.mapFromItem(volumeButtonContainer, volumeButton.x, 0) - var sliderHeight = 200 - var props = {} - props["x"] = buttonPosition.x - props["y"] = root.height - sliderHeight - root.footer.height - props["height"] = sliderHeight - var sliderPane = volumeSliderPaneComponent.createObject(root, props) - sliderPane.open() + Item { + Layout.fillWidth: true; Layout.fillHeight: true + visible: root.deviceClass.interfaces.indexOf("shufflerepeat") >= 0 + HeaderButton { + anchors.centerIn: parent + imageSource: root.stateValue("repeat") === "One" ? "../images/media-playlist-repeat-one.svg" : "../images/media-playlist-repeat.svg" + color: root.stateValue("repeat") === "None" ? keyColor : app.accentColor + property var allowedValues: ["None", "All", "One"] + onClicked: { + var params = [] + var param = {} + param["paramTypeId"] = root.deviceClass.actionTypes.findByName("repeat").id; + param["value"] = allowedValues[(allowedValues.indexOf(root.stateValue("repeat")) + 1) % 3] + params.push(param) + root.executeAction("repeat", params) + } + } + } + Item { + Layout.fillWidth: true; Layout.fillHeight: true + visible: root.deviceClass.interfaces.indexOf("shufflerepeat") >= 0 + HeaderButton { + anchors.centerIn: parent + imageSource: "../images/media-playlist-shuffle.svg" + color: root.stateValue("shuffle") ? app.accentColor: keyColor + onClicked: { + var params = [] + var param = {} + param["paramTypeId"] = root.deviceClass.actionTypes.findByName("shuffle").id; + param["value"] = !root.stateValue("shuffle") + params.push(param) + root.executeAction("shuffle", params) + } + } + } + Item { + id: volumeButtonContainer + Layout.fillWidth: true; Layout.fillHeight: true + HeaderButton { + id: volumeButton + anchors.centerIn: parent + imageSource: "../images/audio-speakers-symbolic.svg" + onClicked: { + print("..."); + print(volumeButton.x, volumeButton.y) + print(Qt.point(volumeButton.x, volumeButton.y)) + print(volumeButton.mapToItem(root, volumeButton.x,0)) + var buttonPosition = root.mapFromItem(volumeButtonContainer, volumeButton.x, 0) + var sliderHeight = 200 + var props = {} + props["x"] = buttonPosition.x + props["y"] = root.height - sliderHeight - root.footer.height + props["height"] = sliderHeight + var sliderPane = volumeSliderPaneComponent.createObject(root, props) + sliderPane.open() + } + } + } + Item { + Layout.fillHeight: true + Layout.preferredWidth: root.deviceClass.browsable && swipeView.currentIndex == 0 ? parent.width / 4 : 0 + Behavior on Layout.preferredWidth { NumberAnimation {} } + HeaderButton { + anchors.centerIn: parent + imageSource: "../images/next.svg" + onClicked: swipeView.currentIndex = 1 + opacity: root.deviceClass.browsable && swipeView.currentIndex == 0 ? 1 : 0 + Behavior on opacity { NumberAnimation {} } } } } diff --git a/nymea-app/ui/images/browser/BrowserIconApplication.svg b/nymea-app/ui/images/browser/BrowserIconApplication.svg new file mode 100644 index 00000000..87b3400d --- /dev/null +++ b/nymea-app/ui/images/browser/BrowserIconApplication.svg @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/nymea-app/ui/images/browser/BrowserIconDocument.svg b/nymea-app/ui/images/browser/BrowserIconDocument.svg new file mode 100644 index 00000000..4110f70e --- /dev/null +++ b/nymea-app/ui/images/browser/BrowserIconDocument.svg @@ -0,0 +1,177 @@ + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/nymea-app/ui/images/browser/BrowserIconFavorites.svg b/nymea-app/ui/images/browser/BrowserIconFavorites.svg new file mode 120000 index 00000000..2ff3eb55 --- /dev/null +++ b/nymea-app/ui/images/browser/BrowserIconFavorites.svg @@ -0,0 +1 @@ +../starred.svg \ No newline at end of file diff --git a/nymea-app/ui/images/browser/BrowserIconFile.svg b/nymea-app/ui/images/browser/BrowserIconFile.svg new file mode 100644 index 00000000..aaa48e15 --- /dev/null +++ b/nymea-app/ui/images/browser/BrowserIconFile.svg @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/nymea-app/ui/images/browser/BrowserIconFolder.svg b/nymea-app/ui/images/browser/BrowserIconFolder.svg new file mode 100644 index 00000000..50289d3e --- /dev/null +++ b/nymea-app/ui/images/browser/BrowserIconFolder.svg @@ -0,0 +1,17 @@ + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/nymea-app/ui/images/browser/BrowserIconMusic.svg b/nymea-app/ui/images/browser/BrowserIconMusic.svg new file mode 100644 index 00000000..b43bc37d --- /dev/null +++ b/nymea-app/ui/images/browser/BrowserIconMusic.svg @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/nymea-app/ui/images/browser/BrowserIconPackage.svg b/nymea-app/ui/images/browser/BrowserIconPackage.svg new file mode 120000 index 00000000..22864336 --- /dev/null +++ b/nymea-app/ui/images/browser/BrowserIconPackage.svg @@ -0,0 +1 @@ +../plugin.svg \ No newline at end of file diff --git a/nymea-app/ui/images/browser/BrowserIconPicture.svg b/nymea-app/ui/images/browser/BrowserIconPicture.svg new file mode 100644 index 00000000..19bb10c9 --- /dev/null +++ b/nymea-app/ui/images/browser/BrowserIconPicture.svg @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + diff --git a/nymea-app/ui/images/browser/BrowserIconVideo.svg b/nymea-app/ui/images/browser/BrowserIconVideo.svg new file mode 100644 index 00000000..56c5a4f4 --- /dev/null +++ b/nymea-app/ui/images/browser/BrowserIconVideo.svg @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/nymea-app/ui/images/browser/MediaBrowserIconAirable.svg b/nymea-app/ui/images/browser/MediaBrowserIconAirable.svg new file mode 100644 index 00000000..fa2c1016 --- /dev/null +++ b/nymea-app/ui/images/browser/MediaBrowserIconAirable.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/nymea-app/ui/images/browser/MediaBrowserIconAmazon.svg b/nymea-app/ui/images/browser/MediaBrowserIconAmazon.svg new file mode 100644 index 00000000..e3381f3b --- /dev/null +++ b/nymea-app/ui/images/browser/MediaBrowserIconAmazon.svg @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/nymea-app/ui/images/browser/MediaBrowserIconAux.svg b/nymea-app/ui/images/browser/MediaBrowserIconAux.svg new file mode 120000 index 00000000..a3c53ece --- /dev/null +++ b/nymea-app/ui/images/browser/MediaBrowserIconAux.svg @@ -0,0 +1 @@ +../action.svg \ No newline at end of file diff --git a/nymea-app/ui/images/browser/MediaBrowserIconDisk.svg b/nymea-app/ui/images/browser/MediaBrowserIconDisk.svg new file mode 100644 index 00000000..1af432c7 --- /dev/null +++ b/nymea-app/ui/images/browser/MediaBrowserIconDisk.svg @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + diff --git a/nymea-app/ui/images/browser/MediaBrowserIconLibrary.svg b/nymea-app/ui/images/browser/MediaBrowserIconLibrary.svg new file mode 120000 index 00000000..1762fbfe --- /dev/null +++ b/nymea-app/ui/images/browser/MediaBrowserIconLibrary.svg @@ -0,0 +1 @@ +../mediaplayer-app-symbolic.svg \ No newline at end of file diff --git a/nymea-app/ui/images/browser/MediaBrowserIconMusicLibrary.svg b/nymea-app/ui/images/browser/MediaBrowserIconMusicLibrary.svg new file mode 120000 index 00000000..cf37aa30 --- /dev/null +++ b/nymea-app/ui/images/browser/MediaBrowserIconMusicLibrary.svg @@ -0,0 +1 @@ +BrowserIconMusic.svg \ No newline at end of file diff --git a/nymea-app/ui/images/browser/MediaBrowserIconNetwork.svg b/nymea-app/ui/images/browser/MediaBrowserIconNetwork.svg new file mode 100644 index 00000000..0bf511ee --- /dev/null +++ b/nymea-app/ui/images/browser/MediaBrowserIconNetwork.svg @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nymea-app/ui/images/browser/MediaBrowserIconPictureLibrary.svg b/nymea-app/ui/images/browser/MediaBrowserIconPictureLibrary.svg new file mode 120000 index 00000000..87b2075a --- /dev/null +++ b/nymea-app/ui/images/browser/MediaBrowserIconPictureLibrary.svg @@ -0,0 +1 @@ +BrowserIconPicture.svg \ No newline at end of file diff --git a/nymea-app/ui/images/browser/MediaBrowserIconPlaylist.svg b/nymea-app/ui/images/browser/MediaBrowserIconPlaylist.svg new file mode 100644 index 00000000..3ab686d4 --- /dev/null +++ b/nymea-app/ui/images/browser/MediaBrowserIconPlaylist.svg @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/nymea-app/ui/images/browser/MediaBrowserIconRecentlyPlayed.svg b/nymea-app/ui/images/browser/MediaBrowserIconRecentlyPlayed.svg new file mode 120000 index 00000000..ccbc6e10 --- /dev/null +++ b/nymea-app/ui/images/browser/MediaBrowserIconRecentlyPlayed.svg @@ -0,0 +1 @@ +MediaBrowserIconPlaylist.svg \ No newline at end of file diff --git a/nymea-app/ui/images/browser/MediaBrowserIconSiriusXM.svg b/nymea-app/ui/images/browser/MediaBrowserIconSiriusXM.svg new file mode 100644 index 00000000..d6121943 --- /dev/null +++ b/nymea-app/ui/images/browser/MediaBrowserIconSiriusXM.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/nymea-app/ui/images/browser/MediaBrowserIconSpotify.svg b/nymea-app/ui/images/browser/MediaBrowserIconSpotify.svg new file mode 100644 index 00000000..ef1fdece --- /dev/null +++ b/nymea-app/ui/images/browser/MediaBrowserIconSpotify.svg @@ -0,0 +1,17 @@ + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/nymea-app/ui/images/browser/MediaBrowserIconTidal.svg b/nymea-app/ui/images/browser/MediaBrowserIconTidal.svg new file mode 100644 index 00000000..b212a6dd --- /dev/null +++ b/nymea-app/ui/images/browser/MediaBrowserIconTidal.svg @@ -0,0 +1,99 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/nymea-app/ui/images/browser/MediaBrowserIconTuneIn.svg b/nymea-app/ui/images/browser/MediaBrowserIconTuneIn.svg new file mode 100644 index 00000000..79c73f9b --- /dev/null +++ b/nymea-app/ui/images/browser/MediaBrowserIconTuneIn.svg @@ -0,0 +1,86 @@ + + + +image/svg+xml + + + + + + + + + + + + + \ No newline at end of file diff --git a/nymea-app/ui/images/browser/MediaBrowserIconUSB.svg b/nymea-app/ui/images/browser/MediaBrowserIconUSB.svg new file mode 100644 index 00000000..9d988a71 --- /dev/null +++ b/nymea-app/ui/images/browser/MediaBrowserIconUSB.svg @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/nymea-app/ui/images/browser/MediaBrowserIconVTuner.svg b/nymea-app/ui/images/browser/MediaBrowserIconVTuner.svg new file mode 100644 index 00000000..6b293f0e --- /dev/null +++ b/nymea-app/ui/images/browser/MediaBrowserIconVTuner.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/nymea-app/ui/images/browser/MediaBrowserIconVideoLibrary.svg b/nymea-app/ui/images/browser/MediaBrowserIconVideoLibrary.svg new file mode 120000 index 00000000..e7788653 --- /dev/null +++ b/nymea-app/ui/images/browser/MediaBrowserIconVideoLibrary.svg @@ -0,0 +1 @@ +BrowserIconVideo.svg \ No newline at end of file diff --git a/nymea-app/ui/mainviews/DevicesPageDelegate.qml b/nymea-app/ui/mainviews/DevicesPageDelegate.qml index da93c081..a93fc9c4 100644 --- a/nymea-app/ui/mainviews/DevicesPageDelegate.qml +++ b/nymea-app/ui/mainviews/DevicesPageDelegate.qml @@ -13,6 +13,14 @@ MainPageTile { disconnected: devicesSubProxyConnectables.count > 0 batteryCritical: devicesSubProxyBattery.count > 0 + backgroundImage: currentDevice.deviceClass.interfaces.indexOf("mediametadataprovider") >= 0 ? + currentDevice.states.getState(currentDevice.deviceClass.stateTypes.findByName("artwork").id).value : "" + + property int currentDeviceIndex: 0 + readonly property Device currentDevice: devicesProxy.get(currentDeviceIndex) +// readonly property State currentBackgroundState: currentDevice.state + + onClicked: { var page; switch (model.name) {