status-desktop/ui/app/AppLayouts/Chat/popups/GroupInfoPopup.qml

439 lines
15 KiB
QML
Raw Normal View History

2020-06-17 19:18:31 +00:00
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import utils 1.0
import shared 1.0
import shared.views 1.0
import shared.panels 1.0
import shared.popups 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"
2020-06-11 17:50:36 +00:00
// TODO: replace with StatusModal
2020-06-11 17:50:36 +00:00
ModalPopup {
id: popup
fix: kick and re-invite user to group chat Fixes: #2601. Kicking a user and re-inviting them now correctly redisplays the join/decline options. Other combinations of User B leaving or declining an invitation are not handled. Please see the notes below for clarification. Additionally, the group invite popup (that shows the list of members belonging to the group) correctly shows when a user is kicked or when a user leaves the group in real time. Previously, the popup needed to be reopened to display this. fix: decline invitation crash Declining a group invitation was crashing the app. This has been fixed. ### NOTES 1. In the case where User A invites User B to a group, but User B declines (or User B joins, then leaves), then from a status-go standpoint, User B is still part of the group, but the chat is marked as `active: false` for User B. This creates a situation where User B cannot re-join the group once s/he has declined the invitation. @cammellos mentioned there possibly will need to be a refactor of https://github.com/status-im/status-go/blob/cab6281dc520c24912de5b5226b42a2f8415aa40/protocol/messenger.go#L1710 (which, by retaining User B as a member, effectively prevents the re-invitation) once “swipe to delete” is implemented on mobile. There is an activity center notification received for User B that is meant to allow re-joining of the group when the notification is accepted. The activity center notification received from status-go looks like the following: ```json "activityCenterNotifications": [ { "id": "0x0e342d33", "chatId": "e342d33f-dd05-4d7b-b14e-b5335e1a3ee9-0x043bf46aa874c377a34946eab67a32cf36c15907b328216dfce375d169fed7d81c21cada3229db1fd37c762d2c02702111a646657feca6621e2e948febcf378fb4", "name": "test-22", "type": 2, "lastMessage": null, "message": null, "timestamp": 1623305612000, "read": false, "dismissed": false, "accepted": false } ] ```
2021-06-10 07:29:05 +00:00
enum ChannelType {
ActiveChannel,
ContextChannel
}
property var store
property bool addMembers: false
property int currMemberCount: 1
property int memberCount: 1
readonly property int maxMembers: 10
property var pubKeys: []
fix: kick and re-invite user to group chat Fixes: #2601. Kicking a user and re-inviting them now correctly redisplays the join/decline options. Other combinations of User B leaving or declining an invitation are not handled. Please see the notes below for clarification. Additionally, the group invite popup (that shows the list of members belonging to the group) correctly shows when a user is kicked or when a user leaves the group in real time. Previously, the popup needed to be reopened to display this. fix: decline invitation crash Declining a group invitation was crashing the app. This has been fixed. ### NOTES 1. In the case where User A invites User B to a group, but User B declines (or User B joins, then leaves), then from a status-go standpoint, User B is still part of the group, but the chat is marked as `active: false` for User B. This creates a situation where User B cannot re-join the group once s/he has declined the invitation. @cammellos mentioned there possibly will need to be a refactor of https://github.com/status-im/status-go/blob/cab6281dc520c24912de5b5226b42a2f8415aa40/protocol/messenger.go#L1710 (which, by retaining User B as a member, effectively prevents the re-invitation) once “swipe to delete” is implemented on mobile. There is an activity center notification received for User B that is meant to allow re-joining of the group when the notification is accepted. The activity center notification received from status-go looks like the following: ```json "activityCenterNotifications": [ { "id": "0x0e342d33", "chatId": "e342d33f-dd05-4d7b-b14e-b5335e1a3ee9-0x043bf46aa874c377a34946eab67a32cf36c15907b328216dfce375d169fed7d81c21cada3229db1fd37c762d2c02702111a646657feca6621e2e948febcf378fb4", "name": "test-22", "type": 2, "lastMessage": null, "message": null, "timestamp": 1623305612000, "read": false, "dismissed": false, "accepted": false } ] ```
2021-06-10 07:29:05 +00:00
property int channelType: GroupInfoPopup.ChannelType.ActiveChannel
property QtObject channel
property bool isAdmin: false
2021-05-25 19:38:18 +00:00
property Component pinnedMessagesPopupComponent
function resetSelectedMembers(){
pubKeys = [];
memberCount = channel ? channel.members.rowCount() : 0;
currMemberCount = memberCount;
2020-12-11 20:38:10 +00:00
contactList.membersData.clear();
const contacts = getContactListObject()
2020-12-11 20:38:10 +00:00
if (channel) {
contacts.forEach(function (contact) {
if(popup.channel.contains(contact.publicKey) ||
!contact.isContact) {
return;
}
contactList.membersData.append(contact)
})
}
}
onClosed: {
popup.destroy();
}
onOpened: {
addMembers = false;
if (popup.channel) {
popup.isAdmin = popup.channel.isAdmin(popup.store.profileModelInst.profile.pubKey)
}
btnSelectMembers.enabled = false;
resetSelectedMembers();
}
function doAddMembers(){
if(pubKeys.length === 0) return;
if (popup.channel) {
chatsModel.groups.addMembers(popup.channel.id, JSON.stringify(pubKeys));
}
popup.close();
}
2020-06-11 17:50:36 +00:00
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 {
2020-06-15 12:51:04 +00:00
id: editGroupNameBtn
visible: !addMembers && popup.isAdmin
2020-06-15 12:51:04 +00:00
height: 24
width: 24
anchors.verticalCenter: groupNameTxt.verticalCenter
2021-05-25 19:38:18 +00:00
anchors.leftMargin: Style.current.halfPadding
anchors.left: groupNameTxt.right
2020-06-15 12:51:04 +00:00
radius: 8
SVGImage {
2020-06-15 12:51:04 +00:00
id: editGroupImg
source: Style.svg("edit-group")
height: 16
width: 16
2020-06-15 12:51:04 +00:00
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
2020-06-15 12:51:04 +00:00
}
onEntered: {
editGroupNameBtn.color = Style.current.grey
2020-06-15 12:51:04 +00:00
}
onClicked: renameGroupPopup.open()
}
}
RenameGroupPopup {
id: renameGroupPopup
activeChannelName: popup.store.chatsModelInst.channelView.activeChannel.name
onDoRename: {
popup.store.chatsModelInst.groups.rename(groupName);
groupNameTxt.text = groupName
close();
}
2020-06-15 12:51:04 +00:00
}
2020-06-11 17:50:36 +00:00
}
Item {
id: addMembersItem
anchors.fill: parent
SearchBox {
id: searchBox
visible: addMembers
iconWidth: 17
iconHeight: 17
customHeight: 44
fontPixelSize: 15
}
2020-12-11 20:38:10 +00:00
NoFriendsRectangle {
visible: contactList.membersData.count === 0 && memberCount === 0
anchors.top: searchBox.bottom
anchors.topMargin: Style.current.xlPadding
anchors.horizontalCenter: parent.horizontalCenter
}
NoFriendsRectangle {
visible: contactList.membersData.count === 0 && memberCount > 0
width: 340
//% "All your contacts are already in the group"
text: qsTrId("group-chat-all-contacts-invited")
textColor: Style.current.textColor
anchors.top: searchBox.bottom
anchors.topMargin: Style.current.xlPadding
anchors.horizontalCenter: parent.horizontalCenter
}
ContactListPanel {
2020-12-11 20:38:10 +00:00
id: contactList
visible: addMembers && contactList.membersData.count > 0
anchors.fill: parent
anchors.topMargin: 50
anchors.top: searchBox.bottom
2020-12-11 20:38:10 +00:00
selectMode: memberCount < maxMembers
searchString: searchBox.text.toLowerCase()
onItemChecked: function(pubKey, itemChecked){
var idx = pubKeys.indexOf(pubKey)
if(itemChecked){
if(idx === -1){
pubKeys.push(pubKey)
}
} else {
if(idx > -1){
pubKeys.splice(idx, 1);
}
}
memberCount = popup.channel.members.rowCount() + pubKeys.length;
2020-12-11 20:38:10 +00:00
btnSelectMembers.enabled = pubKeys.length > 0
}
}
}
2020-06-11 17:50:36 +00:00
Item {
id: groupInfoItem
2020-06-11 17:50:36 +00:00
anchors.fill: parent
Separator {
id: separator
visible: !addMembers
anchors.left: parent.left
anchors.leftMargin: -Style.current.padding
anchors.right: parent.right
anchors.rightMargin: -Style.current.padding
2020-06-11 17:50:36 +00:00
}
2021-05-25 19:38:18 +00:00
StatusSettingsLineButton {
property int pinnedCount: popup.store.chatsModelInst.messageView.pinnedMessagesList.count
2021-05-25 19:38:18 +00:00
id: pinnedMessagesBtn
visible: pinnedCount > 0
height: visible ? implicitHeight : 0
//% "Pinned messages"
text: qsTrId("pinned-messages")
2021-05-25 19:38:18 +00:00
currentValue: pinnedCount
anchors.top: separator.bottom
anchors.topMargin: visible ? Style.current.halfPadding : 0
anchors.leftMargin: 0
anchors.rightMargin: 0
onClicked: openPopup(pinnedMessagesPopupComponent)
iconSource: Style.svg("pin")
2021-05-25 19:38:18 +00:00
}
Separator {
id: separator2
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
}
fix: kick and re-invite user to group chat Fixes: #2601. Kicking a user and re-inviting them now correctly redisplays the join/decline options. Other combinations of User B leaving or declining an invitation are not handled. Please see the notes below for clarification. Additionally, the group invite popup (that shows the list of members belonging to the group) correctly shows when a user is kicked or when a user leaves the group in real time. Previously, the popup needed to be reopened to display this. fix: decline invitation crash Declining a group invitation was crashing the app. This has been fixed. ### NOTES 1. In the case where User A invites User B to a group, but User B declines (or User B joins, then leaves), then from a status-go standpoint, User B is still part of the group, but the chat is marked as `active: false` for User B. This creates a situation where User B cannot re-join the group once s/he has declined the invitation. @cammellos mentioned there possibly will need to be a refactor of https://github.com/status-im/status-go/blob/cab6281dc520c24912de5b5226b42a2f8415aa40/protocol/messenger.go#L1710 (which, by retaining User B as a member, effectively prevents the re-invitation) once “swipe to delete” is implemented on mobile. There is an activity center notification received for User B that is meant to allow re-joining of the group when the notification is accepted. The activity center notification received from status-go looks like the following: ```json "activityCenterNotifications": [ { "id": "0x0e342d33", "chatId": "e342d33f-dd05-4d7b-b14e-b5335e1a3ee9-0x043bf46aa874c377a34946eab67a32cf36c15907b328216dfce375d169fed7d81c21cada3229db1fd37c762d2c02702111a646657feca6621e2e948febcf378fb4", "name": "test-22", "type": 2, "lastMessage": null, "message": null, "timestamp": 1623305612000, "read": false, "dismissed": false, "accepted": false } ] ```
2021-06-10 07:29:05 +00:00
Connections {
target: popup.store.chatsModelInst.channelView
fix: kick and re-invite user to group chat Fixes: #2601. Kicking a user and re-inviting them now correctly redisplays the join/decline options. Other combinations of User B leaving or declining an invitation are not handled. Please see the notes below for clarification. Additionally, the group invite popup (that shows the list of members belonging to the group) correctly shows when a user is kicked or when a user leaves the group in real time. Previously, the popup needed to be reopened to display this. fix: decline invitation crash Declining a group invitation was crashing the app. This has been fixed. ### NOTES 1. In the case where User A invites User B to a group, but User B declines (or User B joins, then leaves), then from a status-go standpoint, User B is still part of the group, but the chat is marked as `active: false` for User B. This creates a situation where User B cannot re-join the group once s/he has declined the invitation. @cammellos mentioned there possibly will need to be a refactor of https://github.com/status-im/status-go/blob/cab6281dc520c24912de5b5226b42a2f8415aa40/protocol/messenger.go#L1710 (which, by retaining User B as a member, effectively prevents the re-invitation) once “swipe to delete” is implemented on mobile. There is an activity center notification received for User B that is meant to allow re-joining of the group when the notification is accepted. The activity center notification received from status-go looks like the following: ```json "activityCenterNotifications": [ { "id": "0x0e342d33", "chatId": "e342d33f-dd05-4d7b-b14e-b5335e1a3ee9-0x043bf46aa874c377a34946eab67a32cf36c15907b328216dfce375d169fed7d81c21cada3229db1fd37c762d2c02702111a646657feca6621e2e948febcf378fb4", "name": "test-22", "type": 2, "lastMessage": null, "message": null, "timestamp": 1623305612000, "read": false, "dismissed": false, "accepted": false } ] ```
2021-06-10 07:29:05 +00:00
onActiveChannelChanged: {
if (popup.channelType === GroupInfoPopup.ChannelType.ActiveChannel) {
popup.channel = popup.store.chatsModelInst.channelView.activeChannel
fix: kick and re-invite user to group chat Fixes: #2601. Kicking a user and re-inviting them now correctly redisplays the join/decline options. Other combinations of User B leaving or declining an invitation are not handled. Please see the notes below for clarification. Additionally, the group invite popup (that shows the list of members belonging to the group) correctly shows when a user is kicked or when a user leaves the group in real time. Previously, the popup needed to be reopened to display this. fix: decline invitation crash Declining a group invitation was crashing the app. This has been fixed. ### NOTES 1. In the case where User A invites User B to a group, but User B declines (or User B joins, then leaves), then from a status-go standpoint, User B is still part of the group, but the chat is marked as `active: false` for User B. This creates a situation where User B cannot re-join the group once s/he has declined the invitation. @cammellos mentioned there possibly will need to be a refactor of https://github.com/status-im/status-go/blob/cab6281dc520c24912de5b5226b42a2f8415aa40/protocol/messenger.go#L1710 (which, by retaining User B as a member, effectively prevents the re-invitation) once “swipe to delete” is implemented on mobile. There is an activity center notification received for User B that is meant to allow re-joining of the group when the notification is accepted. The activity center notification received from status-go looks like the following: ```json "activityCenterNotifications": [ { "id": "0x0e342d33", "chatId": "e342d33f-dd05-4d7b-b14e-b5335e1a3ee9-0x043bf46aa874c377a34946eab67a32cf36c15907b328216dfce375d169fed7d81c21cada3229db1fd37c762d2c02702111a646657feca6621e2e948febcf378fb4", "name": "test-22", "type": 2, "lastMessage": null, "message": null, "timestamp": 1623305612000, "read": false, "dismissed": false, "accepted": false } ] ```
2021-06-10 07:29:05 +00:00
resetSelectedMembers()
}
}
onContextChannelChanged: {
if (popup.channelType === GroupInfoPopup.ChannelType.ContextChannel) {
popup.channel = popup.store.chatsModelInst.channelView.contextChannel
fix: kick and re-invite user to group chat Fixes: #2601. Kicking a user and re-inviting them now correctly redisplays the join/decline options. Other combinations of User B leaving or declining an invitation are not handled. Please see the notes below for clarification. Additionally, the group invite popup (that shows the list of members belonging to the group) correctly shows when a user is kicked or when a user leaves the group in real time. Previously, the popup needed to be reopened to display this. fix: decline invitation crash Declining a group invitation was crashing the app. This has been fixed. ### NOTES 1. In the case where User A invites User B to a group, but User B declines (or User B joins, then leaves), then from a status-go standpoint, User B is still part of the group, but the chat is marked as `active: false` for User B. This creates a situation where User B cannot re-join the group once s/he has declined the invitation. @cammellos mentioned there possibly will need to be a refactor of https://github.com/status-im/status-go/blob/cab6281dc520c24912de5b5226b42a2f8415aa40/protocol/messenger.go#L1710 (which, by retaining User B as a member, effectively prevents the re-invitation) once “swipe to delete” is implemented on mobile. There is an activity center notification received for User B that is meant to allow re-joining of the group when the notification is accepted. The activity center notification received from status-go looks like the following: ```json "activityCenterNotifications": [ { "id": "0x0e342d33", "chatId": "e342d33f-dd05-4d7b-b14e-b5335e1a3ee9-0x043bf46aa874c377a34946eab67a32cf36c15907b328216dfce375d169fed7d81c21cada3229db1fd37c762d2c02702111a646657feca6621e2e948febcf378fb4", "name": "test-22", "type": 2, "lastMessage": null, "message": null, "timestamp": 1623305612000, "read": false, "dismissed": false, "accepted": false } ] ```
2021-06-10 07:29:05 +00:00
resetSelectedMembers()
}
}
}
2020-06-11 17:50:36 +00:00
ListView {
id: memberList
2021-05-25 19:38:18 +00:00
anchors.top: separator2.bottom
2021-05-26 15:43:03 +00:00
anchors.bottom: parent.bottom
2021-05-25 19:38:18 +00:00
anchors.topMargin: addMembers ? 30 : Style.current.padding
anchors.bottomMargin: Style.current.padding
2021-05-25 19:38:18 +00:00
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
anchors.right: parent.right
anchors.rightMargin: Style.current.padding
spacing: Style.current.padding
2020-06-11 17:50:36 +00:00
Layout.fillWidth: true
Layout.fillHeight: true
model: popup.channel? popup.channel.members : []
delegate: Item {
id: contactRow
width: parent.width
height: identicon.height
2021-07-26 22:00:09 +00:00
property string nickname: appMain.getUserNickname(model.publicKey)
StatusQ.StatusSmartIdenticon {
id: identicon
anchors.left: parent.left
image.source: appMain.getProfileImage(model.publicKey)|| model.identicon
image.isIdenticon: true
2020-06-11 17:50:36 +00:00
}
StyledText {
text: !model.userName.endsWith(".eth") && !!contactRow.nickname ?
contactRow.nickname : Utils.removeStatusEns(model.userName)
anchors.left: identicon.right
2021-05-03 17:01:20 +00:00
anchors.leftMargin: Style.current.padding
anchors.verticalCenter: parent.verticalCenter
2021-05-03 17:01:20 +00:00
font.pixelSize: 17
StyledText {
2021-07-26 22:00:09 +00:00
visible: model.publicKey === profileModel.profile.pubKey
anchors.left: parent.right
anchors.leftMargin: 5
2021-02-18 16:36:05 +00:00
//% "(You)"
text: qsTrId("-you-")
2021-01-19 15:02:47 +00:00
color: Style.current.secondaryText
font.pixelSize: parent.font.pixelSize
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
2020-11-30 17:03:52 +00:00
onClicked: {
2021-07-26 22:00:09 +00:00
const userProfileImage = appMain.getProfileImage(model.publicKey)
openProfilePopup(model.userName, model.publicKey, userProfileImage || model.identicon, '', contactRow.nickname, popup)
2020-11-30 17:03:52 +00:00
}
2020-06-11 17:50:36 +00:00
}
}
StyledText {
id: adminLabel
visible: model.isAdmin
//% "Admin"
text: qsTrId("group-chat-admin")
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
font.pixelSize: 13
2021-01-19 15:02:47 +00:00
color: Style.current.secondaryText
2020-06-11 17:50:36 +00:00
}
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
2021-01-19 15:02:47 +00:00
color: Style.current.secondaryText
MouseArea {
anchors.fill: parent
onClicked: {
contextMenu.popup(-contextMenu.width / 2 + moreActionsBtn.width / 2, moreActionsBtn.height + 10)
}
cursorShape: Qt.PointingHandCursor
// TODO: replace with StatusPopupMenu
PopupMenu {
id: contextMenu
Action {
icon.source: Style.svg("make-admin")
icon.width: 16
icon.height: 16
//% "Make Admin"
text: qsTrId("make-admin")
onTriggered: popup.store.chatsModelInst.groups.makeAdmin(popup.channel.id, model.publicKey)
}
Action {
icon.source: Style.svg("remove-from-group")
icon.width: 16
icon.height: 16
icon.color: Style.current.red
//% "Remove From Group"
text: qsTrId("remove-from-group")
onTriggered: popup.store.chatsModelInst.groups.kickMember(popup.channel.id, model.publicKey)
}
}
2020-06-11 17:50:36 +00:00
}
}
}
}
}
footer: Item {
visible: popup.isAdmin
width: parent.width
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.width: 20
icon.height: 16
icon.rotation: 180
onClicked : {
addMembers = false;
resetSelectedMembers();
}
}
StatusQControls.StatusButton {
id: btnSelectMembers
visible: addMembers
enabled: memberCount >= currMemberCount
anchors.right: parent.right
//% "Add selected"
text: qsTrId("add-selected")
anchors.bottom: parent.bottom
onClicked: doAddMembers()
}
}
content: addMembers ? addMembersItem : groupInfoItem
2020-06-11 17:50:36 +00:00
}