From 511c1f7d4cd6603afe6c9df2af33b5aa15648503 Mon Sep 17 00:00:00 2001 From: Alexandra Betouni <31625338+alexandraB99@users.noreply.github.com> Date: Fri, 25 Mar 2022 00:03:36 +0200 Subject: [PATCH] fix(StatusTagSelector): move suggestions popup inside component (#598) Closes #531 --- ui/StatusQ/sandbox/demoapp/CreateChatView.qml | 161 +----------------- .../sandbox/pages/StatusTagSelectorPage.qml | 2 +- .../StatusQ/Components/StatusTagSelector.qml | 158 ++++++++++++++++- 3 files changed, 161 insertions(+), 160 deletions(-) diff --git a/ui/StatusQ/sandbox/demoapp/CreateChatView.qml b/ui/StatusQ/sandbox/demoapp/CreateChatView.qml index 5fc7990d55..ea949acf82 100644 --- a/ui/StatusQ/sandbox/demoapp/CreateChatView.qml +++ b/ui/StatusQ/sandbox/demoapp/CreateChatView.qml @@ -1,8 +1,6 @@ import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 -import QtQml.Models 2.2 -import QtGraphicalEffects 1.0 import StatusQ.Controls 0.1 import StatusQ.Components 0.1 @@ -28,33 +26,19 @@ Page { Layout.fillWidth: true Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft Layout.leftMargin: 17 - implicitHeight: 44 + maxHeight: root.height toLabelText: qsTr("To: ") - warningText: qsTr("5 USER LIMIT REACHED") - //simulate model filtering, TODO this - //makes more sense to be provided by the backend - //figure how real implementation should look like - property ListModel sortedList: ListModel { } + warningText: qsTr("USER LIMIT REACHED") + listLabel: qsTr("Contacts") onTextChanged: { - sortedList.clear(); - if (text !== "") { - for (var i = 0; i < contactsModel.count; i++ ) { - var entry = contactsModel.get(i); - if (entry.name.toLowerCase().includes(text.toLowerCase())) { - sortedList.insert(sortedList.count, {"publicId": entry.publicId, "name": entry.name, - "icon": entry.icon, "isIdenticon": entry.isIdenticon, - "onlineStatus": entry.onlineStatus}); - userListView.model = sortedList; - } - } - } else { - userListView.model = contactsModel; - } + sortModel(root.contactsModel); } + Component.onCompleted: { sortModel(root.contactsModel); } } StatusButton { implicitHeight: 44 + Layout.alignment: Qt.AlignTop enabled: (tagSelector.namesModel.count > 0) text: "Confirm" } @@ -62,138 +46,7 @@ Page { contentItem: Item { anchors.fill: parent - anchors.topMargin: headerRow.height + 16 - - Item { - anchors.fill: parent - visible: (contactsModel.count > 0) - - StatusBaseText { - id: contactsLabel - font.pixelSize: 15 - anchors.left: parent.left - anchors.leftMargin: 8 - color: Theme.palette.baseColor1 - text: qsTr("Contacts") - } - Control { - width: 360 - anchors { - top: contactsLabel.bottom - topMargin: 8//Style.current.padding - bottom: !statusPopupMenuBackgroundContent.visible ? parent.bottom : undefined - bottomMargin: 20//Style.current.bigPadding - } - height: 16 + (!statusPopupMenuBackgroundContent.visible ? parent.height : - (((userListView.count * 64) > parent.height) ? parent.height : (userListView.count * 64))) - x: (statusPopupMenuBackgroundContent.visible && (tagSelector.namesModel.count > 0) && - ((tagSelector.textEdit.x + 24 + statusPopupMenuBackgroundContent.width) < parent.width)) - ? (tagSelector.textEdit.x + 24) : 0 - background: Rectangle { - id: statusPopupMenuBackgroundContent - anchors.fill: parent - visible: (tagSelector.sortedList.count > 0) - color: Theme.palette.statusPopupMenu.backgroundColor - radius: 8 - layer.enabled: true - layer.effect: DropShadow { - width: statusPopupMenuBackgroundContent.width - height: statusPopupMenuBackgroundContent.height - x: statusPopupMenuBackgroundContent.x - visible: statusPopupMenuBackgroundContent.visible - source: statusPopupMenuBackgroundContent - horizontalOffset: 0 - verticalOffset: 4 - radius: 12 - samples: 25 - spread: 0.2 - color: Theme.palette.dropShadow - } - } - contentItem: ListView { - id: userListView - anchors.fill: parent - anchors.topMargin: 8 - anchors.bottomMargin: 8 - clip: true - model: contactsModel - ScrollBar.vertical: ScrollBar { - policy: ScrollBar.AsNeeded - } - boundsBehavior: Flickable.StopAtBounds - delegate: Item { - id: wrapper - anchors.right: parent.right - anchors.left: parent.left - height: 64 - property bool hovered: false - Rectangle { - id: rectangle - anchors.fill: parent - anchors.rightMargin: 8 - anchors.leftMargin: 8 - radius: 8 - visible: (tagSelector.sortedList.count > 0) - color: (wrapper.hovered) ? Theme.palette.baseColor2 : "transparent" - } - - StatusSmartIdenticon { - id: contactImage - anchors.left: parent.left - anchors.leftMargin: 16//Style.current.padding - anchors.verticalCenter: parent.verticalCenter - name: model.name - icon: StatusIconSettings { - width: 28 - height: 28 - letterSize: 15 - } - image: StatusImageSettings { - width: 28 - height: 28 - source: model.icon - isIdenticon: model.isIdenticon - } - } - - StatusBaseText { - id: contactInfo - text: model.name - anchors.right: parent.right - anchors.rightMargin: 8 - anchors.left: contactImage.right - anchors.leftMargin: 16 - anchors.verticalCenter: parent.verticalCenter - elide: Text.ElideRight - color: Theme.palette.directColor1 - font.weight: Font.Medium - font.pixelSize: 15 - } - - MouseArea { - cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor - acceptedButtons: Qt.LeftButton | Qt.RightButton - anchors.fill: parent - hoverEnabled: true - onEntered: { - wrapper.hovered = true; - } - onExited: { - wrapper.hovered = false; - } - onClicked: { - tagSelector.insertTag(model.name, model.publicId); - } - } - } - } - } - Component.onCompleted: { - if (visible) { - tagSelector.textEdit.forceActiveFocus(); - } - } - } + anchors.topMargin: 68 StatusBaseText { visible: (contactsModel.count === 0) diff --git a/ui/StatusQ/sandbox/pages/StatusTagSelectorPage.qml b/ui/StatusQ/sandbox/pages/StatusTagSelectorPage.qml index 3de2c69e1d..6afbb4bb74 100644 --- a/ui/StatusQ/sandbox/pages/StatusTagSelectorPage.qml +++ b/ui/StatusQ/sandbox/pages/StatusTagSelectorPage.qml @@ -51,6 +51,6 @@ Item { anchors.centerIn: parent namesModel: root.asortedContacts toLabelText: qsTr("To: ") - warningText: qsTr("5 USER LIMIT REACHED") + warningText: qsTr("USER LIMIT REACHED") } } diff --git a/ui/StatusQ/src/StatusQ/Components/StatusTagSelector.qml b/ui/StatusQ/src/StatusQ/Components/StatusTagSelector.qml index 6865ba9acd..1fd719cfd4 100644 --- a/ui/StatusQ/src/StatusQ/Components/StatusTagSelector.qml +++ b/ui/StatusQ/src/StatusQ/Components/StatusTagSelector.qml @@ -1,6 +1,7 @@ import QtQuick 2.14 import QtQuick.Layouts 1.12 import QtQuick.Controls 2.14 +import QtGraphicalEffects 1.0 import StatusQ.Core 0.1 import StatusQ.Core.Theme 0.1 @@ -9,13 +10,18 @@ Item { id: root implicitWidth: 448 - implicitHeight: 44 + implicitHeight: 44 + ((userListView.count > 0) ? 44 + ((((userListView.count * 64) > root.maxHeight) + ? root.maxHeight : (userListView.count * 64))) :0) + property real maxHeight property alias textEdit: edit property alias text: edit.text property string warningText: "" property string toLabelText: "" + property string listLabel: "" property int nameCountLimit: 5 + + property ListModel sortedList: ListModel { } property ListModel namesModel: ListModel { } function find(model, criteria) { @@ -31,11 +37,30 @@ Item { } } + function sortModel(inputModel) { + sortedList.clear(); + if (text !== "") { + for (var i = 0; i < inputModel.count; i++ ) { + var entry = inputModel.get(i); + if (entry.name.toLowerCase().includes(text.toLowerCase())) { + sortedList.insert(sortedList.count, {"publicId": entry.publicId, "name": entry.name, + "icon": entry.icon, "isIdenticon": entry.isIdenticon, + "onlineStatus": entry.onlineStatus}); + userListView.model = sortedList; + } + } + } else { + userListView.model = inputModel; + } + } + signal addMember(string memberId) signal removeMember(string memberId) Rectangle { - anchors.fill: parent + id: tagSelectorRect + width: parent.width + height: 44 radius: 8 color: Theme.palette.baseColor2 @@ -52,7 +77,8 @@ Item { } ScrollView { - Layout.fillWidth: true + Layout.preferredWidth: (namesList.contentWidth > (parent.width - 142)) ? + (parent.width - 142) : namesList.contentWidth implicitHeight: 30 Layout.alignment: Qt.AlignVCenter visible: (namesList.count > 0) @@ -66,8 +92,8 @@ Item { model: namesModel orientation: ListView.Horizontal spacing: 8 - onContentWidthChanged: { - positionViewAtEnd(); + onCountChanged: { + contentX = contentWidth; } delegate: Rectangle { id: nameDelegate @@ -134,4 +160,126 @@ Item { } } } + + StatusBaseText { + id: contactsLabel + font.pixelSize: 15 + anchors.left: parent.left + anchors.leftMargin: 8 + anchors.top: tagSelectorRect.bottom + anchors.topMargin: 32 + visible: (namesModel.count === 0) + color: Theme.palette.baseColor1 + text: root.listLabel + } + + Control { + id: suggestionsContainer + width: 360 + anchors { + top: (root.sortedList.count > 0) ? tagSelectorRect.bottom : contactsLabel.bottom + topMargin: 8//Style.current.padding + bottom: parent.bottom + bottomMargin: 20//Style.current.bigPadding + } + visible: ((root.namesModel.count === 0) || (root.sortedList.count > 0)) + x: ((root.namesModel.count > 0) && ((edit.x + 8) <= (root.width - suggestionsContainer.width))) + ? (edit.x + 8) : 0 + background: Rectangle { + id: bgRect + anchors.fill: parent + visible: (root.sortedList.count > 0) + color: Theme.palette.statusPopupMenu.backgroundColor + radius: 8 + layer.enabled: true + layer.effect: DropShadow { + width: bgRect.width + height: bgRect.height + x: bgRect.x + source: bgRect + horizontalOffset: 0 + verticalOffset: 4 + radius: 12 + samples: 25 + spread: 0.2 + color: Theme.palette.dropShadow + } + } + contentItem: ListView { + id: userListView + anchors.fill: parent + anchors.topMargin: 8 + anchors.bottomMargin: 8 + clip: true + ScrollBar.vertical: ScrollBar { + policy: ScrollBar.AsNeeded + } + boundsBehavior: Flickable.StopAtBounds + delegate: Item { + id: wrapper + anchors.right: parent.right + anchors.left: parent.left + height: 64 + property bool hovered: false + Rectangle { + id: rectangle + anchors.fill: parent + anchors.rightMargin: 8 + anchors.leftMargin: 8 + radius: 8 + visible: (root.sortedList.count > 0) + color: (wrapper.hovered) ? Theme.palette.baseColor2 : "transparent" + } + + StatusSmartIdenticon { + id: contactImage + anchors.left: parent.left + anchors.leftMargin: 16//Style.current.padding + anchors.verticalCenter: parent.verticalCenter + name: model.name + icon: StatusIconSettings { + width: 40 + height: 40 + letterSize: 15 + } + image: StatusImageSettings { + width: 40 + height: 40 + source: model.icon + isIdenticon: model.isIdenticon + } + } + + StatusBaseText { + id: contactInfo + text: model.name + anchors.right: parent.right + anchors.rightMargin: 8 + anchors.left: contactImage.right + anchors.leftMargin: 16 + anchors.verticalCenter: parent.verticalCenter + elide: Text.ElideRight + color: Theme.palette.directColor1 + font.weight: Font.Medium + font.pixelSize: 15 + } + + MouseArea { + cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor + acceptedButtons: Qt.LeftButton | Qt.RightButton + anchors.fill: parent + hoverEnabled: true + onEntered: { + wrapper.hovered = true; + } + onExited: { + wrapper.hovered = false; + } + onClicked: { + root.insertTag(model.name, model.publicId); + } + } + } + } + } }