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 cab6281dc5/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
}
]
```
This commit is contained in:
parent
32676d50af
commit
45286e179c
|
@ -746,7 +746,11 @@ QtObject:
|
||||||
self.chats.updateChat(chat)
|
self.chats.updateChat(chat)
|
||||||
if(self.activeChannel.id == chat.id):
|
if(self.activeChannel.id == chat.id):
|
||||||
self.activeChannel.setChatItem(chat)
|
self.activeChannel.setChatItem(chat)
|
||||||
|
self.activeChannelChanged()
|
||||||
self.currentSuggestions.setNewData(self.status.contacts.getContacts())
|
self.currentSuggestions.setNewData(self.status.contacts.getContacts())
|
||||||
|
if self.contextChannel.id == chat.id:
|
||||||
|
self.contextChannel.setChatItem(chat)
|
||||||
|
self.contextChannelChanged()
|
||||||
self.calculateUnreadMessages()
|
self.calculateUnreadMessages()
|
||||||
|
|
||||||
proc deleteMessage*(self: ChatsView, channelId: string, messageId: string) =
|
proc deleteMessage*(self: ChatsView, channelId: string, messageId: string) =
|
||||||
|
|
|
@ -131,6 +131,7 @@ QtObject:
|
||||||
|
|
||||||
QtProperty[QVariant] members:
|
QtProperty[QVariant] members:
|
||||||
read = getMembers
|
read = getMembers
|
||||||
|
notify = membershipChanged
|
||||||
|
|
||||||
proc isTimelineChat*(self: ChatItemView): bool {.slot.} = result = ?.self.chatItem.id == status_utils.getTimelineChatId()
|
proc isTimelineChat*(self: ChatItemView): bool {.slot.} = result = ?.self.chatItem.id == status_utils.getTimelineChatId()
|
||||||
|
|
||||||
|
@ -157,6 +158,15 @@ QtObject:
|
||||||
read = isMember
|
read = isMember
|
||||||
notify = membershipChanged
|
notify = membershipChanged
|
||||||
|
|
||||||
|
proc isMemberButNotJoined*(self: ChatItemView): bool {.slot.} =
|
||||||
|
if self.chatItem.isNil: return false
|
||||||
|
let pubKey = status_settings.getSetting[string](Setting.PublicKey, "0x0")
|
||||||
|
return self.chatItem.isMemberButNotJoined(pubKey)
|
||||||
|
|
||||||
|
QtProperty[bool] isMemberButNotJoined:
|
||||||
|
read = isMemberButNotJoined
|
||||||
|
notify = membershipChanged
|
||||||
|
|
||||||
proc mutedChanged*(self: ChatItemView) {.signal.}
|
proc mutedChanged*(self: ChatItemView) {.signal.}
|
||||||
|
|
||||||
proc muted*(self: ChatItemView): bool {.slot.} =
|
proc muted*(self: ChatItemView): bool {.slot.} =
|
||||||
|
|
|
@ -183,7 +183,14 @@ proc findIndexById*(self: seq[CommunityCategory], id: string): int =
|
||||||
|
|
||||||
proc isMember*(self: Chat, pubKey: string): bool =
|
proc isMember*(self: Chat, pubKey: string): bool =
|
||||||
for member in self.members:
|
for member in self.members:
|
||||||
if member.id == pubKey and member.joined: return true
|
if member.id == pubKey:
|
||||||
|
return member.joined
|
||||||
|
return false
|
||||||
|
|
||||||
|
proc isMemberButNotJoined*(self: Chat, pubKey: string): bool =
|
||||||
|
for member in self.members:
|
||||||
|
if member.id == pubKey:
|
||||||
|
return not member.joined
|
||||||
return false
|
return false
|
||||||
|
|
||||||
proc contains*(self: Chat, pubKey: string): bool =
|
proc contains*(self: Chat, pubKey: string): bool =
|
||||||
|
@ -193,5 +200,6 @@ proc contains*(self: Chat, pubKey: string): bool =
|
||||||
|
|
||||||
proc isAdmin*(self: Chat, pubKey: string): bool =
|
proc isAdmin*(self: Chat, pubKey: string): bool =
|
||||||
for member in self.members:
|
for member in self.members:
|
||||||
if member.id == pubKey and member.joined and member.admin: return true
|
if member.id == pubKey:
|
||||||
|
return member.joined and member.admin
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -16,7 +16,7 @@ proc processChatUpdate(self: ChatModel, response: JsonNode): (seq[Chat], seq[Mes
|
||||||
let pk = status_settings.getSetting[string](Setting.PublicKey, "0x0")
|
let pk = status_settings.getSetting[string](Setting.PublicKey, "0x0")
|
||||||
var chats: seq[Chat] = @[]
|
var chats: seq[Chat] = @[]
|
||||||
var messages: seq[Message] = @[]
|
var messages: seq[Message] = @[]
|
||||||
if response{"result"}{"chats"} != nil:
|
if response{"result"}{"messages"} != nil:
|
||||||
for jsonMsg in response["result"]["messages"]:
|
for jsonMsg in response["result"]["messages"]:
|
||||||
messages.add(jsonMsg.toMessage(pk))
|
messages.add(jsonMsg.toMessage(pk))
|
||||||
if response{"result"}{"chats"} != nil:
|
if response{"result"}{"chats"} != nil:
|
||||||
|
|
|
@ -96,7 +96,7 @@ Column {
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
visible: chatsModel.activeChannel.chatType === Constants.chatTypePrivateGroupChat && !chatsModel.activeChannel.isMember
|
visible: chatsModel.activeChannel.chatType === Constants.chatTypePrivateGroupChat && chatsModel.activeChannel.isMemberButNotJoined
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
width: visible ? joinChat.width : 0
|
width: visible ? joinChat.width : 0
|
||||||
height: visible ? 100 : 0
|
height: visible ? 100 : 0
|
||||||
|
@ -115,7 +115,6 @@ Column {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: {
|
onClicked: {
|
||||||
chatsModel.groups.join()
|
chatsModel.groups.join()
|
||||||
joinOrDecline.visible = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ Item {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
switch (chatsModel.activeChannel.chatType) {
|
switch (chatsModel.activeChannel.chatType) {
|
||||||
case Constants.chatTypePrivateGroupChat:
|
case Constants.chatTypePrivateGroupChat:
|
||||||
openPopup(groupInfoPopupComponent, {channel: chatsModel.activeChannel})
|
openPopup(groupInfoPopupComponent, {channelType: GroupInfoPopup.ChannelType.ActiveChannel})
|
||||||
break;
|
break;
|
||||||
case Constants.chatTypeOneToOne:
|
case Constants.chatTypeOneToOne:
|
||||||
const profileImage = appMain.getProfileImage(chatsModel.activeChannel.id)
|
const profileImage = appMain.getProfileImage(chatsModel.activeChannel.id)
|
||||||
|
@ -106,7 +106,7 @@ Item {
|
||||||
icon.height: chatTopBarContent.iconSize
|
icon.height: chatTopBarContent.iconSize
|
||||||
//% "Group Information"
|
//% "Group Information"
|
||||||
text: qsTrId("group-information")
|
text: qsTrId("group-information")
|
||||||
onTriggered: openPopup(groupInfoPopupComponent, {channel: chatsModel.activeChannel})
|
onTriggered: openPopup(groupInfoPopupComponent, {channelType: GroupInfoPopup.ChannelType.ActiveChannel })
|
||||||
}
|
}
|
||||||
Action {
|
Action {
|
||||||
icon.source: "../../../img/close.svg"
|
icon.source: "../../../img/close.svg"
|
||||||
|
|
|
@ -60,7 +60,7 @@ PopupMenu {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (channelContextMenu.contextChannel.chatType === Constants.chatTypePrivateGroupChat) {
|
if (channelContextMenu.contextChannel.chatType === Constants.chatTypePrivateGroupChat) {
|
||||||
return openPopup(groupInfoPopupComponent, {channel: channelContextMenu.contextChannel})
|
return openPopup(groupInfoPopupComponent, {channelType: GroupInfoPopup.ChannelType.ContextChannel})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,23 @@ import "./"
|
||||||
|
|
||||||
ModalPopup {
|
ModalPopup {
|
||||||
id: popup
|
id: popup
|
||||||
|
enum ChannelType {
|
||||||
|
ActiveChannel,
|
||||||
|
ContextChannel
|
||||||
|
}
|
||||||
property bool addMembers: false
|
property bool addMembers: false
|
||||||
property int currMemberCount: 1
|
property int currMemberCount: 1
|
||||||
property int memberCount: 1
|
property int memberCount: 1
|
||||||
readonly property int maxMembers: 10
|
readonly property int maxMembers: 10
|
||||||
property var pubKeys: []
|
property var pubKeys: []
|
||||||
property var channel
|
property int channelType: GroupInfoPopup.ChannelType.ActiveChannel
|
||||||
|
property QtObject channel: {
|
||||||
|
if (channelType === GroupInfoPopup.ChannelType.ActiveChannel) {
|
||||||
|
return chatsModel.activeChannel
|
||||||
|
} else if (channelType === GroupInfoPopup.ChannelType.ContextChannel) {
|
||||||
|
return chatsModel.contextChannel
|
||||||
|
}
|
||||||
|
}
|
||||||
property bool isAdmin: false
|
property bool isAdmin: false
|
||||||
property Component pinnedMessagesPopupComponent
|
property Component pinnedMessagesPopupComponent
|
||||||
|
|
||||||
|
@ -227,6 +238,22 @@ ModalPopup {
|
||||||
anchors.topMargin: visible ? Style.current.halfPadding : 0
|
anchors.topMargin: visible ? Style.current.halfPadding : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: chatsModel
|
||||||
|
onActiveChannelChanged: {
|
||||||
|
if (popup.channelType === GroupInfoPopup.ChannelType.ActiveChannel) {
|
||||||
|
popup.channel = chatsModel.activeChannel
|
||||||
|
resetSelectedMembers()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onContextChannelChanged: {
|
||||||
|
if (popup.channelType === GroupInfoPopup.ChannelType.ContextChannel) {
|
||||||
|
popup.channel = chatsModel.contextChannel
|
||||||
|
resetSelectedMembers()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: memberList
|
id: memberList
|
||||||
anchors.top: separator2.bottom
|
anchors.top: separator2.bottom
|
||||||
|
|
Loading…
Reference in New Issue