fix(StatusTagSelector): move suggestions popup inside component (#598)

Closes #531
This commit is contained in:
Alexandra Betouni 2022-03-25 00:03:36 +02:00 committed by GitHub
parent aa91a88be7
commit 41f67b59e9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 161 additions and 160 deletions

View File

@ -1,8 +1,6 @@
import QtQuick 2.12 import QtQuick 2.12
import QtQuick.Controls 2.12 import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12 import QtQuick.Layouts 1.12
import QtQml.Models 2.2
import QtGraphicalEffects 1.0
import StatusQ.Controls 0.1 import StatusQ.Controls 0.1
import StatusQ.Components 0.1 import StatusQ.Components 0.1
@ -28,33 +26,19 @@ Page {
Layout.fillWidth: true Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
Layout.leftMargin: 17 Layout.leftMargin: 17
implicitHeight: 44 maxHeight: root.height
toLabelText: qsTr("To: ") toLabelText: qsTr("To: ")
warningText: qsTr("5 USER LIMIT REACHED") warningText: qsTr("USER LIMIT REACHED")
//simulate model filtering, TODO this listLabel: qsTr("Contacts")
//makes more sense to be provided by the backend
//figure how real implementation should look like
property ListModel sortedList: ListModel { }
onTextChanged: { onTextChanged: {
sortedList.clear(); sortModel(root.contactsModel);
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;
}
} }
Component.onCompleted: { sortModel(root.contactsModel); }
} }
StatusButton { StatusButton {
implicitHeight: 44 implicitHeight: 44
Layout.alignment: Qt.AlignTop
enabled: (tagSelector.namesModel.count > 0) enabled: (tagSelector.namesModel.count > 0)
text: "Confirm" text: "Confirm"
} }
@ -62,138 +46,7 @@ Page {
contentItem: Item { contentItem: Item {
anchors.fill: parent anchors.fill: parent
anchors.topMargin: headerRow.height + 16 anchors.topMargin: 68
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();
}
}
}
StatusBaseText { StatusBaseText {
visible: (contactsModel.count === 0) visible: (contactsModel.count === 0)

View File

@ -51,6 +51,6 @@ Item {
anchors.centerIn: parent anchors.centerIn: parent
namesModel: root.asortedContacts namesModel: root.asortedContacts
toLabelText: qsTr("To: ") toLabelText: qsTr("To: ")
warningText: qsTr("5 USER LIMIT REACHED") warningText: qsTr("USER LIMIT REACHED")
} }
} }

View File

@ -1,6 +1,7 @@
import QtQuick 2.14 import QtQuick 2.14
import QtQuick.Layouts 1.12 import QtQuick.Layouts 1.12
import QtQuick.Controls 2.14 import QtQuick.Controls 2.14
import QtGraphicalEffects 1.0
import StatusQ.Core 0.1 import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
@ -9,13 +10,18 @@ Item {
id: root id: root
implicitWidth: 448 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 textEdit: edit
property alias text: edit.text property alias text: edit.text
property string warningText: "" property string warningText: ""
property string toLabelText: "" property string toLabelText: ""
property string listLabel: ""
property int nameCountLimit: 5 property int nameCountLimit: 5
property ListModel sortedList: ListModel { }
property ListModel namesModel: ListModel { } property ListModel namesModel: ListModel { }
function find(model, criteria) { 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 addMember(string memberId)
signal removeMember(string memberId) signal removeMember(string memberId)
Rectangle { Rectangle {
anchors.fill: parent id: tagSelectorRect
width: parent.width
height: 44
radius: 8 radius: 8
color: Theme.palette.baseColor2 color: Theme.palette.baseColor2
@ -52,7 +77,8 @@ Item {
} }
ScrollView { ScrollView {
Layout.fillWidth: true Layout.preferredWidth: (namesList.contentWidth > (parent.width - 142)) ?
(parent.width - 142) : namesList.contentWidth
implicitHeight: 30 implicitHeight: 30
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
visible: (namesList.count > 0) visible: (namesList.count > 0)
@ -66,8 +92,8 @@ Item {
model: namesModel model: namesModel
orientation: ListView.Horizontal orientation: ListView.Horizontal
spacing: 8 spacing: 8
onContentWidthChanged: { onCountChanged: {
positionViewAtEnd(); contentX = contentWidth;
} }
delegate: Rectangle { delegate: Rectangle {
id: nameDelegate 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);
}
}
}
}
}
} }