fix(communities): re-joining of left communities
Fixes: #2649. Upon receipt of status-go signals which included communities that have been left (`joined: false`), those communities were being rejoined automatically when they should not have been. fix(communities): Invitation bubble button state updates The community state inside of the invitation bubble was not reactive to any community actions (such as joining, leaving, updating). In addition, requesting to join a community changed the button’s text to “Pending”, but upon approval, the button’s state was not updating. The component was setting an observed community in the Component.onCompleted event, which was occurring for all invitation bubbles, but because the community wasn’t bound correctly to the bubble, once a bubble with a different community was encountered, the community in context of the bubble wasn’t updated and instead used a local copy. Once the community was bound correctly (to be reactive), the states started working correctly. The invitation bubble has been simplied so that it has states instead of using lots of if/else statements inside of the property bindings. This simplified the component’s logic for things like onClick action and made it a lot easier to read and modify.
This commit is contained in:
parent
433698b252
commit
e281ec3871
|
@ -174,28 +174,35 @@ QtObject:
|
||||||
|
|
||||||
proc communityAdded*(self: CommunitiesView, communityId: string) {.signal.}
|
proc communityAdded*(self: CommunitiesView, communityId: string) {.signal.}
|
||||||
|
|
||||||
|
proc observedCommunityChanged*(self: CommunitiesView) {.signal.}
|
||||||
|
proc communityChanged*(self: CommunitiesView, communityId: string) {.signal.}
|
||||||
|
|
||||||
proc addCommunityToList*(self: CommunitiesView, community: Community) =
|
proc addCommunityToList*(self: CommunitiesView, community: Community) =
|
||||||
let communityCheck = self.communityList.getCommunityById(community.id)
|
let communityCheck = self.communityList.getCommunityById(community.id)
|
||||||
if (communityCheck.id == ""):
|
if (communityCheck.id == ""):
|
||||||
self.communityList.addCommunityItemToList(community)
|
self.communityList.addCommunityItemToList(community)
|
||||||
self.communityAdded(community.id)
|
self.communityAdded(community.id)
|
||||||
|
self.communityChanged(community.id)
|
||||||
else:
|
else:
|
||||||
self.communityList.replaceCommunity(community)
|
self.communityList.replaceCommunity(community)
|
||||||
|
self.communityChanged(community.id)
|
||||||
|
|
||||||
if (self.activeCommunity.active and self.activeCommunity.communityItem.id == community.id):
|
if (self.activeCommunity.active and self.activeCommunity.communityItem.id == community.id):
|
||||||
self.activeCommunity.setCommunityItem(community)
|
self.activeCommunity.setCommunityItem(community)
|
||||||
|
|
||||||
if (self.observedCommunity.communityItem.id == community.id):
|
if (self.observedCommunity.communityItem.id == community.id):
|
||||||
self.observedCommunity.setCommunityItem(community)
|
self.observedCommunity.setCommunityItem(community)
|
||||||
|
self.observedCommunityChanged()
|
||||||
|
|
||||||
if (community.joined == true):
|
if (community.joined == true and community.isMember == true):
|
||||||
let joinedCommunityCheck = self.joinedCommunityList.getCommunityById(community.id)
|
let joinedCommunityCheck = self.joinedCommunityList.getCommunityById(community.id)
|
||||||
if (joinedCommunityCheck.id == ""):
|
if (joinedCommunityCheck.id == ""):
|
||||||
self.joinedCommunityList.addCommunityItemToList(community)
|
self.joinedCommunityList.addCommunityItemToList(community)
|
||||||
else:
|
else:
|
||||||
self.joinedCommunityList.replaceCommunity(community)
|
self.joinedCommunityList.replaceCommunity(community)
|
||||||
elif (community.isMember == true):
|
self.joinedCommunitiesChanged()
|
||||||
discard self.joinCommunity(community.id, false)
|
|
||||||
|
if (community.isMember == true):
|
||||||
var i = 0
|
var i = 0
|
||||||
for communityRequest in self.myCommunityRequests:
|
for communityRequest in self.myCommunityRequests:
|
||||||
if (communityRequest.communityId == community.id):
|
if (communityRequest.communityId == community.id):
|
||||||
|
@ -203,6 +210,9 @@ QtObject:
|
||||||
self.myCommunityRequests.delete(i, i)
|
self.myCommunityRequests.delete(i, i)
|
||||||
break
|
break
|
||||||
i = i + 1
|
i = i + 1
|
||||||
|
# TODO: handle membership request rejection
|
||||||
|
# @cammellos mentioned this would likely changed in Communities Phase 3, so
|
||||||
|
# no need to polish now.
|
||||||
|
|
||||||
proc isCommunityRequestPending*(self: CommunitiesView, communityId: string): bool {.slot.} =
|
proc isCommunityRequestPending*(self: CommunitiesView, communityId: string): bool {.slot.} =
|
||||||
for communityRequest in self.myCommunityRequests:
|
for communityRequest in self.myCommunityRequests:
|
||||||
|
@ -277,8 +287,6 @@ QtObject:
|
||||||
error "Error creating the category", msg = e.msg
|
error "Error creating the category", msg = e.msg
|
||||||
result = fmt"Error creating the category: {e.msg}"
|
result = fmt"Error creating the category: {e.msg}"
|
||||||
|
|
||||||
proc observedCommunityChanged*(self: CommunitiesView) {.signal.}
|
|
||||||
|
|
||||||
proc setObservedCommunity*(self: CommunitiesView, communityId: string) {.slot.} =
|
proc setObservedCommunity*(self: CommunitiesView, communityId: string) {.slot.} =
|
||||||
if(communityId == ""): return
|
if(communityId == ""): return
|
||||||
var community = self.communityList.getCommunityById(communityId)
|
var community = self.communityList.getCommunityById(communityId)
|
||||||
|
@ -303,9 +311,12 @@ QtObject:
|
||||||
if (communityId == self.activeCommunity.communityItem.id):
|
if (communityId == self.activeCommunity.communityItem.id):
|
||||||
self.activeCommunity.setActive(false)
|
self.activeCommunity.setActive(false)
|
||||||
self.joinedCommunityList.removeCommunityItemFromList(communityId)
|
self.joinedCommunityList.removeCommunityItemFromList(communityId)
|
||||||
|
self.joinedCommunitiesChanged()
|
||||||
var updatedCommunity = self.communityList.getCommunityById(communityId)
|
var updatedCommunity = self.communityList.getCommunityById(communityId)
|
||||||
updatedCommunity.joined = false
|
updatedCommunity.joined = false
|
||||||
self.communityList.replaceCommunity(updatedCommunity)
|
self.communityList.replaceCommunity(updatedCommunity)
|
||||||
|
self.communitiesChanged()
|
||||||
|
self.communityChanged(communityId)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error "Error leaving the community", msg = e.msg
|
error "Error leaving the community", msg = e.msg
|
||||||
result = fmt"Error leaving the community: {e.msg}"
|
result = fmt"Error leaving the community: {e.msg}"
|
||||||
|
@ -367,10 +378,21 @@ QtObject:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error "Error requesting to join the community", msg = e.msg
|
error "Error requesting to join the community", msg = e.msg
|
||||||
|
|
||||||
|
proc removeMembershipRequest(self: CommunitiesView, requestId: string, accepted: bool) =
|
||||||
|
var i = 0
|
||||||
|
for request in self.myCommunityRequests:
|
||||||
|
if (request.id == requestId):
|
||||||
|
self.myCommunityRequests.delete(i, i)
|
||||||
|
let name = self.getCommunityNameById(request.communityId)
|
||||||
|
self.membershipRequestChanged(request.communityId, name, accepted)
|
||||||
|
break
|
||||||
|
i = i + 1
|
||||||
|
self.activeCommunity.communityMembershipRequestList.removeCommunityMembershipRequestItemFromList(requestId)
|
||||||
|
|
||||||
proc acceptRequestToJoinCommunity*(self: CommunitiesView, requestId: string): string {.slot.} =
|
proc acceptRequestToJoinCommunity*(self: CommunitiesView, requestId: string): string {.slot.} =
|
||||||
try:
|
try:
|
||||||
self.status.chat.acceptRequestToJoinCommunity(requestId)
|
self.status.chat.acceptRequestToJoinCommunity(requestId)
|
||||||
self.activeCommunity.communityMembershipRequestList.removeCommunityMembershipRequestItemFromList(requestId)
|
self.removeMembershipRequest(requestId, true)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error "Error accepting request to join the community", msg = e.msg
|
error "Error accepting request to join the community", msg = e.msg
|
||||||
return "Error accepting request to join the community"
|
return "Error accepting request to join the community"
|
||||||
|
@ -379,7 +401,7 @@ QtObject:
|
||||||
proc declineRequestToJoinCommunity*(self: CommunitiesView, requestId: string): string {.slot.} =
|
proc declineRequestToJoinCommunity*(self: CommunitiesView, requestId: string): string {.slot.} =
|
||||||
try:
|
try:
|
||||||
self.status.chat.declineRequestToJoinCommunity(requestId)
|
self.status.chat.declineRequestToJoinCommunity(requestId)
|
||||||
self.activeCommunity.communityMembershipRequestList.removeCommunityMembershipRequestItemFromList(requestId)
|
self.removeMembershipRequest(requestId, false)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
error "Error declining request to join the community", msg = e.msg
|
error "Error declining request to join the community", msg = e.msg
|
||||||
return "Error declining request to join the community"
|
return "Error declining request to join the community"
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
import NimQml, Tables, chronicles
|
import # std libs
|
||||||
import ../../../status/chat/chat
|
NimQml, Tables, json, strutils
|
||||||
import ../../../status/status
|
|
||||||
import ../../../status/accounts
|
import # vendor libs
|
||||||
import strutils
|
chronicles, json_serialization
|
||||||
|
|
||||||
|
import # status-desktop libs
|
||||||
|
../../../status/chat/chat, ../../../status/status, ../../../status/accounts
|
||||||
|
|
||||||
type
|
type
|
||||||
CommunityRoles {.pure.} = enum
|
CommunityRoles {.pure.} = enum
|
||||||
|
@ -118,6 +121,11 @@ QtObject:
|
||||||
result = newQVariant("")
|
result = newQVariant("")
|
||||||
of CommunityRoles.CommunityColor: result = newQVariant(communityItem.communityColor)
|
of CommunityRoles.CommunityColor: result = newQVariant(communityItem.communityColor)
|
||||||
|
|
||||||
|
proc getCommunityByIdJson(self: CommunityList, communityId: string): string {.slot.} =
|
||||||
|
for community in self.communities:
|
||||||
|
if (community.id == communityId):
|
||||||
|
result = Json.encode(community)
|
||||||
|
|
||||||
method roleNames(self: CommunityList): Table[int, string] =
|
method roleNames(self: CommunityList): Table[int, string] =
|
||||||
{
|
{
|
||||||
CommunityRoles.Name.int:"name",
|
CommunityRoles.Name.int:"name",
|
||||||
|
|
|
@ -315,7 +315,7 @@ proc createCommunity*(name: string, description: string, access: int, ensOnly: b
|
||||||
|
|
||||||
if rpcResult{"error"} != nil:
|
if rpcResult{"error"} != nil:
|
||||||
let error = Json.decode($rpcResult{"error"}, RpcError)
|
let error = Json.decode($rpcResult{"error"}, RpcError)
|
||||||
raise newException(RpcException, "Error editing community channel: " & error.message)
|
raise newException(RpcException, "Error creating community: " & error.message)
|
||||||
|
|
||||||
if rpcResult{"result"} != nil and rpcResult{"result"}.kind != JNull:
|
if rpcResult{"result"} != nil and rpcResult{"result"}.kind != JNull:
|
||||||
result = rpcResult["result"]["communities"][0].toCommunity()
|
result = rpcResult["result"]["communities"][0].toCommunity()
|
||||||
|
@ -338,7 +338,7 @@ proc editCommunity*(communityId: string, name: string, description: string, acce
|
||||||
|
|
||||||
if rpcResult{"error"} != nil:
|
if rpcResult{"error"} != nil:
|
||||||
let error = Json.decode($rpcResult{"error"}, RpcError)
|
let error = Json.decode($rpcResult{"error"}, RpcError)
|
||||||
raise newException(RpcException, "Error editing community channel: " & error.message)
|
raise newException(RpcException, "Error editing community: " & error.message)
|
||||||
|
|
||||||
if rpcResult{"result"} != nil and rpcResult{"result"}.kind != JNull:
|
if rpcResult{"result"} != nil and rpcResult{"result"}.kind != JNull:
|
||||||
result = rpcResult["result"]["communities"][0].toCommunity()
|
result = rpcResult["result"]["communities"][0].toCommunity()
|
||||||
|
@ -481,8 +481,7 @@ proc requestToJoinCommunity*(communityId: string, ensName: string): seq[Communit
|
||||||
}]).parseJSON()
|
}]).parseJSON()
|
||||||
|
|
||||||
var communityRequests: seq[CommunityMembershipRequest] = @[]
|
var communityRequests: seq[CommunityMembershipRequest] = @[]
|
||||||
|
if rpcResult{"result"}{"requestsToJoinCommunity"} != nil and rpcResult{"result"}{"requestsToJoinCommunity"}.kind != JNull:
|
||||||
if rpcResult{"result"}{"requestsToJoinCommunity"}.kind != JNull:
|
|
||||||
for jsonCommunityReqest in rpcResult["result"]["requestsToJoinCommunity"]:
|
for jsonCommunityReqest in rpcResult["result"]["requestsToJoinCommunity"]:
|
||||||
communityRequests.add(jsonCommunityReqest.toCommunityMembershipRequest())
|
communityRequests.add(jsonCommunityReqest.toCommunityMembershipRequest())
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,27 @@ Item {
|
||||||
height: childrenRect.height
|
height: childrenRect.height
|
||||||
width: rectangleBubbleLoader.width
|
width: rectangleBubbleLoader.width
|
||||||
|
|
||||||
Component.onCompleted: {
|
function getCommunity() {
|
||||||
chatsModel.communities.setObservedCommunity(root.communityId)
|
let community = JSON.parse(chatsModel.communities.list.getCommunityByIdJson(communityId));
|
||||||
|
if (community) {
|
||||||
root.invitedCommunity = chatsModel.communities.observedCommunity
|
community.nbMembers = community.members.length;
|
||||||
}
|
}
|
||||||
|
return community
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
root.invitedCommunity = getCommunity()
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: chatsModel.communities
|
||||||
|
onCommunityChanged: function (communityId) {
|
||||||
|
if (communityId === root.communityId) {
|
||||||
|
root.invitedCommunity = getCommunity()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Loader {
|
Loader {
|
||||||
id: rectangleBubbleLoader
|
id: rectangleBubbleLoader
|
||||||
|
@ -32,6 +48,8 @@ Item {
|
||||||
sourceComponent: Component {
|
sourceComponent: Component {
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: rectangleBubble
|
id: rectangleBubble
|
||||||
|
property alias button: joinBtn
|
||||||
|
property bool isPendingRequest: chatsModel.communities.isCommunityRequestPending(communityId)
|
||||||
width: 270
|
width: 270
|
||||||
height: childrenRect.height + Style.current.halfPadding
|
height: childrenRect.height + Style.current.halfPadding
|
||||||
radius: 16
|
radius: 16
|
||||||
|
@ -39,6 +57,74 @@ Item {
|
||||||
border.color: Style.current.border
|
border.color: Style.current.border
|
||||||
border.width: 1
|
border.width: 1
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: "requiresEns"
|
||||||
|
when: invitedCommunity.ensOnly && !profileModel.profile.ensVerified
|
||||||
|
PropertyChanges {
|
||||||
|
target: joinBtn
|
||||||
|
text: qsTr("Membership requires an ENS username")
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "inviteOnly"
|
||||||
|
when: invitedCommunity.access === Constants.communityChatInvitationOnlyAccess
|
||||||
|
PropertyChanges {
|
||||||
|
target: joinBtn
|
||||||
|
text: qsTr("You need to be invited")
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "pending"
|
||||||
|
when: invitedCommunity.access === Constants.communityChatOnRequestAccess &&
|
||||||
|
rectangleBubble.isPendingRequest
|
||||||
|
PropertyChanges {
|
||||||
|
target: joinBtn
|
||||||
|
text: qsTr("Pending")
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "joined"
|
||||||
|
when: invitedCommunity.joined && invitedCommunity.isMember
|
||||||
|
PropertyChanges {
|
||||||
|
target: joinBtn
|
||||||
|
text: qsTr("View")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "requestToJoin"
|
||||||
|
when: invitedCommunity.access === Constants.communityChatOnRequestAccess &&
|
||||||
|
// !invitedCommunity.joined && !invitedCommunity.isMember
|
||||||
|
invitedCommunity.canRequestAccess
|
||||||
|
PropertyChanges {
|
||||||
|
target: joinBtn
|
||||||
|
text: qsTr("Request to join")
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: "unjoined"
|
||||||
|
when: invitedCommunity.access === Constants.communityChatOnRequestAccess &&
|
||||||
|
invitedCommunity.isMember
|
||||||
|
PropertyChanges {
|
||||||
|
target: joinBtn
|
||||||
|
text: qsTr("Join")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: chatsModel.communities
|
||||||
|
onMembershipRequestChanged: function(communityId, communityName, requestAccepted) {
|
||||||
|
if (communityId === root.communityId) {
|
||||||
|
rectangleBubble.isPendingRequest = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO add check if verified
|
// TODO add check if verified
|
||||||
StyledText {
|
StyledText {
|
||||||
id: title
|
id: title
|
||||||
|
@ -58,10 +144,18 @@ Item {
|
||||||
|
|
||||||
StyledText {
|
StyledText {
|
||||||
id: invitedYou
|
id: invitedYou
|
||||||
text: isCurrentUser ?
|
text: {
|
||||||
|
if (chatsModel.channelView.activeChannel.chatType === Constants.chatTypeOneToOne) {
|
||||||
|
return isCurrentUser ?
|
||||||
qsTr("You invited %1 to join a community").arg(chatsModel.userNameOrAlias(chatsModel.channelView.activeChannel.id))
|
qsTr("You invited %1 to join a community").arg(chatsModel.userNameOrAlias(chatsModel.channelView.activeChannel.id))
|
||||||
//% "%1 invited you to join a community"
|
//% "%1 invited you to join a community"
|
||||||
: qsTrId("-1-invited-you-to-join-a-community").arg(displayUserName)
|
: qsTrId("-1-invited-you-to-join-a-community").arg(displayUserName)
|
||||||
|
} else {
|
||||||
|
return isCurrentUser ?
|
||||||
|
qsTr("You shared a community")
|
||||||
|
: qsTr("A community has been shared")
|
||||||
|
}
|
||||||
|
}
|
||||||
anchors.top: title.bottom
|
anchors.top: title.bottom
|
||||||
anchors.topMargin: 4
|
anchors.topMargin: 4
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
|
@ -127,69 +221,29 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusButton {
|
StatusButton {
|
||||||
property int access: invitedCommunity.access
|
|
||||||
property bool isPendingRequest: {
|
|
||||||
if (invitedCommunity.access !== Constants.communityChatOnRequestAccess) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return chatsModel.communities.isCommunityRequestPending(communityId)
|
|
||||||
}
|
|
||||||
id: joinBtn
|
id: joinBtn
|
||||||
type: "secondary"
|
type: "secondary"
|
||||||
anchors.top: sep2.bottom
|
anchors.top: sep2.bottom
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: 44
|
height: 44
|
||||||
enabled: {
|
enabled: true
|
||||||
if (invitedCommunity.ensOnly && !profileModel.profile.ensVerified) {
|
text: qsTr("Unsupported state")
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (joinBtn.access === Constants.communityChatInvitationOnlyAccess || isPendingRequest) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
text: {
|
|
||||||
if (invitedCommunity.ensOnly && !profileModel.profile.ensVerified) {
|
|
||||||
return qsTr("Membership requires an ENS username")
|
|
||||||
}
|
|
||||||
if (invitedCommunity.canJoin) {
|
|
||||||
return qsTr("Join")
|
|
||||||
}
|
|
||||||
if (invitedCommunity.joined || invitedCommunity.isMember) {
|
|
||||||
return qsTr("View")
|
|
||||||
}
|
|
||||||
if (isPendingRequest) {
|
|
||||||
return qsTr("Pending")
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(joinBtn.access) {
|
|
||||||
case Constants.communityChatPublicAccess: return qsTr("Join")
|
|
||||||
case Constants.communityChatInvitationOnlyAccess: return qsTr("You need to be invited");
|
|
||||||
case Constants.communityChatOnRequestAccess: return qsTr("Request to join")
|
|
||||||
default: return qsTr("Unknown community");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
let error
|
let error
|
||||||
|
|
||||||
if (invitedCommunity.joined || invitedCommunity.isMember) {
|
if (rectangleBubble.state === "joined") {
|
||||||
chatsModel.communities.setActiveCommunity(communityId);
|
chatsModel.communities.setActiveCommunity(communityId);
|
||||||
return
|
return
|
||||||
|
} else if (rectangleBubble.state === "unjoined") {
|
||||||
|
error = chatsModel.communities.joinCommunity(communityId, true)
|
||||||
}
|
}
|
||||||
|
else if (rectangleBubble.state === "requestToJoin") {
|
||||||
if (joinBtn.access === Constants.communityChatOnRequestAccess) {
|
|
||||||
error = chatsModel.communities.requestToJoinCommunity(communityId,
|
error = chatsModel.communities.requestToJoinCommunity(communityId,
|
||||||
profileModel.profile.ensVerified ? profileModel.profile.username : "")
|
profileModel.profile.ensVerified ? profileModel.profile.username : "")
|
||||||
if (!error) {
|
if (!error) {
|
||||||
enabled = false
|
rectangleBubble.isPendingRequest = chatsModel.communities.isCommunityRequestPending(communityId)
|
||||||
text = qsTr("Pending")
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
error = chatsModel.communities.joinCommunity(communityId, true)
|
|
||||||
enabled = false
|
|
||||||
text = qsTr("Joined")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
|
|
Loading…
Reference in New Issue