From e30ba7e760cf7a60fac5e749bff7eb486e022a19 Mon Sep 17 00:00:00 2001 From: MishkaRogachev Date: Thu, 9 Jun 2022 17:59:54 +0300 Subject: [PATCH] feat(@community): Add tags to communities Close #5680 --- .../modules/main/chat_section/controller.nim | 2 + .../main/chat_section/io_interface.nim | 4 +- src/app/modules/main/chat_section/module.nim | 5 +- src/app/modules/main/chat_section/view.nim | 7 +- .../modules/main/communities/controller.nim | 5 + .../modules/main/communities/io_interface.nim | 7 +- src/app/modules/main/communities/module.nim | 10 +- src/app/modules/main/communities/view.nim | 16 +- .../service/community/dto/community.nim | 3 + src/app_service/service/community/service.nim | 21 ++- src/backend/communities.nim | 7 + ui/StatusQ | 2 +- .../community/CommunityTagsPicker.qml | 70 ++++++++ .../CommunityEditSettingsPanel.qml | 7 + .../CommunityOverviewSettingsPanel.qml | 5 + .../popups/community/CommunityTagsPopup.qml | 159 ++++++++++++++++++ .../popups/community/CreateCommunityPopup.qml | 7 + ui/app/AppLayouts/Chat/stores/RootStore.qml | 6 +- .../Chat/views/CommunitySettingsView.qml | 3 + ui/app/AppLayouts/stores/RootStore.qml | 7 +- vendor/status-go | 2 +- 21 files changed, 338 insertions(+), 17 deletions(-) create mode 100644 ui/app/AppLayouts/Chat/controls/community/CommunityTagsPicker.qml create mode 100644 ui/app/AppLayouts/Chat/popups/community/CommunityTagsPopup.qml diff --git a/src/app/modules/main/chat_section/controller.nim b/src/app/modules/main/chat_section/controller.nim index 98c6ceaad6..ec533fd81d 100644 --- a/src/app/modules/main/chat_section/controller.nim +++ b/src/app/modules/main/chat_section/controller.nim @@ -385,6 +385,7 @@ proc editCommunity*( outroMessage: string, access: int, color: string, + tags: string, logoJsonStr: string, bannerJsonStr: string, historyArchiveSupportEnabled: bool, @@ -397,6 +398,7 @@ proc editCommunity*( outroMessage, access, color, + tags, logoJsonStr, bannerJsonStr, historyArchiveSupportEnabled, diff --git a/src/app/modules/main/chat_section/io_interface.nim b/src/app/modules/main/chat_section/io_interface.nim index 8f70ef1ac4..10328613e7 100644 --- a/src/app/modules/main/chat_section/io_interface.nim +++ b/src/app/modules/main/chat_section/io_interface.nim @@ -252,7 +252,9 @@ method removeUserFromCommunity*(self: AccessInterface, pubKey: string) {.base.} method banUserFromCommunity*(self: AccessInterface, pubKey: string) {.base.} = raise newException(ValueError, "No implementation available") -method editCommunity*(self: AccessInterface, name: string, description, introMessage, outroMessage: string, access: int, color: string, logoJsonData: string, bannerJsonData: string, historyArchiveSupportEnabled: bool, pinMessageAllMembersEnabled: bool) {.base.} = +method editCommunity*(self: AccessInterface, name: string, description, introMessage, outroMessage: string, + access: int, color: string, tags: string, logoJsonData: string, bannerJsonData: string, + historyArchiveSupportEnabled: bool, pinMessageAllMembersEnabled: bool) {.base.} = raise newException(ValueError, "No implementation available") method exportCommunity*(self: AccessInterface): string {.base.} = diff --git a/src/app/modules/main/chat_section/module.nim b/src/app/modules/main/chat_section/module.nim index f0ceebf65b..b05dad4809 100644 --- a/src/app/modules/main/chat_section/module.nim +++ b/src/app/modules/main/chat_section/module.nim @@ -741,12 +741,13 @@ method banUserFromCommunity*(self: Module, pubKey: string) = method editCommunity*(self: Module, name: string, description, introMessage, outroMessage: string, - access: int, color: string, + access: int, color: string, tags: string, logoJsonStr: string, bannerJsonStr: string, historyArchiveSupportEnabled: bool, pinMessageAllMembersEnabled: bool) = - self.controller.editCommunity(name, description, introMessage, outroMessage, access, color, logoJsonStr, bannerJsonStr, historyArchiveSupportEnabled, pinMessageAllMembersEnabled) + self.controller.editCommunity(name, description, introMessage, outroMessage, access, color, tags, logoJsonStr, + bannerJsonStr, historyArchiveSupportEnabled, pinMessageAllMembersEnabled) method exportCommunity*(self: Module): string = self.controller.exportCommunity() diff --git a/src/app/modules/main/chat_section/view.nim b/src/app/modules/main/chat_section/view.nim index 7d5b48282f..36b92f817f 100644 --- a/src/app/modules/main/chat_section/view.nim +++ b/src/app/modules/main/chat_section/view.nim @@ -247,8 +247,11 @@ QtObject: proc banUserFromCommunity*(self: View, pubKey: string) {.slot.} = self.delegate.banUserFromCommunity(pubKey) - proc editCommunity*(self: View, name: string, description: string, introMessage: string, outroMessage: string, access: int, color: string, logoJsonData: string, bannerJsonData: string, historyArchiveSupportEnabled: bool, pinMessageAllMembersEnabled: bool) {.slot.} = - self.delegate.editCommunity(name, description, introMessage, outroMessage, access, color, logoJsonData, bannerJsonData, historyArchiveSupportEnabled, pinMessageAllMembersEnabled) + proc editCommunity*(self: View, name: string, description: string, introMessage: string, outroMessage: string, access: int, + color: string, tags: string, logoJsonData: string, bannerJsonData: string, historyArchiveSupportEnabled: bool, + pinMessageAllMembersEnabled: bool) {.slot.} = + self.delegate.editCommunity(name, description, introMessage, outroMessage, access, color, tags, + logoJsonData, bannerJsonData, historyArchiveSupportEnabled, pinMessageAllMembersEnabled) proc exportCommunity*(self: View): string {.slot.} = self.delegate.exportCommunity() diff --git a/src/app/modules/main/communities/controller.nim b/src/app/modules/main/communities/controller.nim index 16f7e7a665..a9151cec39 100644 --- a/src/app/modules/main/communities/controller.nim +++ b/src/app/modules/main/communities/controller.nim @@ -62,6 +62,9 @@ proc init*(self: Controller) = let args = CommunityMutedArgs(e) self.delegate.communityMuted(args.communityId, args.muted) +proc getCommunityTags*(self: Controller): string = + result = self.communityService.getCommunityTags() + proc getAllCommunities*(self: Controller): seq[CommunityDto] = result = self.communityService.getAllCommunities() @@ -82,6 +85,7 @@ proc createCommunity*( outroMessage: string, access: int, color: string, + tags: string, imageUrl: string, aX: int, aY: int, bX: int, bY: int, historyArchiveSupportEnabled: bool, @@ -93,6 +97,7 @@ proc createCommunity*( outroMessage, access, color, + tags, imageUrl, aX, aY, bX, bY, historyArchiveSupportEnabled, diff --git a/src/app/modules/main/communities/io_interface.nim b/src/app/modules/main/communities/io_interface.nim index f152d7288e..c8b2c39065 100644 --- a/src/app/modules/main/communities/io_interface.nim +++ b/src/app/modules/main/communities/io_interface.nim @@ -13,6 +13,9 @@ method load*(self: AccessInterface) {.base.} = method isLoaded*(self: AccessInterface): bool {.base.} = raise newException(ValueError, "No implementation available") +method setCommunityTags*(self: AccessInterface, communityTags: string) {.base.} = + raise newException(ValueError, "No implementation available") + method setAllCommunities*(self: AccessInterface, communities: seq[CommunityDto]) {.base.} = raise newException(ValueError, "No implementation available") @@ -25,7 +28,9 @@ method getCommunityItem*(self: AccessInterface, community: CommunityDto): Sectio method joinCommunity*(self: AccessInterface, communityId: string): string {.base.} = raise newException(ValueError, "No implementation available") -method createCommunity*(self: AccessInterface, name: string, description, introMessage, outroMessage: string, access: int, color: string, imagePath: string, aX: int, aY: int, bX: int, bY: int, historyArchiveSupportEnabled: bool, pinMessageAllMembersEnabled: bool) {.base.} = +method createCommunity*(self: AccessInterface, name: string, description, introMessage, outroMessage: string, access: int, + color: string, tags: string, imagePath: string, aX: int, aY: int, bX: int, bY: int, + historyArchiveSupportEnabled: bool, pinMessageAllMembersEnabled: bool) {.base.} = raise newException(ValueError, "No implementation available") method deleteCommunityCategory*(self: AccessInterface, communityId: string, categoryId: string) {.base.} = diff --git a/src/app/modules/main/communities/module.nim b/src/app/modules/main/communities/module.nim index b4d857ea6c..f8cd3444c8 100644 --- a/src/app/modules/main/communities/module.nim +++ b/src/app/modules/main/communities/module.nim @@ -30,6 +30,7 @@ type moduleLoaded: bool # Forward declaration +method setCommunityTags*(self: Module, communityTags: string) method setAllCommunities*(self: Module, communities: seq[CommunityDto]) method setCuratedCommunities*(self: Module, curatedCommunities: seq[CuratedCommunity]) @@ -66,6 +67,7 @@ method isLoaded*(self: Module): bool = method viewDidLoad*(self: Module) = self.moduleLoaded = true + self.setCommunityTags(self.controller.getCommunityTags()) self.setAllCommunities(self.controller.getAllCommunities()) self.setCuratedCommunities(self.controller.getCuratedCommunities()) @@ -121,6 +123,9 @@ method getCuratedCommunityItem(self: Module, c: CuratedCommunity): CuratedCommun c.community.color, len(c.community.members)) +method setCommunityTags*(self: Module, communityTags: string) = + self.view.setCommunityTags(communityTags) + method setAllCommunities*(self: Module, communities: seq[CommunityDto]) = for community in communities: self.view.addItem(self.getCommunityItem(community)) @@ -175,12 +180,13 @@ method communityCategoryDeleted*(self: Module) = method createCommunity*(self: Module, name: string, description, introMessage: string, outroMessage: string, - access: int, color: string, + access: int, color: string, tags: string, imagePath: string, aX: int, aY: int, bX: int, bY: int, historyArchiveSupportEnabled: bool, pinMessageAllMembersEnabled: bool) = - self.controller.createCommunity(name, description, introMessage, outroMessage, access, color, imagePath, aX, aY, bX, bY, historyArchiveSupportEnabled, pinMessageAllMembersEnabled) + self.controller.createCommunity(name, description, introMessage, outroMessage, access, color, tags, + imagePath, aX, aY, bX, bY, historyArchiveSupportEnabled, pinMessageAllMembersEnabled) method deleteCommunityCategory*(self: Module, communityId: string, categoryId: string) = self.controller.deleteCommunityCategory(communityId, categoryId) diff --git a/src/app/modules/main/communities/view.nim b/src/app/modules/main/communities/view.nim index f4e92fafba..068b6be857 100644 --- a/src/app/modules/main/communities/view.nim +++ b/src/app/modules/main/communities/view.nim @@ -10,6 +10,7 @@ import ./models/curated_community_model QtObject: type View* = ref object of QObject + communityTags: QVariant delegate: io_interface.AccessInterface model: SectionModel modelVariant: QVariant @@ -28,6 +29,7 @@ QtObject: proc newView*(delegate: io_interface.AccessInterface): View = new(result, delete) result.QObject.setup + result.communityTags = newQVariant("") result.delegate = delegate result.model = newModel() result.modelVariant = newQVariant(result.model) @@ -41,6 +43,9 @@ QtObject: proc communityAdded*(self: View, communityId: string) {.signal.} proc communityChanged*(self: View, communityId: string) {.signal.} + proc setCommunityTags*(self: View, communityTags: string) = + self.communityTags = newQVariant(communityTags) + proc addItem*(self: View, item: SectionItem) = self.model.addItem(item) self.communityAdded(item.id) @@ -48,6 +53,12 @@ QtObject: proc model*(self: View): SectionModel = result = self.model + proc getTags(self: View): QVariant {.slot.} = + return self.communityTags + + QtProperty[QVariant] tags: + read = getTags + proc getModel(self: View): QVariant {.slot.} = return self.modelVariant @@ -84,12 +95,13 @@ QtObject: proc createCommunity*(self: View, name: string, description: string, introMessage: string, outroMessage: string, - access: int, color: string, + access: int, color: string, tags: string, imagePath: string, aX: int, aY: int, bX: int, bY: int, historyArchiveSupportEnabled: bool, pinMessageAllMembersEnabled: bool) {.slot.} = - self.delegate.createCommunity(name, description, introMessage, outroMessage, access, color, imagePath, aX, aY, bX, bY, historyArchiveSupportEnabled, pinMessageAllMembersEnabled) + self.delegate.createCommunity(name, description, introMessage, outroMessage, access, color, tags, + imagePath, aX, aY, bX, bY, historyArchiveSupportEnabled, pinMessageAllMembersEnabled) proc deleteCommunityCategory*(self: View, communityId: string, categoryId: string): string {.slot.} = self.delegate.deleteCommunityCategory(communityId, categoryId) diff --git a/src/app_service/service/community/dto/community.nim b/src/app_service/service/community/dto/community.nim index 08e0b280a9..bf48bda2bd 100644 --- a/src/app_service/service/community/dto/community.nim +++ b/src/app_service/service/community/dto/community.nim @@ -61,6 +61,7 @@ type CommunityDto* = object canManageUsers*: bool canJoin*: bool color*: string + tags*: string requestedToJoinAt*: int64 isMember*: bool muted*: bool @@ -120,6 +121,7 @@ proc toCommunityDto*(jsonObj: JsonNode): CommunityDto = discard jsonObj.getProp("canManageUsers", result.canManageUsers) discard jsonObj.getProp("canJoin", result.canJoin) discard jsonObj.getProp("color", result.color) + discard jsonObj.getProp("tags", result.tags) discard jsonObj.getProp("requestedToJoinAt", result.requestedToJoinAt) discard jsonObj.getProp("isMember", result.isMember) discard jsonObj.getProp("muted", result.muted) @@ -179,6 +181,7 @@ proc toChannelGroupDto*(communityDto: CommunityDto): ChannelGroupDto = introMessage: communityDto.introMessage, outroMessage: communityDto.outroMessage, color: communityDto.color, + # tags: communityDto.tags, NOTE: do we need tags here? permissions: communityDto.permissions, members: communityDto.members.map(m => ChatMember( id: m.id, diff --git a/src/app_service/service/community/service.nim b/src/app_service/service/community/service.nim index af5dd6855a..a18fa98997 100644 --- a/src/app_service/service/community/service.nim +++ b/src/app_service/service/community/service.nim @@ -25,7 +25,7 @@ type community*: CommunityDto error*: string fromUserAction*: bool - + CuratedCommunityArgs* = ref object of Args curatedCommunity*: CuratedCommunity @@ -100,12 +100,14 @@ QtObject: threadpool: ThreadPool events: EventEmitter chatService: chat_service.Service + communityTags: string # JSON string contraining tags map joinedCommunities: Table[string, CommunityDto] # [community_id, CommunityDto] curatedCommunities: Table[string, CuratedCommunity] # [community_id, CuratedCommunity] allCommunities: Table[string, CommunityDto] # [community_id, CommunityDto] myCommunityRequests*: seq[CommunityMembershipRequestDto] # Forward declaration + proc loadCommunityTags(self: Service): string proc loadAllCommunities(self: Service): seq[CommunityDto] proc loadJoinedComunities(self: Service): seq[CommunityDto] proc loadCuratedCommunities(self: Service): seq[CuratedCommunity] @@ -127,6 +129,7 @@ QtObject: result.events = events result.threadpool = threadpool result.chatService = chatService + result.communityTags = newString(0) result.joinedCommunities = initTable[string, CommunityDto]() result.curatedCommunities = initTable[string, CuratedCommunity]() result.allCommunities = initTable[string, CommunityDto]() @@ -327,6 +330,7 @@ QtObject: proc init*(self: Service) = self.doConnect() + self.communityTags = self.loadCommunityTags(); let joinedCommunities = self.loadJoinedComunities() for community in joinedCommunities: self.joinedCommunities[community.id] = community @@ -350,6 +354,12 @@ QtObject: self.loadMyPendingRequestsToJoin() + proc loadCommunityTags(self: Service): string = + let response = status_go.getCommunityTags() + var result = newString(0) + toUgly(result, response.result) + return result + proc loadAllCommunities(self: Service): seq[CommunityDto] = try: let response = status_go.getAllCommunities() @@ -386,6 +396,9 @@ QtObject: error "error loading communities settings: ", errDesription return + proc getCommunityTags*(self: Service): string = + return self.communityTags + proc getJoinedCommunities*(self: Service): seq[CommunityDto] = return toSeq(self.joinedCommunities.values) @@ -498,7 +511,7 @@ QtObject: if not response.result.hasKey("communitiesSettings") or response.result["communitiesSettings"].kind != JArray or response.result["communitiesSettings"].len == 0: error "error: ", procName="joinCommunity", errDesription = "no 'communitiesSettings' key in response" return - + var updatedCommunity = response.result["communities"][0].toCommunityDto() let communitySettings = response.result["communitiesSettings"][0].toCommunitySettingsDto() @@ -591,6 +604,7 @@ QtObject: outroMessage: string, access: int, color: string, + tags: string, imageUrl: string, aX: int, aY: int, bX: int, bY: int, historyArchiveSupportEnabled: bool, @@ -604,6 +618,7 @@ QtObject: outroMessage, access, color, + tags, image, aX, aY, bX, bY, historyArchiveSupportEnabled, @@ -635,6 +650,7 @@ QtObject: outroMessage: string, access: int, color: string, + tags: string, logoJsonStr: string, bannerJsonStr: string, historyArchiveSupportEnabled: bool, @@ -651,6 +667,7 @@ QtObject: outroMessage, access, color, + tags, logoJson["imagePath"].getStr(), int(cropRectJson["x"].getFloat()), int(cropRectJson["y"].getFloat()), diff --git a/src/backend/communities.nim b/src/backend/communities.nim index 12fba32eeb..d1ce9046ed 100644 --- a/src/backend/communities.nim +++ b/src/backend/communities.nim @@ -6,6 +6,9 @@ import interpret/cropped_image export response_type +proc getCommunityTags*(): RpcResponse[JsonNode] {.raises: [Exception].} = + result = callPrivateRPC("communityTags".prefix) + proc getJoinedComunities*(): RpcResponse[JsonNode] {.raises: [Exception].} = let payload = %* [] result = callPrivateRPC("joinedCommunities".prefix, payload) @@ -42,6 +45,7 @@ proc createCommunity*( outroMessage: string, access: int, color: string, + tags: string, imageUrl: string, aX: int, aY: int, bX: int, bY: int, historyArchiveSupportEnabled: bool, @@ -56,6 +60,7 @@ proc createCommunity*( "outroMessage": outroMessage, "ensOnly": false, # TODO ensOnly is no longer supported. Remove this when we remove it in status-go "color": color, + "tags": parseJson(tags), "image": imageUrl, "imageAx": aX, "imageAy": aY, @@ -73,6 +78,7 @@ proc editCommunity*( outroMessage: string, access: int, color: string, + tags: string, imageUrl: string, aX: int, aY: int, @@ -92,6 +98,7 @@ proc editCommunity*( "outroMessage": outroMessage, "ensOnly": false, # TODO ensOnly is no longer supported. Remove this when we remove it in status-go "color": color, + "tags": parseJson(tags), "image": imageUrl, "imageAx": aX, "imageAy": aY, diff --git a/ui/StatusQ b/ui/StatusQ index 1730fe756d..604bb7a74c 160000 --- a/ui/StatusQ +++ b/ui/StatusQ @@ -1 +1 @@ -Subproject commit 1730fe756d71b9357dbb82a896116d575f2ff08b +Subproject commit 604bb7a74c83f365b1697005045eb7da2ddef3cb diff --git a/ui/app/AppLayouts/Chat/controls/community/CommunityTagsPicker.qml b/ui/app/AppLayouts/Chat/controls/community/CommunityTagsPicker.qml new file mode 100644 index 0000000000..5eb45f0e7b --- /dev/null +++ b/ui/app/AppLayouts/Chat/controls/community/CommunityTagsPicker.qml @@ -0,0 +1,70 @@ +import QtQuick 2.14 +import QtQuick.Layouts 1.14 + +import utils 1.0 + +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 +import StatusQ.Components 0.1 +import StatusQ.Popups 0.1 +import StatusQ.Controls 0.1 + +import "../../popups/community" + +ColumnLayout { + id: root + + property string tags + property string selectedTags + + onSelectedTagsChanged: { + var obj = JSON.parse(tags); + var array = JSON.parse(selectedTags); + + d.tagsModel.clear(); + for (const key of Object.keys(obj)) { + if (array.indexOf(key) != -1) { + d.tagsModel.append({ name: key, emoji: obj[key], selected: false }); + } + } + } + + spacing: 8 + + QtObject { + id: d + + property ListModel tagsModel: ListModel {} + } + + StatusBaseText { + text: qsTr("Tags") + font.pixelSize: 15 + color: Theme.palette.directColor1 + } + + StatusPickerButton { + bgColor: root.selectedTags == "" ? Theme.palette.baseColor2 : "transparent" + text: root.selectedTags == "" ? "Choose tags describing the community" : "" + Layout.fillWidth: true + + StatusCommunityTags { + anchors.centerIn: parent + model: d.tagsModel + active: false + width: parent.width + } + + onClicked: { + tagsDialog.tags = root.tags; + tagsDialog.selectedTags = root.selectedTags; + tagsDialog.open(); + } + + CommunityTagsPopup { + id: tagsDialog + anchors.centerIn: parent + onAccepted: root.selectedTags = selectedTags + } + } +} \ No newline at end of file diff --git a/ui/app/AppLayouts/Chat/panels/communities/CommunityEditSettingsPanel.qml b/ui/app/AppLayouts/Chat/panels/communities/CommunityEditSettingsPanel.qml index 7e3216d1d2..74ee826e96 100644 --- a/ui/app/AppLayouts/Chat/panels/communities/CommunityEditSettingsPanel.qml +++ b/ui/app/AppLayouts/Chat/panels/communities/CommunityEditSettingsPanel.qml @@ -26,6 +26,8 @@ Flickable { property alias introMessage: introMessageTextInput.text property alias outroMessage: outroMessageTextInput.text property alias color: colorPicker.color + property alias tags: tagsPicker.tags + property alias selectedTags: tagsPicker.selectedTags property alias options: options property alias logoImageData: logoPicker.imageData @@ -76,6 +78,11 @@ Flickable { Layout.fillWidth: true } + CommunityTagsPicker { + id: tagsPicker + Layout.fillWidth: true + } + StatusModalDivider { Layout.fillWidth: true Layout.bottomMargin: -layout.spacing diff --git a/ui/app/AppLayouts/Chat/panels/communities/CommunityOverviewSettingsPanel.qml b/ui/app/AppLayouts/Chat/panels/communities/CommunityOverviewSettingsPanel.qml index b02b7a3b4e..124d864457 100644 --- a/ui/app/AppLayouts/Chat/panels/communities/CommunityOverviewSettingsPanel.qml +++ b/ui/app/AppLayouts/Chat/panels/communities/CommunityOverviewSettingsPanel.qml @@ -23,6 +23,8 @@ StackLayout { property string bannerImageData property rect bannerCropRect property color color + property string tags + property string selectedTags property bool archiveSupportEnabled property bool requestToJoinEnabled property bool pinMessagesEnabled @@ -170,6 +172,8 @@ StackLayout { description: root.description introMessage: root.introMessage outroMessage: root.outroMessage + tags: root.tags + selectedTags: root.selectedTags color: root.color logoImageData: root.logoImageData bannerImageData: root.bannerImageData @@ -191,6 +195,7 @@ StackLayout { root.requestToJoinEnabled != options.requestToJoinEnabled || root.pinMessagesEnabled != options.pinMessagesEnabled || root.color != color || + root.selectedTags != selectedTags || logoImagePath.length > 0 || isValidRect(logoCropRect) || bannerPath.length > 0 || diff --git a/ui/app/AppLayouts/Chat/popups/community/CommunityTagsPopup.qml b/ui/app/AppLayouts/Chat/popups/community/CommunityTagsPopup.qml new file mode 100644 index 0000000000..0756667bc3 --- /dev/null +++ b/ui/app/AppLayouts/Chat/popups/community/CommunityTagsPopup.qml @@ -0,0 +1,159 @@ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 + +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 +import StatusQ.Components 0.1 +import StatusQ.Controls 0.1 +import StatusQ.Popups 0.1 + +import utils 1.0 + +StatusModal { + id: root + + property string tags + property string selectedTags + property int maxSelectedTags: 4 + + signal accepted(string selectedTags) + + function updateSelectedTags() { + var array = selectedTags.length ? JSON.parse(selectedTags) : []; + + d.cntSelectedTags = 0; + for (let i = 0; i < d.tagsModel.count; ++i) { + let item = d.tagsModel.get(i); + if (array.indexOf(item.name) != -1) { + item.selected = true; + d.cntSelectedTags++; + } else { + item.selected = false; + } + d.tagsModel.set(i, item); + } + } + + onTagsChanged: { + var obj = JSON.parse(tags); + + d.cntSelectedTags = 0; + d.tagsModel.clear(); + for (const key of Object.keys(obj)) { + d.tagsModel.append({ name: key, emoji: obj[key], selected: false }); + } + } + onSelectedTagsChanged: updateSelectedTags() + + width: 680 + implicitHeight: 820 + + header.title: qsTr("Community Tags") + + QtObject { + id: d + + property int cntSelectedTags: 0 + property ListModel tagsModel: ListModel {} + } + + rightButtons: [ + StatusButton { + text: qsTr("Confirm Community Tags") + onClicked: { + var selectedTags = []; + for (let i = 0; i < d.tagsModel.count; ++i) { + let item = d.tagsModel.get(i); + if (item.selected) + selectedTags.push(item.name); + } + root.accepted(selectedTags.length ? JSON.stringify(selectedTags) : ""); + root.close(); + } + } + ] + + leftButtons: [ + StatusRoundButton { + id: btnBack + icon.name: "arrow-left" + icon.width: 20 + icon.height: 16 + onClicked: { + root.updateSelectedTags(); + root.close(); + } + } + ] + + contentItem: ScrollView { + id: scroll + width: parent.width + topPadding: 30 + leftPadding: 20 + rightPadding: 20 + bottomPadding: 20 + contentHeight: column.height + + ScrollBar.vertical.policy: ScrollBar.AsNeeded + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff + + clip: true + + ColumnLayout { + id: column + width: scroll.width - scroll.leftPadding - scroll.rightPadding + spacing: 20 + + StatusInput { + id: tagsFilter + leftPadding: 0 + rightPadding: 0 + label: qsTr("Select tags that will fit your Community") + input.icon.name: "search" + input.placeholderText: qsTr("Search tags") + Layout.fillWidth: true + } + + StatusCommunityTags { + filterString: tagsFilter.text + model: d.tagsModel + enabled: d.cntSelectedTags < maxSelectedTags + onClicked: { + d.cntSelectedTags++; + item.selected = true; + } + Layout.fillWidth: true + } + + StatusModalDivider { + Layout.fillWidth: true + } + + RowLayout { + StatusBaseText { + text: qsTr("Selected tags") + font.pixelSize: 15 + Layout.fillWidth: true + } + + StatusBaseText { + text: d.cntSelectedTags + "/" + maxSelectedTags + color: Theme.palette.baseColor1 + font.pixelSize: 13 + } + } + + StatusCommunityTags { + model: d.tagsModel + showOnlySelected: true + onClicked: { + d.cntSelectedTags--; + item.selected = false; + } + Layout.fillWidth: true + } + } + } +} \ No newline at end of file diff --git a/ui/app/AppLayouts/Chat/popups/community/CreateCommunityPopup.qml b/ui/app/AppLayouts/Chat/popups/community/CreateCommunityPopup.qml index af39f499f3..19303803c2 100644 --- a/ui/app/AppLayouts/Chat/popups/community/CreateCommunityPopup.qml +++ b/ui/app/AppLayouts/Chat/popups/community/CreateCommunityPopup.qml @@ -100,6 +100,12 @@ StatusModal { Layout.fillWidth: true } + CommunityTagsPicker { + id: communityTagsPicker + tags: root.store.communityTags + Layout.fillWidth: true + } + StatusModalDivider { Layout.fillWidth: true } @@ -149,6 +155,7 @@ StatusModal { introMessage: Utils.filterXSS(introMessageInput.input.text), outroMessage: Utils.filterXSS(outroMessageInput.input.text), color: colorPicker.color.toString().toUpperCase(), + tags: communityTagsPicker.selectedTags, image: { src: logoPicker.source, AX: logoPicker.cropRect.x, diff --git a/ui/app/AppLayouts/Chat/stores/RootStore.qml b/ui/app/AppLayouts/Chat/stores/RootStore.qml index e231ad7973..ac88ae8ef9 100644 --- a/ui/app/AppLayouts/Chat/stores/RootStore.qml +++ b/ui/app/AppLayouts/Chat/stores/RootStore.qml @@ -138,6 +138,8 @@ QtObject { property bool isCommunityHistoryArchiveSupportEnabled: advancedModule? advancedModule.isCommunityHistoryArchiveSupportEnabled : false + property string communityTags: communitiesModule.tags + function reCalculateAddToGroupContacts(channel) { const contacts = getContactListObject() @@ -234,6 +236,7 @@ QtObject { introMessage: "", outroMessage: "", color: "", + tags: "", image: { src: "", AX: 0, @@ -248,7 +251,8 @@ QtObject { } }) { return communitiesModuleInst.createCommunity( - args.name, args.description, args.introMessage, args.outroMessage, args.options.checkedMembership, args.color, + args.name, args.description, args.introMessage, args.outroMessage, + args.options.checkedMembership, args.color, args.tags, args.image.src, args.image.AX, args.image.AY, args.image.BX, args.image.BY, args.options.historyArchiveSupportEnabled, args.options.pinMessagesAllowedForMembers); } diff --git a/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml b/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml index e70422e82f..04a97f1c47 100644 --- a/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml +++ b/ui/app/AppLayouts/Chat/views/CommunitySettingsView.qml @@ -125,6 +125,8 @@ StatusAppTwoPanelLayout { logoImageData: root.community.image bannerImageData: root.community.bannerImageData color: root.community.color + tags: root.rootStore.communityTags + selectedTags: root.community.tags archiveSupportEnabled: root.community.historyArchiveSupportEnabled requestToJoinEnabled: root.community.access === Constants.communityChatOnRequestAccess pinMessagesEnabled: root.community.pinMessageAllMembersEnabled @@ -140,6 +142,7 @@ StatusAppTwoPanelLayout { Utils.filterXSS(item.outroMessage), item.options.requestToJoinEnabled ? Constants.communityChatOnRequestAccess : Constants.communityChatPublicAccess, item.color.toString().toUpperCase(), + item.selectedTags, JSON.stringify({imagePath: String(item.logoImagePath).replace("file://", ""), cropRect: item.logoCropRect}), JSON.stringify({imagePath: String(item.bannerPath).replace("file://", ""), cropRect: item.bannerCropRect}), item.options.archiveSupportEnabled, diff --git a/ui/app/AppLayouts/stores/RootStore.qml b/ui/app/AppLayouts/stores/RootStore.qml index ed309e4e89..794ccdf676 100644 --- a/ui/app/AppLayouts/stores/RootStore.qml +++ b/ui/app/AppLayouts/stores/RootStore.qml @@ -62,8 +62,11 @@ QtObject { return profileSectionModule.ensUsernamesModule.getEtherscanLink() } - function createCommunity(communityName, communityDescription, checkedMembership, communityColor, communityImage, imageCropperModalaX, imageCropperModalaY, imageCropperModalbX, imageCropperModalbY) { - communitiesModuleInst.createCommunity(communityName, communityDescription, checkedMembership, communityColor, communityImage, imageCropperModalaX, imageCropperModalaY, imageCropperModalbX, imageCropperModalbY); + function createCommunity(communityName, communityDescription, checkedMembership, communityColor, communityTags, + communityImage, imageCropperModalaX, imageCropperModalaY, imageCropperModalbX, imageCropperModalbY) { + communitiesModuleInst.createCommunity(communityName, communityDescription, checkedMembership, communityColor, + communityTags, communityImage, imageCropperModalaX, imageCropperModalaY, + imageCropperModalbX, imageCropperModalbY); } function copyToClipboard(text) { diff --git a/vendor/status-go b/vendor/status-go index 8063152657..2873e65a61 160000 --- a/vendor/status-go +++ b/vendor/status-go @@ -1 +1 @@ -Subproject commit 80631526574c1607b98d1330ac659019ebb003c1 +Subproject commit 2873e65a611ed00782d3b833f5a6c2340f98939d