fix(@desktop/Chat): Group chat popup member list doesn't have proper visuals

fixes #4176
This commit is contained in:
Khushboo Mehta 2021-11-30 11:50:53 +01:00 committed by Khushboo-dev-cpp
parent 33c3f2278b
commit 0fbdbdbd15
6 changed files with 202 additions and 305 deletions

@ -1 +1 @@
Subproject commit 419b73845646354ea103b665ed8379b591ebc8e8 Subproject commit e54211cb994ee8a650c49553c1e761670ea3d4f1

View File

@ -1,47 +1,54 @@
import QtQuick 2.13 import QtQuick 2.13
import QtQuick.Controls 2.3 import QtQuick.Controls 2.3
import StatusQ.Components 0.1
import StatusQ.Controls 0.1
import utils 1.0 import utils 1.0
import "../controls"
ScrollView { ScrollView {
property alias membersData: membersData id: contactListPanel
property alias model: groupMembers.model
property string searchString property string searchString
property bool selectMode: true property bool selectMode: true
property var onItemChecked property var onItemChecked
anchors.fill: parent
id: root
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical.policy: groupMembers.contentHeight > groupMembers.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff ScrollBar.vertical.policy: groupMembers.contentHeight > groupMembers.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff
ListView { ListView {
id: groupMembers
anchors.fill: parent anchors.fill: parent
model: ListModel {
id: membersData
}
spacing: 0 spacing: 0
clip: true clip: true
id: groupMembers delegate: StatusListItem {
delegate: Contact { id: contactDelegate
isVisible: { property bool isChecked: false
title: !model.name.endsWith(".eth") && !!model.localNickname ?
model.localNickname : Utils.removeStatusEns(model.name)
image.source: appMain.getProfileImage(model.pubKey) || model.identicon
image.isIdenticon: !!model.identicon
visible: {
if (selectMode) { if (selectMode) {
return !searchString || model.name.toLowerCase().includes(searchString) return !searchString || model.name.toLowerCase().includes(searchString)
} }
return checkbox.checked || model.isUser
return isChecked || isUser
} }
showCheckbox: root.selectMode components: [
pubKey: model.pubKey StatusCheckBox {
isContact: !!model.isContact id: checkbox
isUser: model.isUser visible: contactListPanel.selectMode && !model.isUser
name: !model.name.endsWith(".eth") && !!model.localNickname ? checked: contactDelegate.isChecked
model.localNickname : Utils.removeStatusEns(model.name) onClicked: {
address: model.address contactDelegate.isChecked = !contactDelegate.isChecked
identicon: model.thumbnailImage || model.identicon onItemChecked(model.pubKey, contactDelegate.isChecked)
onItemChecked: function (pubKey, itemChecked) { }
root.onItemChecked(pubKey, itemChecked) }
]
onClicked: {
contactDelegate.isChecked = !contactDelegate.isChecked
onItemChecked(model.pubKey, contactDelegate.isChecked)
} }
} }
} }

View File

@ -32,16 +32,16 @@ ModalPopup {
memberCount = 1; memberCount = 1;
pubKeys = []; pubKeys = [];
contactList.membersData.clear(); popup.store.addToGroupContacts.clear();
getContactListObject(contactList.membersData) getContactListObject(popup.store.addToGroupContacts)
contactList.membersData.append({ popup.store.addToGroupContacts.append({
//% "(You)" //% "(You)"
name: userProfile.username + " " + qsTrId("(you)"), name: userProfile.username + " " + qsTrId("(you)"),
pubKey: userProfile.pubKey, pubKey: userProfile.pubKey,
address: "", address: "",
identicon: userProfile.identicon, identicon: "",
thumbnailImage: userProfile.thumbnailImage, thumbnailImage: userProfile.thumbnailImage,
isUser: true isUser: true
}); });
@ -135,6 +135,8 @@ ModalPopup {
ContactListPanel { ContactListPanel {
id: contactList id: contactList
anchors.fill: parent
model: popup.store.addToGroupContacts
searchString: searchBox.text.toLowerCase() searchString: searchBox.text.toLowerCase()
selectMode: selectChatMembers && memberCount < maxMembers selectMode: selectChatMembers && memberCount < maxMembers
anchors.topMargin: 50 anchors.topMargin: 50

View File

@ -2,22 +2,23 @@ import QtQuick 2.13
import QtQuick.Controls 2.13 import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13 import QtQuick.Layouts 1.13
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import StatusQ.Popups 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import utils 1.0 import utils 1.0
import shared 1.0
import shared.views 1.0 import shared.views 1.0
import shared.panels 1.0 import shared.panels 1.0
import shared.popups 1.0
import shared.status 1.0 import shared.status 1.0
import shared.controls 1.0
import StatusQ.Controls 0.1 as StatusQControls
import StatusQ.Components 0.1 as StatusQ
import "../panels" import "../panels"
// TODO: replace with StatusModal StatusModal {
ModalPopup {
id: popup id: popup
enum ChannelType { enum ChannelType {
ActiveChannel, ActiveChannel,
ContextChannel ContextChannel
@ -34,24 +35,45 @@ ModalPopup {
property Component pinnedMessagesPopupComponent property Component pinnedMessagesPopupComponent
function resetSelectedMembers(){ function resetSelectedMembers(){
pubKeys = []; pubKeys = []
memberCount = channel ? channel.members.rowCount() : 0; memberCount = channel ? channel.members.rowCount() : 0
currMemberCount = memberCount; currMemberCount = memberCount
contactList.membersData.clear(); popup.store.addToGroupContacts.clear()
popup.store.reCalculateAddToGroupContacts(channel)
}
const contacts = getContactListObject() function doAddMembers(){
if(pubKeys.length === 0) return;
if (popup.channel) {
chatsModel.groups.addMembers(popup.channel.id, JSON.stringify(pubKeys));
}
popup.close();
}
if (channel) { height: 504
contacts.forEach(function (contact) { anchors.centerIn: parent
if(popup.channel.contains(contact.publicKey) ||
!contact.isContact) { //% "Add members"
return; header.title: addMembers ? qsTrId("add-members") : (popup.channel ? popup.channel.name : "")
} header.subTitle: {
contactList.membersData.append(contact) let cnt = memberCount;
}) if(addMembers){
//% "%1 / 10 members"
return qsTrId("%1-/-10-members").arg(cnt)
} else {
//% "%1 members"
if(cnt > 1) return qsTrId("%1-members").arg(cnt);
//% "1 member"
return qsTrId("1-member");
} }
} }
header.editable: !addMembers && popup.isAdmin
header.icon.isLetterIdenticon: true
header.icon.name: popup.channel ? popup.channel.name : ""
header.icon.background.color: popup.channel ? popup.channel.color : "transparent"
onEditButtonClicked: renameGroupPopup.open()
onClosed: { onClosed: {
popup.destroy(); popup.destroy();
@ -66,147 +88,57 @@ ModalPopup {
resetSelectedMembers(); resetSelectedMembers();
} }
function doAddMembers(){ ColumnLayout {
if(pubKeys.length === 0) return;
if (popup.channel) {
chatsModel.groups.addMembers(popup.channel.id, JSON.stringify(pubKeys));
}
popup.close();
}
header: Item {
height: children[0].height
width: parent.width
StatusQ.StatusLetterIdenticon {
id: letterIdenticon
width: 36
height: 36
anchors.top: parent.top
color: popup.channel ? popup.channel.color : "transparent"
name: popup.channel ? popup.channel.name : ""
}
StyledTextEdit {
id: groupNameTxt
//% "Add members"
text: addMembers ? qsTrId("add-members")
: (popup.channel ? popup.channel.name : "")
anchors.top: parent.top
anchors.topMargin: 2
anchors.left: letterIdenticon.right
anchors.leftMargin: Style.current.smallPadding
font.bold: true
font.pixelSize: 14
readOnly: true
wrapMode: Text.WordWrap
}
StyledText {
text: {
let cnt = memberCount;
if(addMembers){
//% "%1 / 10 members"
return qsTrId("%1-/-10-members").arg(cnt)
} else {
//% "%1 members"
if(cnt > 1) return qsTrId("%1-members").arg(cnt);
//% "1 member"
return qsTrId("1-member");
}
}
width: 160
anchors.left: letterIdenticon.right
anchors.leftMargin: Style.current.smallPadding
anchors.top: groupNameTxt.bottom
anchors.topMargin: 2
font.pixelSize: 14
color: Style.current.secondaryText
}
Rectangle {
id: editGroupNameBtn
visible: !addMembers && popup.isAdmin
height: 24
width: 24
anchors.verticalCenter: groupNameTxt.verticalCenter
anchors.leftMargin: Style.current.halfPadding
anchors.left: groupNameTxt.right
radius: 8
SVGImage {
id: editGroupImg
source: Style.svg("edit-group")
height: 16
width: 16
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
MouseArea {
id: closeModalMouseArea
cursorShape: Qt.PointingHandCursor
anchors.fill: parent
hoverEnabled: true
onExited: {
editGroupNameBtn.color = Style.current.white
}
onEntered: {
editGroupNameBtn.color = Style.current.grey
}
onClicked: renameGroupPopup.open()
}
}
RenameGroupPopup {
id: renameGroupPopup
activeChannelName: popup.store.chatsModelInst.channelView.activeChannel.name
onDoRename: {
popup.store.chatsModelInst.groups.rename(groupName);
groupNameTxt.text = groupName
close();
}
}
}
Item {
id: addMembersItem id: addMembersItem
anchors.fill: parent
SearchBox { width: parent.width - 2*Style.current.padding
height: parent.height
anchors.top: parent.top
anchors.topMargin: Style.current.halfPadding
anchors.horizontalCenter: parent.horizontalCenter
visible: addMembers
spacing: Style.current.padding
StatusBaseInput {
id: searchBox id: searchBox
visible: addMembers implicitHeight: 36
iconWidth: 17 //% "Search"
iconHeight: 17 placeholderText: qsTrId("search")
customHeight: 44 placeholderFont.pixelSize: 15
fontPixelSize: 15 icon.name: "search"
icon.width: 17
icon.height: 17
Layout.fillWidth: true
Layout.alignment: Qt.AlignTop
} }
NoFriendsRectangle { NoFriendsRectangle {
visible: contactList.membersData.count === 0 && memberCount === 0 visible: popup.store.addToGroupContacts.count === 0 && memberCount === 0
anchors.top: searchBox.bottom Layout.preferredHeight: childrenRect.height
anchors.topMargin: Style.current.xlPadding Layout.fillWidth: true
anchors.horizontalCenter: parent.horizontalCenter Layout.alignment: Qt.AlignVCenter
Layout.bottomMargin: childrenRect.height
} }
NoFriendsRectangle { NoFriendsRectangle {
visible: contactList.membersData.count === 0 && memberCount > 0 visible: popup.store.addToGroupContacts.count === 0 && memberCount > 0
width: 340
//% "All your contacts are already in the group" //% "All your contacts are already in the group"
text: qsTrId("group-chat-all-contacts-invited") text: qsTrId("group-chat-all-contacts-invited")
textColor: Style.current.textColor textColor: Style.current.textColor
anchors.top: searchBox.bottom Layout.preferredHeight: childrenRect.height
anchors.topMargin: Style.current.xlPadding Layout.fillWidth: true
anchors.horizontalCenter: parent.horizontalCenter Layout.alignment: Qt.AlignVCenter
Layout.bottomMargin: childrenRect.height
} }
ContactListPanel { ContactListPanel {
id: contactList id: contactList
visible: addMembers && contactList.membersData.count > 0 visible: popup.store.addToGroupContacts.count > 0
anchors.fill: parent Layout.fillHeight: true
anchors.topMargin: 50 Layout.fillWidth: true
anchors.top: searchBox.bottom model: popup.store.addToGroupContacts
selectMode: memberCount < maxMembers selectMode: memberCount < maxMembers
searchString: searchBox.text.toLowerCase() searchString: searchBox.text.toLowerCase()
onItemChecked: function(pubKey, itemChecked){ onItemChecked: function(pubKey, itemChecked){
@ -226,32 +158,26 @@ ModalPopup {
} }
} }
Item { ColumnLayout {
id: groupInfoItem id: groupInfoItem
anchors.fill: parent
Separator { width: parent.width - 2*Style.current.padding
id: separator height: parent.height
visible: !addMembers anchors.top: parent.top
anchors.left: parent.left anchors.topMargin: Style.current.padding
anchors.leftMargin: -Style.current.padding anchors.horizontalCenter: parent.horizontalCenter
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding visible: !addMembers
} spacing: Style.current.padding
StatusSettingsLineButton { StatusSettingsLineButton {
property int pinnedCount: popup.store.chatsModelInst.messageView.pinnedMessagesList.count property int pinnedCount: popup.store.chatsModelInst.messageView.pinnedMessagesList.count
id: pinnedMessagesBtn id: pinnedMessagesBtn
visible: pinnedCount > 0 visible: pinnedCount > 0
height: visible ? implicitHeight : 0
//% "Pinned messages" //% "Pinned messages"
text: qsTrId("pinned-messages") text: qsTrId("pinned-messages")
currentValue: pinnedCount currentValue: pinnedCount
anchors.top: separator.bottom
anchors.topMargin: visible ? Style.current.halfPadding : 0
anchors.leftMargin: 0
anchors.rightMargin: 0
onClicked: openPopup(pinnedMessagesPopupComponent) onClicked: openPopup(pinnedMessagesPopupComponent)
iconSource: Style.svg("pin") iconSource: Style.svg("pin")
} }
@ -259,12 +185,6 @@ ModalPopup {
Separator { Separator {
id: separator2 id: separator2
visible: pinnedMessagesBtn.visible visible: pinnedMessagesBtn.visible
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
anchors.top: pinnedMessagesBtn.bottom
anchors.topMargin: visible ? Style.current.halfPadding : 0
} }
Connections { Connections {
@ -285,154 +205,106 @@ ModalPopup {
ListView { ListView {
id: memberList id: memberList
anchors.top: separator2.bottom
anchors.bottom: parent.bottom
anchors.topMargin: addMembers ? 30 : Style.current.padding
anchors.bottomMargin: Style.current.padding
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
anchors.right: parent.right
anchors.rightMargin: Style.current.padding
spacing: Style.current.padding spacing: Style.current.padding
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
model: popup.channel? popup.channel.members : [] model: popup.channel? popup.channel.members : []
delegate: Item { delegate: StatusListItem {
id: contactRow id: contactRow
width: parent.width
height: identicon.height
property string nickname: appMain.getUserNickname(model.publicKey) property string nickname: appMain.getUserNickname(model.publicKey)
StatusQ.StatusSmartIdenticon { title: !model.userName.endsWith(".eth") && !!contactRow.nickname ?
id: identicon contactRow.nickname : Utils.removeStatusEns(model.userName)
anchors.left: parent.left //% "(You)"
image.source: appMain.getProfileImage(model.publicKey)|| model.identicon titleAsideText: model.publicKey === userProfile.pubKey ? qsTrId("-you-") : ""
image.isIdenticon: true //% "Admin"
} statusListItemTitle.font.pixelSize: 17
statusListItemTitleAside.font.pixelSize: 17
StyledText { label: model.isAdmin ? qsTrId("group-chat-admin"): ""
text: !model.userName.endsWith(".eth") && !!contactRow.nickname ? image.source: appMain.getProfileImage(model.publicKey) || model.identicon
contactRow.nickname : Utils.removeStatusEns(model.userName) image.isIdenticon: model.identicon
anchors.left: identicon.right components: [
anchors.leftMargin: Style.current.padding StatusFlatRoundButton {
anchors.verticalCenter: parent.verticalCenter id: moreActionsBtn
font.pixelSize: 17 type: StatusFlatRoundButton.Type.Tertiary
color: "transparent"
StyledText { icon.name: "more"
visible: model.publicKey === userProfile.pubKey icon.color: Theme.palette.baseColor1
anchors.left: parent.right visible: !model.isAdmin && popup.isAdmin
anchors.leftMargin: 5
//% "(You)"
text: qsTrId("-you-")
color: Style.current.secondaryText
font.pixelSize: parent.font.pixelSize
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
const userProfileImage = appMain.getProfileImage(model.publicKey)
openProfilePopup(model.userName, model.publicKey, userProfileImage || model.identicon, '', contactRow.nickname, popup)
}
}
}
StyledText {
id: adminLabel
visible: model.isAdmin
//% "Admin"
text: qsTrId("group-chat-admin")
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 13
color: Style.current.secondaryText
}
StyledText {
id: moreActionsBtn
visible: !model.isAdmin && popup.isAdmin
text: "..."
anchors.right: parent.right
anchors.rightMargin: Style.current.smallPadding
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 20
font.bold: true
color: Style.current.secondaryText
MouseArea {
anchors.fill: parent
onClicked: { onClicked: {
contextMenu.popup(-contextMenu.width / 2 + moreActionsBtn.width / 2, moreActionsBtn.height + 10) contextMenu.popup(-contextMenu.width / 2 + moreActionsBtn.width / 2, moreActionsBtn.height + 10)
} }
cursorShape: Qt.PointingHandCursor StatusPopupMenu {
// TODO: replace with StatusPopupMenu
PopupMenu {
id: contextMenu id: contextMenu
Action { StatusMenuItem {
icon.source: Style.svg("make-admin") icon.name: "admin"
icon.width: 16 icon.width: 16
icon.height: 16 icon.height: 16
//% "Make Admin" //% "Make Admin"
text: qsTrId("make-admin") text: qsTrId("make-admin")
onTriggered: popup.store.chatsModelInst.groups.makeAdmin(popup.channel.id, model.publicKey) onTriggered: popup.store.chatsModelInst.groups.makeAdmin(popup.channel.id, model.publicKey)
} }
Action { StatusMenuItem {
icon.source: Style.svg("remove-from-group") icon.name: "remove-contact"
icon.width: 16 icon.width: 16
icon.height: 16 icon.height: 16
icon.color: Style.current.red type: StatusMenuItem.Type.Danger
//% "Remove From Group" //% "Remove From Group"
text: qsTrId("remove-from-group") text: qsTrId("remove-from-group")
onTriggered: popup.store.chatsModelInst.groups.kickMember(popup.channel.id, model.publicKey) onTriggered: popup.store.chatsModelInst.groups.kickMember(popup.channel.id, model.publicKey)
} }
} }
} }
]
onTitleClicked: {
const userProfileImage = appMain.getProfileImage(model.publicKey)
openProfilePopup(model.userName, model.publicKey, userProfileImage || model.identicon, '', contactRow.nickname, popup)
} }
} }
} }
} }
footer: Item { leftButtons: [
visible: popup.isAdmin StatusRoundButton {
width: parent.width visible: popup.addMembers
height: children[0].height
StatusQControls.StatusButton {
visible: !addMembers
anchors.right: parent.right
//% "Add members"
text: qsTrId("add-members")
anchors.bottom: parent.bottom
onClicked: {
addMembers = true;
}
}
StatusQControls.StatusRoundButton {
id: btnBack
visible: addMembers
anchors.bottom: parent.bottom
anchors.left: parent.left
icon.name: "arrow-right" icon.name: "arrow-right"
icon.width: 20 icon.width: 20
icon.height: 16 icon.height: 16
icon.rotation: 180 icon.rotation: 180
onClicked : { onClicked: {
addMembers = false; popup.addMembers = false;
resetSelectedMembers(); popup.resetSelectedMembers();
} }
} }
]
StatusQControls.StatusButton { rightButtons: [
StatusButton {
visible: !popup.addMembers
//% "Add members"
text: qsTrId("add-members")
onClicked: {
popup.addMembers = true;
}
},
StatusButton {
id: btnSelectMembers id: btnSelectMembers
visible: addMembers visible: popup.addMembers
enabled: memberCount >= currMemberCount enabled: popup.memberCount >= popup.currMemberCount
anchors.right: parent.right
//% "Add selected" //% "Add selected"
text: qsTrId("add-selected") text: qsTrId("add-selected")
anchors.bottom: parent.bottom onClicked: popup.doAddMembers()
onClicked: doAddMembers() }
]
RenameGroupPopup {
id: renameGroupPopup
activeChannelName: popup.store.chatsModelInst.channelView.activeChannel.name
onDoRename: {
popup.store.chatsModelInst.groups.rename(groupName)
popup.header.title = groupName
close()
} }
} }
content: addMembers ? addMembersItem : groupInfoItem
} }

View File

@ -38,8 +38,8 @@ StatusModal {
anchors.topMargin: Style.current.padding anchors.topMargin: Style.current.padding
//% "Group name" //% "Group name"
placeholderText: qsTrId("group-name") placeholderText: qsTrId("group-name")
Keys.onEnterPressed: doRename() Keys.onEnterPressed: doRename(groupName.text)
Keys.onReturnPressed: doRename() Keys.onReturnPressed: doRename(groupName.text)
} }
} }
@ -48,7 +48,7 @@ StatusModal {
id: saveBtn id: saveBtn
//% "Save" //% "Save"
text: qsTrId("save") text: qsTrId("save")
onClicked : { doRename(groupName.text); } onClicked : { doRename(groupName.text) }
} }
] ]
} }

View File

@ -23,6 +23,22 @@ QtObject {
property var currentAccount: walletSectionCurrent property var currentAccount: walletSectionCurrent
property var currentCurrency: walletSection.currentCurrency property var currentCurrency: walletSection.currentCurrency
property ListModel addToGroupContacts: ListModel {}
function reCalculateAddToGroupContacts(channel) {
const contacts = getContactListObject()
if (channel) {
contacts.forEach(function (contact) {
if(channel.contains(contact.pubKey) ||
!contact.isContact) {
return;
}
addToGroupContacts.append(contact)
})
}
}
function copyToClipboard(text) { function copyToClipboard(text) {
chatsModelInst.copyToClipboard(text); chatsModelInst.copyToClipboard(text);
} }