refactor(members): unify members models into one (#16508)

Fixes #16433
This commit is contained in:
Jonathan Rainville 2024-10-25 21:25:50 -04:00 committed by GitHub
parent d00690f53b
commit f7823cd0b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 353 additions and 255 deletions

View File

@ -206,8 +206,8 @@ method onChatMemberUpdated*(self: Module, publicKey: string, memberRole: MemberR
icon = contactDetails.icon,
isContact = contactDetails.dto.isContact,
isVerified = not isMe and contactDetails.dto.isContactVerified(),
memberRole = memberRole,
joined = joined,
memberRole,
joined,
isUntrustworthy = contactDetails.dto.trustStatus == TrustStatus.Untrustworthy,
)

View File

@ -198,54 +198,61 @@ proc createMemberItem(self: Module, memberId, requestId: string, status: Members
membershipRequestState = status,
)
method getCommunityItem(self: Module, c: CommunityDto): SectionItem =
# TODO: unite bannedMembers, pendingMemberRequests and declinedMemberRequests
var members: seq[MemberItem] = @[]
for member in c.members:
if c.pendingAndBannedMembers.hasKey(member.id):
let communityMemberState = c.pendingAndBannedMembers[member.id]
members.add(self.createMemberItem(member.id, "", toMembershipRequestState(communityMemberState)))
method getCommunityItem(self: Module, community: CommunityDto): SectionItem =
var memberItems: seq[MemberItem] = @[]
for member in community.members:
var communityMemberState = MembershipRequestState.Accepted
if community.pendingAndBannedMembers.hasKey(member.id):
let memberState = community.pendingAndBannedMembers[member.id].toMembershipRequestState()
if memberState == MembershipRequestState.BannedPending or memberState == MembershipRequestState.KickedPending:
communityMemberState = memberState
memberItems.add(self.createMemberItem(member.id, "", communityMemberState))
var bannedMembers: seq[MemberItem] = @[]
for memberId, communityMemberState in c.pendingAndBannedMembers:
for memberId, communityMemberState in community.pendingAndBannedMembers:
bannedMembers.add(self.createMemberItem(memberId, "", toMembershipRequestState(communityMemberState)))
let pendingMembers = community.pendingRequestsToJoin.map(proc(requestDto: CommunityMembershipRequestDto): MemberItem =
result = self.createMemberItem(requestDto.publicKey, requestDto.id, MembershipRequestState(requestDto.state))
)
let declinedMemberItems = community.declinedRequestsToJoin.map(proc(requestDto: CommunityMembershipRequestDto): MemberItem =
result = self.createMemberItem(requestDto.publicKey, requestDto.id, MembershipRequestState(requestDto.state))
)
memberItems = concat(memberItems, pendingMembers, declinedMemberItems, bannedMembers)
return initItem(
c.id,
community.id,
SectionType.Community,
c.name,
c.memberRole,
c.isControlNode,
c.description,
c.introMessage,
c.outroMessage,
c.images.thumbnail,
c.images.banner,
community.name,
community.memberRole,
community.isControlNode,
community.description,
community.introMessage,
community.outroMessage,
community.images.thumbnail,
community.images.banner,
icon = "",
c.color,
c.tags,
community.color,
community.tags,
hasNotification = false,
notificationsCount = 0,
active = false,
enabled = true,
c.joined,
c.canJoin,
c.spectated,
c.canManageUsers,
c.canRequestAccess,
c.isMember,
c.permissions.access,
c.permissions.ensOnly,
c.muted,
members = members,
historyArchiveSupportEnabled = c.settings.historyArchiveSupportEnabled,
bannedMembers = bannedMembers,
pendingMemberRequests = c.pendingRequestsToJoin.map(proc(requestDto: CommunityMembershipRequestDto): MemberItem =
result = self.createMemberItem(requestDto.publicKey, requestDto.id, MembershipRequestState(requestDto.state))),
declinedMemberRequests = c.declinedRequestsToJoin.map(proc(requestDto: CommunityMembershipRequestDto): MemberItem =
result = self.createMemberItem(requestDto.publicKey, requestDto.id, MembershipRequestState(requestDto.state))),
encrypted = c.encrypted,
communityTokens = @[]
community.joined,
community.canJoin,
community.spectated,
community.canManageUsers,
community.canRequestAccess,
community.isMember,
community.permissions.access,
community.permissions.ensOnly,
community.muted,
members = memberItems,
historyArchiveSupportEnabled = community.settings.historyArchiveSupportEnabled,
encrypted = community.encrypted,
communityTokens = @[],
activeMembersCount = int(community.activeMembersCount),
)
proc getCuratedCommunityItem(self: Module, community: CommunityDto): CuratedCommunityItem =
@ -302,8 +309,10 @@ method setCommunityTags*(self: Module, communityTags: string) =
self.view.setCommunityTags(communityTags)
method setAllCommunities*(self: Module, communities: seq[CommunityDto]) =
var items: seq[SectionItem] = @[]
for community in communities:
self.view.addItem(self.getCommunityItem(community))
items.add(self.getCommunityItem(community))
self.view.model.addItems(items)
method communityAdded*(self: Module, community: CommunityDto) =
self.view.addItem(self.getCommunityItem(community))

View File

@ -359,6 +359,36 @@ proc createCommunitySectionItem[T](self: Module[T], communityDetails: CommunityD
else:
discard
var memberItems = members.map(proc(member: ChatMember): MemberItem =
var state = MembershipRequestState.Accepted
if member.id in communityDetails.pendingAndBannedMembers:
let memberState = communityDetails.pendingAndBannedMembers[member.id].toMembershipRequestState()
if memberState == MembershipRequestState.BannedPending or memberState == MembershipRequestState.KickedPending:
state = memberState
elif not member.joined:
state = MembershipRequestState.AwaitingAddress
var airdropAddress = ""
if not existingCommunity.isEmpty() and not existingCommunity.communityTokens.isNil:
airdropAddress = existingCommunity.members.getAirdropAddressForMember(member.id)
result = self.createMemberItem(
member.id,
requestId = "",
state,
member.role,
airdropAddress,
)
)
let pendingMembers = communityDetails.pendingRequestsToJoin.map(proc(requestDto: CommunityMembershipRequestDto): MemberItem =
result = self.createMemberItem(requestDto.publicKey, requestDto.id, MembershipRequestState(requestDto.state), MemberRole.None)
)
let declinedMemberItems = communityDetails.declinedRequestsToJoin.map(proc(requestDto: CommunityMembershipRequestDto): MemberItem =
result = self.createMemberItem(requestDto.publicKey, requestDto.id, MembershipRequestState(requestDto.state), MemberRole.None)
)
memberItems = concat(memberItems, pendingMembers, declinedMemberItems, bannedMembers)
result = initItem(
communityDetails.id,
sectionType = SectionType.Community,
@ -386,42 +416,15 @@ proc createCommunitySectionItem[T](self: Module[T], communityDetails: CommunityD
communityDetails.permissions.access,
communityDetails.permissions.ensOnly,
communityDetails.muted,
# members
members.map(proc(member: ChatMember): MemberItem =
var state = MembershipRequestState.Accepted
if member.id in communityDetails.pendingAndBannedMembers:
let memberState = communityDetails.pendingAndBannedMembers[member.id].toMembershipRequestState()
if memberState == MembershipRequestState.BannedPending or memberState == MembershipRequestState.KickedPending:
state = memberState
elif not member.joined:
state = MembershipRequestState.AwaitingAddress
var airdropAddress = ""
if not existingCommunity.isEmpty() and not existingCommunity.communityTokens.isNil:
airdropAddress = existingCommunity.members.getAirdropAddressForMember(member.id)
result = self.createMemberItem(
member.id,
requestId = "",
state,
member.role,
airdropAddress,
)
),
memberItems,
communityDetails.settings.historyArchiveSupportEnabled,
communityDetails.adminSettings.pinMessageAllMembersEnabled,
bannedMembers,
# pendingMemberRequests
communityDetails.pendingRequestsToJoin.map(proc(requestDto: CommunityMembershipRequestDto): MemberItem =
result = self.createMemberItem(requestDto.publicKey, requestDto.id, MembershipRequestState(requestDto.state), MemberRole.None)
),
# declinedMemberRequests
communityDetails.declinedRequestsToJoin.map(proc(requestDto: CommunityMembershipRequestDto): MemberItem =
result = self.createMemberItem(requestDto.publicKey, requestDto.id, MembershipRequestState(requestDto.state), MemberRole.None)
),
communityDetails.encrypted,
communityTokensItems,
communityDetails.pubsubTopic,
communityDetails.pubsubTopicKey,
communityDetails.shard.index,
activeMembersCount = int(communityDetails.activeMembersCount),
)
proc connectForNotificationsOnly[T](self: Module[T]) =
@ -1358,7 +1361,7 @@ method newCommunityMembershipRequestReceived*[T](self: Module[T], membershipRequ
singletonInstance.globalEvents.newCommunityMembershipRequestNotification("New membership request",
fmt "{contactName} asks to join {community.name}", community.id)
self.view.model().addPendingMember(membershipRequest.communityId, self.createMemberItem(
self.view.model().addMember(membershipRequest.communityId, self.createMemberItem(
membershipRequest.publicKey,
membershipRequest.id,
MembershipRequestState(membershipRequest.state),
@ -1366,7 +1369,7 @@ method newCommunityMembershipRequestReceived*[T](self: Module[T], membershipRequ
))
method communityMembershipRequestCanceled*[T](self: Module[T], communityId: string, requestId: string, pubKey: string) =
self.view.model().removePendingMember(communityId, pubKey)
self.view.model().removeMember(communityId, pubKey)
method meMentionedCountChanged*[T](self: Module[T], allMentions: int) =
singletonInstance.globalEvents.meMentionedIconBadgeNotification(allMentions)

View File

@ -174,13 +174,17 @@ QtObject:
self.endInsertRows()
self.countChanged()
proc findIndexForMember(self: Model, pubKey: string): int =
proc findIndexForMember*(self: Model, pubKey: string): int =
for i in 0 ..< self.items.len:
if(self.items[i].pubKey == pubKey):
if self.items[i].pubKey == pubKey:
return i
return -1
proc getMemberItemByIndex*(self: Model, ind: int): MemberItem =
if ind >= 0 and ind < self.items.len:
return self.items[ind]
proc getMemberItem*(self: Model, pubKey: string): MemberItem =
let ind = self.findIndexForMember(pubKey)
if ind != -1:
@ -283,6 +287,7 @@ QtObject:
memberRole: MemberRole,
joined: bool,
isUntrustworthy: bool,
membershipRequestState: MembershipRequestState = MembershipRequestState.None,
callDataChanged: bool = true,
): seq[int] =
let ind = self.findIndexForMember(pubKey)
@ -307,6 +312,12 @@ QtObject:
updateRole(joined, Joined)
updateRole(isUntrustworthy, IsUntrustworthy)
var updatedMembershipRequestState = membershipRequestState
if updatedMembershipRequestState == MembershipRequestState.None:
updatedMembershipRequestState = self.items[ind].membershipRequestState
updateRoleWithValue(membershipRequestState, MembershipRequestState, updatedMembershipRequestState)
if preferredDisplayNameChanged:
roles.add(ModelRole.PreferredDisplayName.int)
@ -341,6 +352,7 @@ QtObject:
item.memberRole,
item.joined,
item.isUntrustworthy,
item.membershipRequestState,
callDataChanged = false,
)
@ -427,6 +439,7 @@ QtObject:
memberRole = self.items[ind].memberRole,
joined = self.items[ind].joined,
isUntrustworthy,
self.items[ind].membershipRequestState,
)
proc setOnlineStatus*(self: Model, pubKey: string, onlineStatus: OnlineStatus) =
@ -509,3 +522,9 @@ QtObject:
break
if not found:
result.add(pubkey)
proc isUserBanned*(self: Model, pubkey: string): bool =
let ind = self.findIndexForMember(pubkey)
if ind == -1:
return false
return self.getMemberItemByIndex(ind).membershipRequestState == MembershipRequestState.Banned

View File

@ -49,15 +49,13 @@ type
membersModel: member_model.Model
historyArchiveSupportEnabled: bool
pinMessageAllMembersEnabled: bool
bannedMembersModel: member_model.Model
pendingMemberRequestsModel*: member_model.Model
declinedMemberRequestsModel: member_model.Model
encrypted: bool
communityTokensModel: community_tokens_model.TokenModel
pubsubTopic: string
pubsubTopicKey: string
shardIndex: int
isPendingOwnershipRequest: bool
activeMembersCount: int
proc initItem*(
id: string,
@ -89,15 +87,13 @@ proc initItem*(
members: seq[MemberItem] = @[],
historyArchiveSupportEnabled = false,
pinMessageAllMembersEnabled = false,
bannedMembers: seq[MemberItem] = @[],
pendingMemberRequests: seq[MemberItem] = @[],
declinedMemberRequests: seq[MemberItem] = @[],
encrypted: bool = false,
communityTokens: seq[TokenItem] = @[],
pubsubTopic = "",
pubsubTopicKey = "",
shardIndex = -1,
isPendingOwnershipRequest: bool = false
isPendingOwnershipRequest: bool = false,
activeMembersCount: int = 0,
): SectionItem =
result.id = id
result.sectionType = sectionType
@ -129,12 +125,6 @@ proc initItem*(
result.membersModel.setItems(members)
result.historyArchiveSupportEnabled = historyArchiveSupportEnabled
result.pinMessageAllMembersEnabled = pinMessageAllMembersEnabled
result.bannedMembersModel = newModel()
result.bannedMembersModel.setItems(bannedMembers)
result.pendingMemberRequestsModel = newModel()
result.pendingMemberRequestsModel.setItems(pendingMemberRequests)
result.declinedMemberRequestsModel = newModel()
result.declinedMemberRequestsModel.setItems(declinedMemberRequests)
result.encrypted = encrypted
result.communityTokensModel = newTokenModel()
result.communityTokensModel.setItems(communityTokens)
@ -142,6 +132,7 @@ proc initItem*(
result.pubsubTopicKey = pubsubTopicKey
result.shardIndex = shardIndex
result.isPendingOwnershipRequest = isPendingOwnershipRequest
result.activeMembersCount = activeMembersCount
proc isEmpty*(self: SectionItem): bool =
return self.id.len == 0
@ -177,9 +168,6 @@ proc `$`*(self: SectionItem): string =
members:{self.membersModel},
historyArchiveSupportEnabled:{self.historyArchiveSupportEnabled},
pinMessageAllMembersEnabled:{self.pinMessageAllMembersEnabled},
bannedMembers:{self.bannedMembersModel},
pendingMemberRequests:{self.pendingMemberRequestsModel},
declinedMemberRequests:{self.declinedMemberRequestsModel},
encrypted:{self.encrypted},
communityTokensModel:{self.communityTokensModel},
isPendingOwnershipRequest:{self.isPendingOwnershipRequest}
@ -365,17 +353,8 @@ proc updateMember*(
self.membersModel.updateItem(pubkey, name, ensName, isEnsVerified, nickname, alias, image, isContact,
isVerified, isUntrustworthy)
proc bannedMembers*(self: SectionItem): member_model.Model {.inline.} =
self.bannedMembersModel
proc amIBanned*(self: SectionItem): bool {.inline.} =
self.bannedMembersModel.isContactWithIdAdded(singletonInstance.userProfile.getPubKey())
proc pendingMemberRequests*(self: SectionItem): member_model.Model {.inline.} =
self.pendingMemberRequestsModel
proc declinedMemberRequests*(self: SectionItem): member_model.Model {.inline.} =
self.declinedMemberRequestsModel
return self.membersModel.isUserBanned(singletonInstance.userProfile.getPubKey())
proc isPendingOwnershipRequest*(self: SectionItem): bool {.inline.} =
self.isPendingOwnershipRequest
@ -438,13 +417,9 @@ proc communityTokens*(self: SectionItem): community_tokens_model.TokenModel {.in
self.communityTokensModel
proc updatePendingRequestLoadingState*(self: SectionItem, memberKey: string, loading: bool) {.inline.} =
self.pendingMemberRequestsModel.updateLoadingState(memberKey, loading)
self.membersModel.updateLoadingState(memberKey, loading)
proc updateMembershipStatus*(self: SectionItem, memberKey: string, state: MembershipRequestState) {.inline.} =
case state:
of MembershipRequestState.Banned, MembershipRequestState.BannedWithAllMessagesDelete, MembershipRequestState.UnbannedPending:
self.bannedMembersModel.updateMembershipStatus(memberKey, state)
else:
self.membersModel.updateMembershipStatus(memberKey, state)
proc pubsubTopic*(self: SectionItem): string {.inline.} =
@ -464,3 +439,9 @@ proc shardIndex*(self: SectionItem): int {.inline.} =
proc `shardIndex=`*(self: var SectionItem, value: int) {.inline.} =
self.shardIndex = value
proc activeMembersCount*(self: SectionItem): int {.inline.} =
self.activeMembersCount
proc `activeMembersCount=`*(self: var SectionItem, value: int) {.inline.} =
self.activeMembersCount = value

View File

@ -37,16 +37,14 @@ type
MembersModel
HistoryArchiveSupportEnabled
PinMessageAllMembersEnabled
BannedMembersModel
Encrypted
CommunityTokensModel
PendingMemberRequestsModel
DeclinedMemberRequestsModel
AmIBanned
PubsubTopic
PubsubTopicKey
ShardIndex
IsPendingOwnershipRequest
ActiveMembersCount
QtObject:
type
@ -110,19 +108,17 @@ QtObject:
ModelRole.Access.int:"access",
ModelRole.EnsOnly.int:"ensOnly",
ModelRole.Muted.int:"muted",
ModelRole.MembersModel.int:"members",
ModelRole.MembersModel.int:"allMembers",
ModelRole.HistoryArchiveSupportEnabled.int:"historyArchiveSupportEnabled",
ModelRole.PinMessageAllMembersEnabled.int:"pinMessageAllMembersEnabled",
ModelRole.BannedMembersModel.int:"bannedMembers",
ModelRole.Encrypted.int:"encrypted",
ModelRole.CommunityTokensModel.int:"communityTokens",
ModelRole.PendingMemberRequestsModel.int:"pendingMemberRequests",
ModelRole.DeclinedMemberRequestsModel.int:"declinedMemberRequests",
ModelRole.AmIBanned.int:"amIBanned",
ModelRole.PubsubTopic.int:"pubsubTopic",
ModelRole.PubsubTopicKey.int:"pubsubTopicKey",
ModelRole.ShardIndex.int:"shardIndex",
ModelRole.IsPendingOwnershipRequest.int:"isPendingOwnershipRequest",
ModelRole.ActiveMembersCount.int:"activeMembersCount",
}.toTable
method data(self: SectionModel, index: QModelIndex, role: int): QVariant =
@ -194,16 +190,10 @@ QtObject:
result = newQVariant(item.historyArchiveSupportEnabled)
of ModelRole.PinMessageAllMembersEnabled:
result = newQVariant(item.pinMessageAllMembersEnabled)
of ModelRole.BannedMembersModel:
result = newQVariant(item.bannedMembers)
of ModelRole.Encrypted:
result = newQVariant(item.encrypted)
of ModelRole.CommunityTokensModel:
result = newQVariant(item.communityTokens)
of ModelRole.PendingMemberRequestsModel:
result = newQVariant(item.pendingMemberRequests)
of ModelRole.DeclinedMemberRequestsModel:
result = newQVariant(item.declinedMemberRequests)
of ModelRole.AmIBanned:
result = newQVariant(item.amIBanned)
of ModelRole.PubsubTopic:
@ -214,6 +204,8 @@ QtObject:
result = newQVariant(item.shardIndex)
of ModelRole.IsPendingOwnershipRequest:
result = newQVariant(item.isPendingOwnershipRequest)
of ModelRole.ActiveMembersCount:
result = newQVariant(item.activeMembersCount)
proc itemExists*(self: SectionModel, id: string): bool =
for it in self.items:
@ -330,11 +322,9 @@ QtObject:
updateRoleWithValue(pubsubTopicKey, PubsubTopicKey, item.pubsubTopicKey)
updateRoleWithValue(shardIndex, ShardIndex, item.shardIndex)
updateRoleWithValue(isPendingOwnershipRequest, IsPendingOwnershipRequest, item.isPendingOwnershipRequest)
updateRoleWithValue(activeMembersCount, ActiveMembersCount, item.activeMembersCount)
self.items[ind].members.updateToTheseItems(item.members.getItems())
self.items[ind].bannedMembers.updateToTheseItems(item.bannedMembers.getItems())
self.items[ind].pendingMemberRequests.updateToTheseItems(item.pendingMemberRequests.getItems())
self.items[ind].declinedMemberRequests.updateToTheseItems(item.declinedMemberRequests.getItems())
if roles.len == 0:
return
@ -357,7 +347,6 @@ QtObject:
isUntrustworthy: bool,
) =
for item in self.items:
# TODO refactor to use only one model https://github.com/status-im/status-desktop/issues/16433
item.members.updateItem(
pubKey,
displayName,
@ -370,42 +359,6 @@ QtObject:
isVerified,
isUntrustworthy,
)
item.bannedMembers.updateItem(
pubKey,
displayName,
ensName,
isEnsVerified,
localNickname,
alias,
icon,
isContact,
isVerified,
isUntrustworthy,
)
item.pendingMemberRequests.updateItem(
pubKey,
displayName,
ensName,
isEnsVerified,
localNickname,
alias,
icon,
isContact,
isVerified,
isUntrustworthy,
)
item.declinedMemberRequests.updateItem(
pubKey,
displayName,
ensName,
isEnsVerified,
localNickname,
alias,
icon,
isContact,
isVerified,
isUntrustworthy,
)
proc getNthEnabledItem*(self: SectionModel, nth: int): SectionItem =
if nth >= 0 and nth < self.items.len:
@ -598,16 +551,16 @@ QtObject:
self.items[index].communityTokens.setItems(communityTokensItems)
proc addPendingMember*(self: SectionModel, communityId: string, memberItem: MemberItem) =
proc addMember*(self: SectionModel, communityId: string, memberItem: MemberItem) =
let i = self.getItemIndex(communityId)
if i == -1:
return
self.items[i].pendingMemberRequests.addItem(memberItem)
self.items[i].members.addItem(memberItem)
proc removePendingMember*(self: SectionModel, communityId: string, memberId: string) =
proc removeMember*(self: SectionModel, communityId: string, memberId: string) =
let i = self.getItemIndex(communityId)
if i == -1:
return
self.items[i].pendingMemberRequests.removeItemById(memberId)
self.items[i].members.removeItemById(memberId)

View File

@ -61,18 +61,19 @@ type MemberRole* {.pure} = enum
type MembershipRequestState* {.pure} = enum
None = 0,
Pending = 1,
Accepted = 2,
Declined = 3,
AcceptedPending = 4,
DeclinedPending = 5,
Banned = 6,
Kicked = 7,
BannedPending = 8,
UnbannedPending = 9,
KickedPending = 10,
AwaitingAddress = 11,
Unbanned = 12,
BannedWithAllMessagesDelete = 13
Declined = 2,
Accepted = 3
Canceled = 4,
AcceptedPending = 5,
DeclinedPending = 6,
AwaitingAddress = 7,
Banned = 8,
Kicked = 9,
BannedPending = 10,
UnbannedPending = 11,
KickedPending = 12,
Unbanned = 13,
BannedWithAllMessagesDelete = 14
type
ContractTransactionStatus* {.pure.} = enum

View File

@ -57,7 +57,7 @@ Item {
sourceComponent: ProfilePopupInviteFriendsPanel {
id: panel
community: ({ id: "communityId" })
communityId: "communityId"
rootStore: AppLayoutStores.RootStore {
function communityHasMember(communityId, pubKey) {

View File

@ -18,7 +18,9 @@ import AppLayouts.Chat.stores 1.0 as ChatStores
import AppLayouts.Profile.stores 1.0 as ProfileStores
import AppLayouts.Wallet.stores 1.0 as WalletStore
import StatusQ 0.1
import StatusQ.Core.Utils 0.1
import SortFilterProxyModel 0.2
StackLayout {
id: root
@ -35,6 +37,12 @@ StackLayout {
required property SharedStores.CurrenciesStore currencyStore
property var sectionItemModel
MembersModelAdaptor {
id: membersModelAdaptor
allMembers: !!sectionItemModel ? sectionItemModel.allMembers : null
}
property var sendModalPopup
readonly property bool isOwner: sectionItemModel.memberRole === Constants.memberRole.owner
@ -96,23 +104,22 @@ StackLayout {
id: joinCommunityViewComponent
JoinCommunityView {
id: joinCommunityView
readonly property var communityData: sectionItemModel
readonly property string communityId: communityData.id
name: communityData.name
introMessage: communityData.introMessage
communityDesc: communityData.description
color: communityData.color
image: communityData.image
membersCount: communityData.members.count
readonly property string communityId: sectionItemModel.id
name: sectionItemModel.name
introMessage: sectionItemModel.introMessage
communityDesc: sectionItemModel.description
color: sectionItemModel.color
image: sectionItemModel.image
membersCount: membersModelAdaptor.joinedMembers.ModelCount.count
accessType: mainViewLoader.accessType
joinCommunity: true
amISectionAdmin: communityData.memberRole === Constants.memberRole.owner ||
communityData.memberRole === Constants.memberRole.admin ||
communityData.memberRole === Constants.memberRole.tokenMaster
amISectionAdmin: sectionItemModel.memberRole === Constants.memberRole.owner ||
sectionItemModel.memberRole === Constants.memberRole.admin ||
sectionItemModel.memberRole === Constants.memberRole.tokenMaster
communityItemsModel: root.rootStore.communityItemsModel
requirementsMet: root.permissionsStore.allTokenRequirementsMet
requirementsCheckPending: root.rootStore.permissionsCheckOngoing
requiresRequest: !communityData.amIMember
requiresRequest: !sectionItemModel.amIMember
communityHoldingsModel: root.permissionsStore.becomeMemberPermissionsModel
viewOnlyHoldingsModel: root.permissionsStore.viewOnlyPermissionsModel
viewAndPostHoldingsModel: root.permissionsStore.viewAndPostPermissionsModel
@ -125,13 +132,13 @@ StackLayout {
onNotificationButtonClicked: Global.openActivityCenterPopup()
onAdHocChatButtonClicked: rootStore.openCloseCreateChatView()
onRequestToJoinClicked: {
Global.communityIntroPopupRequested(joinCommunityView.communityId, communityData.name,
communityData.introMessage, communityData.image,
Global.communityIntroPopupRequested(joinCommunityView.communityId, sectionItemModel.name,
sectionItemModel.introMessage, sectionItemModel.image,
root.isInvitationPending)
}
onInvitationPendingClicked: {
Global.communityIntroPopupRequested(joinCommunityView.communityId, communityData.name, communityData.introMessage,
communityData.image, root.isInvitationPending)
Global.communityIntroPopupRequested(joinCommunityView.communityId, sectionItemModel.name, sectionItemModel.introMessage,
sectionItemModel.image, root.isInvitationPending)
}
}
}
@ -157,6 +164,7 @@ StackLayout {
currencyStore: root.currencyStore
sendModalPopup: root.sendModalPopup
sectionItemModel: root.sectionItemModel
joinedMembersCount: membersModelAdaptor.joinedMembers.ModelCount.count
amIMember: sectionItem.amIMember
amISectionAdmin: root.sectionItemModel.memberRole === Constants.memberRole.owner ||
root.sectionItemModel.memberRole === Constants.memberRole.admin ||
@ -250,7 +258,11 @@ StackLayout {
isPendingOwnershipRequest: root.isPendingOwnershipRequest
chatCommunitySectionModule: root.rootStore.chatCommunitySectionModule
community: sectionItemModel
community: root.sectionItemModel
joinedMembers: membersModelAdaptor.joinedMembers
bannedMembers: membersModelAdaptor.bannedMembers
pendingMembers: membersModelAdaptor.pendingMembers
declinedMembers: membersModelAdaptor.declinedMembers
communitySettingsDisabled: root.communitySettingsDisabled
onCommunitySettingsDisabledChanged: if (communitySettingsDisabled) goTo(Constants.CommunitySettingsSections.Overview)
@ -263,12 +275,11 @@ StackLayout {
id: controlNodeOfflineComponent
ControlNodeOfflineCommunityView {
id: controlNodeOfflineView
readonly property var communityData: sectionItemModel
name: communityData.name
communityDesc: communityData.description
color: communityData.color
image: communityData.image
membersCount: communityData.members.count
name: root.sectionItemModel.name
communityDesc: root.sectionItemModel.description
color: root.sectionItemModel.color
image: root.sectionItemModel.image
membersCount: membersModelAdaptor.joinedMembers.ModelCount.count
communityItemsModel: root.rootStore.communityItemsModel
notificationCount: activityCenterStore.unreadNotificationsCount
hasUnseenNotifications: activityCenterStore.hasUnseenNotifications
@ -282,11 +293,11 @@ StackLayout {
BannedMemberCommunityView {
id: communityBanView
readonly property var communityData: sectionItemModel
name: communityData.name
communityDesc: communityData.description
color: communityData.color
image: communityData.image
membersCount: communityData.members.count
name: root.sectionItemModel.name
communityDesc: root.sectionItemModel.description
color: root.sectionItemModel.color
image: root.sectionItemModel.image
membersCount: membersModelAdaptor.joinedMembers.count
communityItemsModel: root.rootStore.communityItemsModel
notificationCount: activityCenterStore.unreadNotificationsCount
hasUnseenNotifications: activityCenterStore.hasUnseenNotifications

View File

@ -50,6 +50,7 @@ StatusSectionLayout {
required property SharedStores.CurrenciesStore currencyStore
required property var sendModalPopup
property var sectionItemModel
property int joinedMembersCount
property var emojiPopup
property var stickersPopup
@ -300,7 +301,8 @@ StatusSectionLayout {
id: communtiyColumnComponent
CommunityColumnView {
communitySectionModule: root.rootStore.chatCommunitySectionModule
communityData: sectionItemModel
communityData: root.sectionItemModel
joinedMembersCount: root.joinedMembersCount
store: root.rootStore
communitiesStore: root.communitiesStore
walletAssetsStore: root.walletAssetsStore

View File

@ -0,0 +1,113 @@
import QtQml 2.15
import StatusQ 0.1
import StatusQ.Models 0.1
import StatusQ.Core.Utils 0.1
import utils 1.0
import SortFilterProxyModel 0.2
QObject {
id: root
/**
Expected model structure:
pubKey [string] - unique identifier of a member, e.g "0x3234235"
displayName [string] - member's chosen name
preferredDisplayName [string] - calculated member name according to priorities (eg: nickname has higher priority)
ensName [string] - member's ENS name
isEnsVerified [bool] - whether the ENS name was verified on chain
localNickname [string] - local nickname set by the current user
alias [string] - generated 3 word name
icon [string] - thumbnail image of the user
colorId [string] - generated color ID for the user's profile
colorHash [string] - generated color hash for the user's profile
onlineStatus [int] - the online status of the member
isContact [bool] - whether the user is a mutual contact or not
isVerified [bool] - wheter the user has been marked as verified or not
isUntrustworthy [bool] - wheter the user has been marked as untrustworthy or not
isBlocked [bool] - whether the user has been blocked or not
contactRequest [int] - state of the contact request that was sent
incomingVerificationStatus [int] - state of the verification request that was received
outgoingVerificationStatus [int] - state of the verification request that was send
memberRole [int] - role of the member in the community
joined [bool] - whether the user has joined the community
requestToJoinId [string] - the user's request to join ID
requestToJoinLoading [bool] - whether the request is being processed after an admin made an action (loading state)
airdropAddress [string] - the member's airdrop address (only available to TMs and owners)
membershipRequestState [int] - the user's membership state (pending, joined, etc.)
**/
property var allMembers
readonly property var joinedMembers: SortFilterProxyModel {
sourceModel: root.allMembers ?? null
filters: AnyOf {
ValueFilter {
roleName: "membershipRequestState"
value: Constants.CommunityMembershipRequestState.Accepted
}
ValueFilter {
roleName: "membershipRequestState"
value: Constants.CommunityMembershipRequestState.KickedPending
}
ValueFilter {
roleName: "membershipRequestState"
value: Constants.CommunityMembershipRequestState.BannedPending
}
ValueFilter {
roleName: "membershipRequestState"
value: Constants.CommunityMembershipRequestState.AwaitingAddress
}
}
}
readonly property var bannedMembers: SortFilterProxyModel {
sourceModel: root.allMembers ?? null
filters: AnyOf {
ValueFilter {
roleName: "membershipRequestState"
value: Constants.CommunityMembershipRequestState.Banned
}
ValueFilter {
roleName: "membershipRequestState"
value: Constants.CommunityMembershipRequestState.UnbannedPending
}
ValueFilter {
roleName: "membershipRequestState"
value: Constants.CommunityMembershipRequestState.BannedWithAllMessagesDelete
}
}
}
readonly property var pendingMembers: SortFilterProxyModel {
sourceModel: root.allMembers ?? null
filters: AnyOf {
ValueFilter {
roleName: "membershipRequestState"
value: Constants.CommunityMembershipRequestState.Pending
}
ValueFilter {
roleName: "membershipRequestState"
value: Constants.CommunityMembershipRequestState.AcceptedPending
}
ValueFilter {
roleName: "membershipRequestState"
value: Constants.CommunityMembershipRequestState.RejectedPending
}
}
}
readonly property var declinedMembers: SortFilterProxyModel {
sourceModel: root.allMembers ?? null
filters: ValueFilter {
roleName: "membershipRequestState"
value: Constants.CommunityMembershipRequestState.Rejected
}
}
}

View File

@ -1,6 +1,7 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import StatusQ 0.1
import StatusQ.Controls 0.1
import utils 1.0
@ -14,8 +15,8 @@ SettingsPage {
property RootStore rootStore
property var membersModel
property var bannedMembersModel
property var pendingMemberRequestsModel
property var declinedMemberRequestsModel
property var pendingMembersModel
property var declinedMembersModel
property string communityName
property int memberRole
@ -79,7 +80,7 @@ SettingsPage {
objectName: "pendingRequestsButton"
width: implicitWidth
text: qsTr("Pending Requests")
enabled: pendingMemberRequestsModel.count > 0
enabled: pendingMembersModel.ModelCount.count > 0
}
StatusTabButton {
@ -87,14 +88,14 @@ SettingsPage {
objectName: "declinedRequestsButton"
width: implicitWidth
text: qsTr("Rejected")
enabled: declinedMemberRequestsModel.count > 0
enabled: declinedMembersModel.ModelCount.count > 0
}
StatusTabButton {
id: bannedBtn
objectName: "bannedButton"
width: implicitWidth
enabled: bannedMembersModel.count > 0
enabled: bannedMembersModel.ModelCount.count > 0
text: qsTr("Banned")
}
}
@ -110,10 +111,10 @@ SettingsPage {
rootStore: root.rootStore
memberRole: root.memberRole
placeholderText: {
if (root.membersModel.count === 0)
if (root.membersModel.ModelCount.count === 0)
return qsTr("No members to search")
return qsTr("Search %1's %n member(s)", "", root.membersModel ? root.membersModel.count : 0).arg(root.communityName)
return qsTr("Search %1's %n member(s)", "", root.membersModel ? root.membersModel.ModelCount.count : 0).arg(root.communityName)
}
panelType: MembersTabPanel.TabType.AllMembers
@ -138,14 +139,14 @@ SettingsPage {
}
MembersTabPanel {
model: root.pendingMemberRequestsModel
model: root.pendingMembersModel
rootStore: root.rootStore
memberRole: root.memberRole
placeholderText: {
if (root.pendingMemberRequestsModel.count === 0)
if (root.pendingMembersModel.ModelCount.count === 0)
return qsTr("No pending requests to search")
return qsTr("Search %1's %n pending request(s)", "", root.pendingMemberRequestsModel.count).arg(root.communityName)
return qsTr("Search %1's %n pending request(s)", "", root.pendingMembersModel.ModelCount.count).arg(root.communityName)
}
panelType: MembersTabPanel.TabType.PendingRequests
@ -157,14 +158,14 @@ SettingsPage {
}
MembersTabPanel {
model: root.declinedMemberRequestsModel
model: root.declinedMembersModel
rootStore: root.rootStore
memberRole: root.memberRole
placeholderText: {
if (root.declinedMemberRequestsModel.count === 0)
if (root.declinedMembersModel.ModelCount.count === 0)
return qsTr("No rejected members to search")
return qsTr("Search %1's %n rejected member(s)", "", root.declinedMemberRequestsModel.count).arg(root.communityName)
return qsTr("Search %1's %n rejected member(s)", "", root.declinedMembersModel.ModelCount.count).arg(root.communityName)
}
panelType: MembersTabPanel.TabType.DeclinedRequests
@ -179,10 +180,10 @@ SettingsPage {
rootStore: root.rootStore
memberRole: root.memberRole
placeholderText: {
if (root.bannedMembersModel.count === 0)
if (root.bannedMembersModel.ModelCount.count === 0)
return qsTr("No banned members to search")
return qsTr("Search %1's %n banned member(s)", "", root.bannedMembersModel.count).arg(root.communityName)
return qsTr("Search %1's %n banned member(s)", "", root.bannedMembersModel.ModelCount.count).arg(root.communityName)
}
panelType: MembersTabPanel.TabType.BannedMembers

View File

@ -25,7 +25,7 @@ ColumnLayout {
property AppLayoutStores.RootStore rootStore
property ProfileStores.ContactsStore contactsStore
property var community
property string communityId
property var pubKeys: ([])
@ -58,7 +58,7 @@ ColumnLayout {
rootStore: root.rootStore
contactsStore: root.contactsStore
communityId: root.community.id
communityId: root.communityId
hideCommunityMembers: true
showCheckbox: true
@ -90,11 +90,11 @@ ColumnLayout {
StatusDescriptionListItem {
Layout.fillWidth: true
title: qsTr("Share community")
subTitle: Utils.getCommunityShareLink(root.community.id)
subTitle: Utils.getCommunityShareLink(root.communityId)
tooltip.text: qsTr("Copied!")
asset.name: "copy"
iconButton.onClicked: {
let link = Utils.getCommunityShareLink(root.community.id)
let link = Utils.getCommunityShareLink(root.communityId)
ClipboardUtils.setText(link)
tooltip.visible = !tooltip.visible
}

View File

@ -17,7 +17,7 @@ StatusDialog {
required property var community
signal importControlNode(var community)
signal importControlNode(string communityId)
width: 640
@ -76,7 +76,7 @@ StatusDialog {
text: qsTr("Make this device the control node for %1").arg(root.community.name)
enabled: agreementCheckBox.checked && agreementCheckBox2.checked
onClicked: {
root.importControlNode(root.community)
root.importControlNode(root.community.id)
root.close()
}
}

View File

@ -96,7 +96,7 @@ StatusStackModal {
ProfilePopupInviteFriendsPanel {
rootStore: root.rootStore
contactsStore: root.contactsStore
community: root.community
communityId: root.communityId
onPubKeysChanged: root.pubKeys = pubKeys
},

View File

@ -44,6 +44,7 @@ Item {
required property CurrenciesStore currencyStore
property bool hasAddedContacts: false
property var communityData
property int joinedMembersCount
property alias createChannelPopup: createChannelPopup
property int requestToJoinState: Constants.RequestToJoinState.None
@ -79,7 +80,7 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
name: communityData.name
membersCount: communityData.members.count
membersCount: root.joinedMembersCount
image: communityData.image
color: communityData.color
amISectionAdmin: root.isSectionAdmin

View File

@ -38,7 +38,11 @@ StatusSectionLayout {
property ChatStores.RootStore rootStore
property var chatCommunitySectionModule
required property TokensStore tokensStore
property var community
required property var community
required property var joinedMembers
required property var bannedMembers
required property var pendingMembers
required property var declinedMembers
required property TransactionStore transactionStore
property bool communitySettingsDisabled
property var sendModalPopup
@ -109,7 +113,7 @@ StatusSectionLayout {
id: communityHeader
title: community.name
subTitle: qsTr("%n member(s)", "", community.members.count || 0)
subTitle: qsTr("%n member(s)", "", root.joinedMembers.ModelCount.count || 0)
asset.name: community.image
asset.color: community.color
asset.isImage: true
@ -291,10 +295,10 @@ StatusSectionLayout {
sourceComponent: MembersSettingsPanel {
rootStore: root.rootStore
membersModel: root.community.members
bannedMembersModel: root.community.bannedMembers
pendingMemberRequestsModel: root.community.pendingMemberRequests
declinedMemberRequestsModel: root.community.declinedMemberRequests
membersModel: root.joinedMembers
bannedMembersModel: root.bannedMembers
pendingMembersModel: root.pendingMembers
declinedMembersModel: root.declinedMembers
editable: root.isAdmin || root.isOwner || root.isTokenMasterOwner
memberRole: community.memberRole
communityName: root.community.name
@ -392,7 +396,7 @@ StatusSectionLayout {
// Models
tokensModel: root.community.communityTokens
membersModel: root.community.members
membersModel: root.joinedMembers
flatNetworks: communityTokensStore.filteredFlatModel
accounts: root.walletAccountsModel
referenceAssetsBySymbolModel: root.tokensStore.assetsBySymbolModel
@ -559,7 +563,7 @@ StatusSectionLayout {
}
}
membersModel: community.members
membersModel: root.joinedMembers
enabledChainIds: root.enabledChainIds
onEnableNetwork: root.enableNetwork(chainId)

View File

@ -57,15 +57,12 @@ QObject {
},
FastExpressionRole {
name: "membersCount"
expression: model.members.count
expectedRoles: ["members"]
expression: model.allMembers.rowCount()
expectedRoles: ["allMembers"]
},
FastExpressionRole {
ConstantRole {
name: "showcaseVisibility"
expression: getShowcaseVisibility()
function getShowcaseVisibility() {
return Constants.ShowcaseVisibility.Everyone
}
value: Constants.ShowcaseVisibility.Everyone
},
FastExpressionRole {
name: "isShowcaseLoading"

View File

@ -55,12 +55,12 @@ QObject {
},
FastExpressionRole {
name: "membersCount"
expression: model.members.count
expectedRoles: ["members"]
expression: model.allMembers.rowCount()
expectedRoles: ["allMembers"]
},
FastExpressionRole {
ConstantRole {
name: "isShowcaseLoading"
expression: false
value: false
}
]
filters: ValueFilter {

View File

@ -79,7 +79,7 @@ QtObject {
property var communitiesModuleInst: Global.appIsReady? communitiesModule : null
property var communitiesList: SortFilterProxyModel {
readonly property var communitiesList: SortFilterProxyModel {
sourceModel: root.mainModuleInst.sectionsModel
filters: ValueFilter {
roleName: "sectionType"

View File

@ -963,7 +963,7 @@ QtObject {
id: importControlNodePopup
ImportControlNodePopup {
onClosed: destroy()
onImportControlNode: root.rootStore.promoteSelfToControlNode(community.id)
onImportControlNode: root.rootStore.promoteSelfToControlNode(communityId)
}
},

View File

@ -63,6 +63,8 @@ Item {
asset.height: 32
name: model.name ?? ""
memberCountVisible: model.joined || !model.encrypted
members: model.membersCount
activeUsers: model.activeMembersCount
banner: model.bannerImageData ?? ""
descriptionFontSize: 12
descriptionFontColor: Theme.palette.baseColor1
@ -108,7 +110,7 @@ Item {
StatusBaseText {
font.pixelSize: Theme.tertiaryTextFontSize
color: Theme.palette.successColor1
text: qsTr("Youre there too")
text: qsTr("You're there too")
}
}
}

View File

@ -1322,16 +1322,17 @@ QtObject {
enum CommunityMembershipRequestState {
None = 0,
Pending,
Accepted,
Rejected,
Accepted,
Canceled,
AcceptedPending,
RejectedPending,
AwaitingAddress,
Banned,
Kicked,
BannedPending,
UnbannedPending,
KickedPending,
AwaitingAddress,
Unbanned,
BannedWithAllMessagesDelete
}