feat(curated-comms): add permission model to curated communities

Fixes #10410

Adds the permission model to the curated communities model.

Also fixes the assetsModel and collectiblesModel used by the community portal, because it was using the basic Chat Store created in AppMain, but that store doesn't have the assets model.
This commit is contained in:
Jonathan Rainville 2023-06-16 14:38:32 -04:00
parent fe8a58c5db
commit 347bc9c9d7
13 changed files with 223 additions and 74 deletions

View File

@ -86,8 +86,6 @@ proc addOrUpdateChat(self: Module,
insertIntoModel: bool = true,
): Item
proc buildTokenPermissionItem*(self: Module, tokenPermission: CommunityTokenPermissionDto): TokenPermissionItem
proc buildTokenList*(self: Module)
proc newModule*(
@ -283,7 +281,7 @@ proc rebuildCommunityTokenPermissionsModel(self: Module) =
var tokenPermissionsItems: seq[TokenPermissionItem] = @[]
for id, tokenPermission in community.tokenPermissions:
let tokenPermissionItem = self.buildTokenPermissionItem(tokenPermission)
let tokenPermissionItem = buildTokenPermissionItem(tokenPermission)
tokenPermissionsItems.add(tokenPermissionItem)
let memberPermissions = filter(tokenPermissionsItems, tokenPermissionsItem =>
@ -787,7 +785,7 @@ method onCommunityTokenPermissionDeleted*(self: Module, communityId: string, per
singletonInstance.globalEvents.showCommunityTokenPermissionDeletedNotification(communityId, "Community permission deleted", "A token permission has been removed")
method onCommunityTokenPermissionCreated*(self: Module, communityId: string, tokenPermission: CommunityTokenPermissionDto) =
let tokenPermissionItem = self.buildTokenPermissionItem(tokenPermission)
let tokenPermissionItem = buildTokenPermissionItem(tokenPermission)
if tokenPermissionItem.tokenCriteriaMet:
self.view.setAllTokenRequirementsMet(true)
self.view.tokenPermissionsModel.addItem(tokenPermissionItem)
@ -855,7 +853,7 @@ method onCommunityCheckPermissionsToJoinResponse*(self: Module, checkPermissions
method onCommunityTokenPermissionUpdated*(self: Module, communityId: string, tokenPermission: CommunityTokenPermissionDto) =
let tokenPermissionItem = self.buildTokenPermissionItem(tokenPermission)
let tokenPermissionItem = buildTokenPermissionItem(tokenPermission)
self.view.tokenPermissionsModel.updateItem(tokenPermission.id, tokenPermissionItem)
singletonInstance.globalEvents.showCommunityTokenPermissionUpdatedNotification(communityId, "Community permission updated", "A token permission has been updated")
@ -1317,33 +1315,6 @@ method requestToJoinCommunity*(self: Module, communityId: string, ensName: strin
method requestToJoinCommunityWithAuthentication*(self: Module, communityId: string, ensName: string) =
self.controller.authenticateToRequestToJoinCommunity(communityId, ensName)
proc buildTokenPermissionItem*(self: Module, tokenPermission: CommunityTokenPermissionDto): TokenPermissionItem =
var tokenCriteriaItems: seq[TokenCriteriaItem] = @[]
for tc in tokenPermission.tokenCriteria:
let tokenCriteriaItem = initTokenCriteriaItem(
tc.symbol,
tc.name,
tc.amount.parseFloat,
tc.`type`.int,
tc.ensPattern,
false # tokenCriteriaMet will be updated by a call to checkPermissionsToJoin
)
tokenCriteriaItems.add(tokenCriteriaItem)
let tokenPermissionItem = initTokenPermissionItem(
tokenPermission.id,
tokenPermission.`type`.int,
tokenCriteriaItems,
@[], # TODO: handle chat list items
tokenPermission.isPrivate,
false # allTokenCriteriaMet will be update by a call to checkPermissinosToJoin
)
return tokenPermissionItem
method onDeactivateChatLoader*(self: Module, chatId: string) =
self.view.chatsModel().disableChatLoader(chatId)

View File

@ -7,6 +7,9 @@ import ../../../../app_service/service/community/service as community_service
import ../../../../app_service/service/contacts/service as contacts_service
import ../../../../app_service/service/network/service as networks_service
import ../../../../app_service/service/community_tokens/service as community_tokens_service
import ../../../../app_service/service/token/service as token_service
import ../../shared_models/token_permissions_model
type
Controller* = ref object of RootObj
@ -16,6 +19,7 @@ type
contactsService: contacts_service.Service
communityTokensService: community_tokens_service.Service
networksService: networks_service.Service
tokenService: token_service.Service
proc newController*(
delegate: io_interface.AccessInterface,
@ -24,6 +28,7 @@ proc newController*(
contactsService: contacts_service.Service,
communityTokensService: community_tokens_service.Service,
networksService: networks_service.Service,
tokenService: token_service.Service,
): Controller =
result = Controller()
result.delegate = delegate
@ -32,6 +37,7 @@ proc newController*(
result.contactsService = contactsService
result.communityTokensService = communityTokensService
result.networksService = networksService
result.tokenService = tokenService
proc delete*(self: Controller) =
discard
@ -252,3 +258,6 @@ proc getCommunityTokens*(self: Controller, communityId: string): seq[CommunityTo
proc getNetwork*(self:Controller, chainId: int): NetworkDto =
self.networksService.getNetwork(chainId)
proc getTokenList*(self: Controller): seq[TokenDto] =
return self.tokenService.getTokenList()

View File

@ -1,4 +1,5 @@
import strformat
import ../../../shared_models/[token_permissions_model, token_permission_item]
type
CuratedCommunityItem* = object
@ -13,6 +14,7 @@ type
members: int
activeMembers: int
featured: bool
permissionModel: TokenPermissionsModel
proc initCuratedCommunityItem*(
id: string,
@ -25,7 +27,8 @@ proc initCuratedCommunityItem*(
tags: string,
members: int,
activeMembers: int,
featured: bool
featured: bool,
tokenPermissionsItems: seq[TokenPermissionItem]
): CuratedCommunityItem =
result.id = id
result.name = name
@ -38,6 +41,9 @@ proc initCuratedCommunityItem*(
result.members = members
result.activeMembers = activeMembers
result.featured = featured
result.permissionModel = newTokenPermissionsModel()
if tokenPermissionsItems.len > 0:
result.permissionModel.setItems(tokenPermissionsItems)
proc `$`*(self: CuratedCommunityItem): string =
result = fmt"""CuratedCommunityItem(
@ -84,3 +90,9 @@ proc getTags*(self: CuratedCommunityItem): string =
proc getFeatured*(self: CuratedCommunityItem): bool =
return self.featured
proc getPermissionsModel*(self: CuratedCommunityItem): TokenPermissionsModel =
return self.permissionModel
proc setPermissionModelItems*(self: CuratedCommunityItem, items: seq[TokenPermissionItem]) =
self.permissionModel.setItems(items)

View File

@ -1,5 +1,6 @@
import NimQml, Tables
import curated_community_item
import ../../../shared_models/[token_permissions_model, token_permission_item]
type
ModelRole {.pure.} = enum
@ -15,6 +16,7 @@ type
Popularity
Color
Tags
Permissions
QtObject:
type CuratedCommunityModel* = ref object of QAbstractListModel
@ -62,6 +64,7 @@ QtObject:
ModelRole.Color.int:"color",
ModelRole.Popularity.int:"popularity",
ModelRole.Tags.int:"tags",
ModelRole.Permissions.int:"permissionsModel",
}.toTable
method data(self: CuratedCommunityModel, index: QModelIndex, role: int): QVariant =
@ -95,6 +98,8 @@ QtObject:
result = newQVariant(index.row)
of ModelRole.Tags:
result = newQVariant(item.getTags())
of ModelRole.Permissions:
result = newQVariant(item.getPermissionsModel())
of ModelRole.Featured:
result = newQVariant(item.getFeatured())
@ -132,17 +137,20 @@ QtObject:
if idx > -1:
let index = self.createIndex(idx, 0, nil)
self.items[idx] = item
self.dataChanged(index, index, @[ModelRole.Name.int,
ModelRole.Available.int,
ModelRole.Description.int,
ModelRole.Icon.int,
ModelRole.Banner.int,
ModelRole.Featured.int,
ModelRole.Members.int,
ModelRole.ActiveMembers.int,
ModelRole.Color.int,
ModelRole.Popularity.int,
ModelRole.Tags.int])
self.dataChanged(index, index, @[
ModelRole.Name.int,
ModelRole.Available.int,
ModelRole.Description.int,
ModelRole.Icon.int,
ModelRole.Banner.int,
ModelRole.Featured.int,
ModelRole.Members.int,
ModelRole.ActiveMembers.int,
ModelRole.Color.int,
ModelRole.Popularity.int,
ModelRole.Tags.int,
ModelRole.Permissions.int,
])
else:
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
@ -150,3 +158,10 @@ QtObject:
self.items.add(item)
self.endInsertRows()
self.countChanged()
proc setPermissionItems*(self: CuratedCommunityModel, itemId: string, items: seq[TokenPermissionItem]) =
let idx = self.findIndexById(itemId)
if idx == -1:
echo "Tried to set permission items on an item that doesn't exist. Item ID: ", itemId
return
self.items[idx].setPermissionModelItems(items)

View File

@ -12,8 +12,8 @@ import ./models/discord_channels_model
import ./models/discord_file_list_model
import ./models/discord_import_task_item
import ./models/discord_import_tasks_model
import ../../shared_models/section_item
import ../../shared_models/[member_item, section_model]
import ../../shared_models/[member_item, section_model, section_item, token_permissions_model, token_permission_item,
token_list_item, token_criteria_item]
import ../../../global/global_singleton
import ../../../core/eventemitter
import ../../../../app_service/common/types
@ -22,6 +22,7 @@ import ../../../../app_service/service/contacts/service as contacts_service
import ../../../../app_service/service/network/service as networks_service
import ../../../../app_service/service/transaction/service as transaction_service
import ../../../../app_service/service/community_tokens/service as community_tokens_service
import ../../../../app_service/service/token/service as token_service
import ../../../../app_service/service/chat/dto/chat
import ./tokens/module as community_tokens_module
@ -47,6 +48,7 @@ type
method setCommunityTags*(self: Module, communityTags: string)
method setAllCommunities*(self: Module, communities: seq[CommunityDto])
method setCuratedCommunities*(self: Module, curatedCommunities: seq[CommunityDto])
proc buildTokenList(self: Module)
proc newModule*(
delegate: delegate_interface.AccessInterface,
@ -55,7 +57,9 @@ proc newModule*(
contactsService: contacts_service.Service,
communityTokensService: community_tokens_service.Service,
networksService: networks_service.Service,
transactionService: transaction_service.Service): Module =
transactionService: transaction_service.Service,
tokensService: token_service.Service,
): Module =
result = Module()
result.delegate = delegate
result.view = newView(result)
@ -67,6 +71,7 @@ proc newModule*(
contactsService,
communityTokensService,
networksService,
tokensService,
)
result.communityTokensModule = community_tokens_module.newCommunityTokensModule(result, events, communityTokensService, transactionService, networksService)
result.moduleLoaded = false
@ -95,6 +100,7 @@ method viewDidLoad*(self: Module) =
method communityDataLoaded*(self: Module) =
self.setCommunityTags(self.controller.getCommunityTags())
self.setAllCommunities(self.controller.getAllCommunities())
self.buildTokenList()
method onActivated*(self: Module) =
self.controller.asyncLoadCuratedCommunities()
@ -169,19 +175,27 @@ method getCommunityItem(self: Module, c: CommunityDto): SectionItem =
communityTokens = @[]
)
proc getCuratedCommunityItem(self: Module, c: CommunityDto): CuratedCommunityItem =
proc getCuratedCommunityItem(self: Module, community: CommunityDto): CuratedCommunityItem =
var tokenPermissionsItems: seq[TokenPermissionItem] = @[]
for id, tokenPermission in community.tokenPermissions:
let tokenPermissionItem = buildTokenPermissionItem(tokenPermission)
tokenPermissionsItems.add(tokenPermissionItem)
return initCuratedCommunityItem(
c.id,
c.name,
c.description,
c.isAvailable,
c.images.thumbnail,
c.images.banner,
c.color,
c.tags,
len(c.members),
int(c.activeMembersCount),
c.featuredInDirectory)
community.id,
community.name,
community.description,
community.isAvailable,
community.images.thumbnail,
community.images.banner,
community.color,
community.tags,
len(community.members),
int(community.activeMembersCount),
community.featuredInDirectory,
tokenPermissionsItems,
)
proc getDiscordCategoryItem(self: Module, c: DiscordCategoryDto): DiscordCategoryItem =
return initDiscordCategoryItem(
@ -384,3 +398,37 @@ method requestCancelDiscordCommunityImport*(self: Module, id: string) =
method communityInfoAlreadyRequested*(self: Module) =
self.view.communityInfoAlreadyRequested()
proc buildTokenList(self: Module) =
var tokenListItems: seq[TokenListItem]
var collectiblesListItems: seq[TokenListItem]
let communities = self.controller.getAllCommunities()
let erc20Tokens = self.controller.getTokenList()
for token in erc20Tokens:
let tokenListItem = initTokenListItem(
key = token.symbol,
name = token.name,
symbol = token.symbol,
color = token.color,
image = "",
category = ord(TokenListItemCategory.General)
)
tokenListItems.add(tokenListItem)
for community in communities:
for token in community.communityTokensMetadata:
let tokenListItem = initTokenListItem(
key = token.symbol,
name = token.name,
symbol = token.symbol,
color = "", # community tokens don't have `color`
image = token.image,
category = ord(TokenListItemCategory.Community)
)
collectiblesListItems.add(tokenListItem)
self.view.setTokenListItems(tokenListItems)
self.view.setCollectiblesListItems(collectiblesListItems)

View File

@ -1,9 +1,7 @@
import NimQml, json, strutils, sequtils
import ./io_interface
import ../../shared_models/section_model
import ../../shared_models/section_item
import ../../shared_models/section_details
import ../../shared_models/[section_model, section_item, section_details, token_list_model, token_list_item]
import ./models/curated_community_model
import ./models/discord_file_list_model
import ./models/discord_file_item
@ -22,6 +20,10 @@ QtObject:
curatedCommunitiesModel: CuratedCommunityModel
curatedCommunitiesModelVariant: QVariant
curatedCommunitiesLoading: bool
tokenListModel: TokenListModel
tokenListModelVariant: QVariant
collectiblesListModel: TokenListModel
collectiblesListModelVariant: QVariant
discordFileListModel: DiscordFileListModel
discordFileListModelVariant: QVariant
discordCategoriesModel: DiscordCategoriesModel
@ -59,6 +61,11 @@ QtObject:
self.discordChannelsModelVariant.delete
self.discordImportTasksModel.delete
self.discordImportTasksModelVariant.delete
self.tokenListModel.delete
self.tokenListModelVariant.delete
self.collectiblesListModel.delete
self.collectiblesListModelVariant.delete
self.QObject.delete
proc newView*(delegate: io_interface.AccessInterface): View =
@ -89,6 +96,10 @@ QtObject:
result.discordImportTasksModel = newDiscordDiscordImportTasksModel()
result.discordImportTasksModelVariant = newQVariant(result.discordImportTasksModel)
result.downloadingCommunityHistoryArchives = false
result.tokenListModel = newTokenListModel()
result.tokenListModelVariant = newQVariant(result.tokenListModel)
result.collectiblesListModel = newTokenListModel()
result.collectiblesListModelVariant = newQVariant(result.collectiblesListModel)
proc load*(self: View) =
self.delegate.viewDidLoad()
@ -566,3 +577,26 @@ QtObject:
if self.discordChannelsModel.allChannelsByCategoryUnselected(item.getCategoryId()):
self.discordCategoriesModel.unselectItem(item.getCategoryId())
proc tokenListModel*(self: View): TokenListModel =
result = self.tokenListModel
proc getTokenListModel(self: View): QVariant{.slot.} =
return self.tokenListModelVariant
QtProperty[QVariant] tokenList:
read = getTokenListModel
proc setTokenListItems*(self: View, tokenListItems: seq[TokenListItem]) =
self.tokenListModel.setItems(tokenListItems)
proc collectiblesListModel*(self: View): TokenListModel =
result = self.collectiblesListModel
proc getCollectiblesListModel(self: View): QVariant{.slot.} =
return self.collectiblesListModelVariant
QtProperty[QVariant] collectiblesModel:
read = getCollectiblesListModel
proc setCollectiblesListItems*(self: View, tokenListItems: seq[TokenListItem]) =
self.collectiblesListModel.setItems(tokenListItems)

View File

@ -207,7 +207,7 @@ proc newModule*[T](
result.stickersModule = stickers_module.newModule(result, events, stickersService, settingsService, walletAccountService, networkService, tokenService)
result.activityCenterModule = activity_center_module.newModule(result, events, activityCenterService, contactsService,
messageService, chatService, communityService)
result.communitiesModule = communities_module.newModule(result, events, communityService, contactsService, communityTokensService, networkService, transactionService)
result.communitiesModule = communities_module.newModule(result, events, communityService, contactsService, communityTokensService, networkService, transactionService, tokenService)
result.appSearchModule = app_search_module.newModule(result, events, contactsService, chatService, communityService,
messageService)
result.nodeSectionModule = node_section_module.newModule(result, events, settingsService, nodeService, nodeConfigurationService)

View File

@ -1,4 +1,4 @@
import strformat
import strformat, strutils
import ../../../app_service/service/community/dto/community
import ../../../app_service/service/chat/dto/chat
import token_criteria_model
@ -62,3 +62,31 @@ proc getIsPrivate*(self: TokenPermissionItem): bool =
proc getTokenCriteriaMet*(self: TokenPermissionItem): bool =
return self.tokenCriteriaMet
proc buildTokenPermissionItem*(tokenPermission: CommunityTokenPermissionDto): TokenPermissionItem =
var tokenCriteriaItems: seq[TokenCriteriaItem] = @[]
for tc in tokenPermission.tokenCriteria:
let tokenCriteriaItem = initTokenCriteriaItem(
tc.symbol,
tc.name,
tc.amount.parseFloat,
tc.`type`.int,
tc.ensPattern,
false # tokenCriteriaMet will be updated by a call to checkPermissionsToJoin
)
tokenCriteriaItems.add(tokenCriteriaItem)
let tokenPermissionItem = initTokenPermissionItem(
tokenPermission.id,
tokenPermission.`type`.int,
tokenCriteriaItems,
@[], # TODO: handle chat list items
tokenPermission.isPrivate,
false # allTokenCriteriaMet will be update by a call to checkPermissinosToJoin
)
return tokenPermissionItem

View File

@ -32,13 +32,13 @@ QtObject:
ModelRole.Key.int:"key",
ModelRole.Type.int:"permissionType",
ModelRole.TokenCriteria.int:"holdingsListModel",
ModelRole.ChatList.int:"channelsModel",
ModelRole.ChatList.int:"channelsListModel",
ModelRole.IsPrivate.int:"isPrivate",
}.toTable
proc countChanged(self: TokenPermissionsModel) {.signal.}
proc getCount*(self: TokenPermissionsModel): int {.slot.} =
self.items.len
return self.items.len
QtProperty[int] count:
read = getCount
notify = countChanged
@ -126,6 +126,5 @@ QtObject:
ModelRole.Key.int,
ModelRole.Type.int,
ModelRole.TokenCriteria.int,
ModelRole.IsPrivate.int
ModelRole.IsPrivate.int,
])

View File

@ -228,6 +228,12 @@ Control {
}
onModelChanged: d.buildShortModel(root.model)
Connections {
target: root.model
function onCountChanged() {
d.buildShortModel(root.model)
}
}
Component.onCompleted: d.buildShortModel(root.model)
ListModel { id: shortModel }
@ -268,6 +274,12 @@ Control {
spacing: -root.overlapping
onModelChanged: buildTokensRowModel(singlePermissionItem.model)
Connections {
target: singlePermissionItem.model
function onCountChanged() {
buildTokensRowModel(singlePermissionItem.model)
}
}
Component.onCompleted: buildTokensRowModel(singlePermissionItem.model)
ListModel{ id: shortTokensRowModel }

View File

@ -25,8 +25,8 @@ StatusSectionLayout {
property var communitiesStore
property alias assetsModel: communitiesGrid.assetsModel
property alias collectiblesModel: communitiesGrid.collectiblesModel
property var assetsModel
property var collectiblesModel
objectName: "communitiesPortalLayout"
onNotificationButtonClicked: Global.openActivityCenterPopup()

View File

@ -84,9 +84,10 @@ StatusScrollView {
popularity: model.popularity
categories: tagsJson.model
// Community restriccions
// Community restrictions
rigthHeaderComponent: CommunityPermissionsRow {
visible: !!card.permissionsList
visible: !!card.permissionsList && card.permissionsList.count > 0
assetsModel: root.assetsModel
collectiblesModel: root.collectiblesModel
model: card.permissionsList

View File

@ -967,8 +967,28 @@ Item {
CommunitiesPortalLayout {
anchors.fill: parent
communitiesStore: appMain.communitiesStore
assetsModel: appMain.rootChatStore.assetsModel
collectiblesModel: appMain.rootChatStore.collectiblesModel
assetsModel: SortFilterProxyModel {
sourceModel: appMain.communitiesStore.communitiesModuleInst.tokenList
proxyRoles: ExpressionRole {
function tokenIcon(symbol) {
return Constants.tokenIcon(symbol)
}
name: "iconSource"
expression: !!model.icon ? model.icon : tokenIcon(model.symbol)
}
}
collectiblesModel: SortFilterProxyModel {
sourceModel: appMain.communitiesStore.communitiesModuleInst.collectiblesModel
proxyRoles: ExpressionRole {
function icon(icon) {
return !!icon ? icon : Style.png("tokens/DEFAULT-TOKEN")
}
name: "iconSource"
expression: icon(model.icon)
}
}
notificationCount: appMain.activityCenterStore.unreadNotificationsCount
hasUnseenNotifications: activityCenterStore.hasUnseenNotifications
}