From b414d616a672238fee9ffc2afd3a15346bf3656a Mon Sep 17 00:00:00 2001 From: Mykhailo Prakhov <117639195+mprakhov@users.noreply.github.com> Date: Tue, 31 Oct 2023 18:55:41 +0100 Subject: [PATCH] feat: info msg if owner is not awailable after community ownership change (#12560) feat: info msg if the owner is not available after community ownership change --- .../modules/main/chat_section/controller.nim | 12 +- .../main/chat_section/io_interface.nim | 3 + src/app/modules/main/chat_section/module.nim | 7 + src/app/modules/main/chat_section/view.nim | 17 +++ src/app/modules/main/controller.nim | 1 + src/app/modules/main/module.nim | 13 +- .../service/community/async_tasks.nim | 2 + .../service/community/dto/community.nim | 1 + src/app_service/service/community/service.nim | 38 ++++- src/backend/communities.nim | 18 ++- ui/app/AppLayouts/Chat/ChatLayout.qml | 31 +++- .../panels/ControlNodeOfflineCenterPanel.qml | 138 ++++++++++++++++++ ui/app/AppLayouts/Communities/panels/qmldir | 1 + .../views/ControlNodeOfflineCommunityView.qml | 117 +++++++++++++++ ui/app/AppLayouts/Communities/views/qmldir | 1 + vendor/status-go | 2 +- 16 files changed, 379 insertions(+), 23 deletions(-) create mode 100644 ui/app/AppLayouts/Communities/panels/ControlNodeOfflineCenterPanel.qml create mode 100644 ui/app/AppLayouts/Communities/views/ControlNodeOfflineCommunityView.qml diff --git a/src/app/modules/main/chat_section/controller.nim b/src/app/modules/main/chat_section/controller.nim index fa6215b728..53ff18dead 100644 --- a/src/app/modules/main/chat_section/controller.nim +++ b/src/app/modules/main/chat_section/controller.nim @@ -67,7 +67,7 @@ proc newController*(delegate: io_interface.AccessInterface, sectionId: string, i result.walletAccountService = walletAccountService result.tokenService = tokenService result.communityTokensService = communityTokensService - + proc delete*(self: Controller) = self.events.disconnect() @@ -304,6 +304,11 @@ proc init*(self: Controller) = if args.communityId == self.sectionId: self.delegate.setPermissionsToJoinCheckOngoing(false) + self.events.on(SIGNAL_WAITING_ON_NEW_COMMUNITY_OWNER_TO_CONFIRM_REQUEST_TO_REJOIN) do(e: Args): + let args = CommunityIdArgs(e) + if args.communityId == self.sectionId: + self.delegate.onWaitingOnNewCommunityOwnerToConfirmRequestToRejoin() + self.events.on(SignalType.Wallet.event, proc(e: Args) = var data = WalletSignal(e) if data.eventType == backend_collectibles.eventCollectiblesOwnershipUpdateFinished: @@ -676,4 +681,7 @@ proc collectCommunityMetricsMessagesTimestamps*(self: Controller, intervals: str self.communityService.collectCommunityMetricsMessagesTimestamps(self.getMySectionId(), intervals) proc collectCommunityMetricsMessagesCount*(self: Controller, intervals: string) = - self.communityService.collectCommunityMetricsMessagesCount(self.getMySectionId(), intervals) \ No newline at end of file + self.communityService.collectCommunityMetricsMessagesCount(self.getMySectionId(), intervals) + +proc waitingOnNewCommunityOwnerToConfirmRequestToRejoin*(self: Controller, communityId: string): bool = + self.communityService.waitingOnNewCommunityOwnerToConfirmRequestToRejoin(communityId) diff --git a/src/app/modules/main/chat_section/io_interface.nim b/src/app/modules/main/chat_section/io_interface.nim index 2785a7e5d6..bf8a810590 100644 --- a/src/app/modules/main/chat_section/io_interface.nim +++ b/src/app/modules/main/chat_section/io_interface.nim @@ -405,3 +405,6 @@ method setChannelsPermissionsCheckOngoing*(self: AccessInterface, value: bool) { method getChannelsPermissionsCheckOngoing*(self: AccessInterface): bool {.base.} = raise newException(ValueError, "No implementation available") + +method onWaitingOnNewCommunityOwnerToConfirmRequestToRejoin*(self: AccessInterface) {.base.} = + raise newException(ValueError, "No implementation available") \ No newline at end of file diff --git a/src/app/modules/main/chat_section/module.nim b/src/app/modules/main/chat_section/module.nim index 453777ccf1..ee2eabdf7b 100644 --- a/src/app/modules/main/chat_section/module.nim +++ b/src/app/modules/main/chat_section/module.nim @@ -339,6 +339,7 @@ method onChatsLoaded*( else: let community = self.controller.getMyCommunity() self.view.setAmIMember(community.joined) + self.view.setWaitingOnNewCommunityOwnerToConfirmRequestToRejoin(self.controller.waitingOnNewCommunityOwnerToConfirmRequestToRejoin(community.id)) self.initCommunityTokenPermissionsModel(channelGroup) self.onCommunityCheckAllChannelsPermissionsResponse(channelGroup.channelPermissions) self.controller.asyncCheckPermissionsToJoin() @@ -889,9 +890,12 @@ method onCommunityCheckAllChannelsPermissionsResponse*(self: Module, checkAllCha method onKickedFromCommunity*(self: Module) = self.view.setAmIMember(false) + let communityId = self.controller.getMySectionId() + self.view.setWaitingOnNewCommunityOwnerToConfirmRequestToRejoin(self.controller.waitingOnNewCommunityOwnerToConfirmRequestToRejoin(communityId)) method onJoinedCommunity*(self: Module) = self.view.setAmIMember(true) + self.view.setWaitingOnNewCommunityOwnerToConfirmRequestToRejoin(false) method onMarkAllMessagesRead*(self: Module, chat: ChatDto) = self.updateBadgeNotifications(chat, hasUnreadMessages=false, unviewedMentionsCount=0) @@ -1342,3 +1346,6 @@ method setChannelsPermissionsCheckOngoing*(self: Module, value: bool) = for chatId, cModule in self.chatContentModules: if self.view.chatsModel().getItemPermissionsRequired(chatId): cModule.setPermissionsCheckOngoing(true) + +method onWaitingOnNewCommunityOwnerToConfirmRequestToRejoin*(self: Module) = + self.view.setWaitingOnNewCommunityOwnerToConfirmRequestToRejoin(true) diff --git a/src/app/modules/main/chat_section/view.nim b/src/app/modules/main/chat_section/view.nim index 17f74774db..53f1d16ec5 100644 --- a/src/app/modules/main/chat_section/view.nim +++ b/src/app/modules/main/chat_section/view.nim @@ -29,6 +29,7 @@ QtObject: chatsLoaded: bool communityMetrics: string # NOTE: later this should be replaced with QAbstractListModel-based model permissionsCheckOngoing: bool + isWaitingOnNewCommunityOwnerToConfirmRequestToRejoin: bool proc delete*(self: View) = self.model.delete @@ -67,6 +68,7 @@ QtObject: result.requiresTokenPermissionToJoin = false result.chatsLoaded = false result.communityMetrics = "[]" + result.isWaitingOnNewCommunityOwnerToConfirmRequestToRejoin = false proc load*(self: View) = self.delegate.viewDidLoad() @@ -446,3 +448,18 @@ QtObject: return self.permissionsCheckOngoing = value self.permissionsCheckOngoingChanged() + + proc getWaitingOnNewCommunityOwnerToConfirmRequestToRejoin*(self: View): bool {.slot.} = + return self.isWaitingOnNewCommunityOwnerToConfirmRequestToRejoin + + proc isWaitingOnNewCommunityOwnerToConfirmRequestToRejoinChanged*(self: View) {.signal.} + + proc setWaitingOnNewCommunityOwnerToConfirmRequestToRejoin*(self: View, value: bool) = + if (value == self.isWaitingOnNewCommunityOwnerToConfirmRequestToRejoin): + return + self.isWaitingOnNewCommunityOwnerToConfirmRequestToRejoin = value + self.isWaitingOnNewCommunityOwnerToConfirmRequestToRejoinChanged() + + QtProperty[bool] isWaitingOnNewCommunityOwnerToConfirmRequestToRejoin: + read = getWaitingOnNewCommunityOwnerToConfirmRequestToRejoin + notify = isWaitingOnNewCommunityOwnerToConfirmRequestToRejoinChanged \ No newline at end of file diff --git a/src/app/modules/main/controller.nim b/src/app/modules/main/controller.nim index d5f430dd0b..2303bc1247 100644 --- a/src/app/modules/main/controller.nim +++ b/src/app/modules/main/controller.nim @@ -543,3 +543,4 @@ proc asyncGetRevealedAccountsForAllMembers*(self: Controller, communityId: strin proc asyncReevaluateCommunityMembersPermissions*(self: Controller, communityId: string) = self.communityService.asyncReevaluateCommunityMembersPermissions(communityId) + diff --git a/src/app/modules/main/module.nim b/src/app/modules/main/module.nim index 38cb76ae87..b84674ad1e 100644 --- a/src/app/modules/main/module.nim +++ b/src/app/modules/main/module.nim @@ -1155,12 +1155,13 @@ method onRemoteDestructed*[T](self: Module[T], communityId: string, chainId: int method onRequestReevaluateMembersPermissionsIfRequired*[T](self: Module[T], communityId: string, chainId: int, contractAddress: string) = let communityDto = self.controller.getCommunityById(communityId) for _, tokenPermission in communityDto.tokenPermissions.pairs: - for tokenCriteria in tokenPermission.tokenCriteria: - if tokenCriteria.contractAddresses.hasKey(chainId): - let actualAddress = tokenCriteria.contractAddresses[chainId] - if actualAddress == contractAddress: - self.controller.asyncReevaluateCommunityMembersPermissions(communityId) - return + if tokenPermission.type != TokenPermissionType.BecomeTokenOwner: + for tokenCriteria in tokenPermission.tokenCriteria: + if tokenCriteria.contractAddresses.hasKey(chainId): + let actualAddress = tokenCriteria.contractAddresses[chainId] + if actualAddress == contractAddress: + self.controller.asyncReevaluateCommunityMembersPermissions(communityId) + return method onAcceptRequestToJoinLoading*[T](self: Module[T], communityId: string, memberKey: string) = let item = self.view.model().getItemById(communityId) diff --git a/src/app_service/service/community/async_tasks.nim b/src/app_service/service/community/async_tasks.nim index 11d09e79a4..1cfff58dd3 100644 --- a/src/app_service/service/community/async_tasks.nim +++ b/src/app_service/service/community/async_tasks.nim @@ -11,12 +11,14 @@ const asyncLoadCommunitiesDataTask: Task = proc(argEncoded: string) {.gcsafe, ni let responseCommunities = status_go.getAllCommunities() let responseSettings = status_go.getCommunitiesSettings() let responseMyPendingRequestsToJoin = status_go.myPendingRequestsToJoin() + let responseMyAwaitingAddressesRequestsToJoin = status_go.myAwaitingAddressesRequestsToJoin() arg.finish(%* { "tags": responseTags, "communities": responseCommunities, "settings": responseSettings, "myPendingRequestsToJoin": responseMyPendingRequestsToJoin, + "myAwaitingAddressesRequestsToJoin": responseMyAwaitingAddressesRequestsToJoin, "error": "", }) except Exception as e: diff --git a/src/app_service/service/community/dto/community.nim b/src/app_service/service/community/dto/community.nim index 3e405b0f37..f182cdcfaf 100644 --- a/src/app_service/service/community/dto/community.nim +++ b/src/app_service/service/community/dto/community.nim @@ -17,6 +17,7 @@ type RequestToJoinType* {.pure.}= enum Canceled = 4, AcceptedPending = 5, DeclinedPending = 6, + AwaitingAddress = 7, type MutedType* {.pure.}= enum For15min = 1, diff --git a/src/app_service/service/community/service.nim b/src/app_service/service/community/service.nim index d5d74db96a..d95a7abcaa 100644 --- a/src/app_service/service/community/service.nim +++ b/src/app_service/service/community/service.nim @@ -180,6 +180,7 @@ const SIGNAL_COMMUNITY_MEMBERS_CHANGED* = "communityMembersChanged" const SIGNAL_COMMUNITY_KICKED* = "communityKicked" const SIGNAL_NEW_REQUEST_TO_JOIN_COMMUNITY* = "newRequestToJoinCommunity" const SIGNAL_REQUEST_TO_JOIN_COMMUNITY_CANCELED* = "requestToJoinCommunityCanceled" +const SIGNAL_WAITING_ON_NEW_COMMUNITY_OWNER_TO_CONFIRM_REQUEST_TO_REJOIN* = "waitingOnNewCommunityOwnerToConfirmRequestToRejoin" const SIGNAL_CURATED_COMMUNITY_FOUND* = "curatedCommunityFound" const SIGNAL_CURATED_COMMUNITIES_UPDATED* = "curatedCommunitiesUpdated" const SIGNAL_COMMUNITY_MUTED* = "communityMuted" @@ -232,6 +233,7 @@ QtObject: historyArchiveDownloadTaskCommunityIds*: HashSet[string] requestedCommunityIds*: HashSet[string] communityMetrics: Table[string, CommunityMetricsDto] + myAwaitingAddressesRequestsToJoin: Table[string, CommunityMembershipRequestDto] # Forward declaration proc asyncLoadCuratedCommunities*(self: Service) @@ -328,6 +330,8 @@ QtObject: try: self.updateMembershipRequestToNewState(membershipRequest.communityId, membershipRequest.id, community, requestToJoinState) + if requestToJoinState == RequestToJoinType.AwaitingAddress: + self.events.emit(SIGNAL_WAITING_ON_NEW_COMMUNITY_OWNER_TO_CONFIRM_REQUEST_TO_REJOIN, CommunityIdArgs(communityId: membershipRequest.communityId)) except Exception as e: error "Unknown request", msg = e.msg @@ -431,6 +435,7 @@ QtObject: proc saveUpdatedCommunity(self: Service, community: var CommunityDto) = # Community data we get from the signals and responses don't contgain the pending requests # therefore, we must keep the old one + community.pendingRequestsToJoin = self.communities[community.id].pendingRequestsToJoin community.declinedRequestsToJoin = self.communities[community.id].declinedRequestsToJoin community.canceledRequestsToJoin = self.communities[community.id].canceledRequestsToJoin @@ -660,6 +665,9 @@ QtObject: # If the community was not joined before but is now, we signal it if(not wasJoined and community.joined and community.isMember): + if community.id in self.myAwaitingAddressesRequestsToJoin: + self.myAwaitingAddressesRequestsToJoin.del(community.id) + self.events.emit(SIGNAL_COMMUNITY_JOINED, CommunityArgs(community: community, fromUserAction: false)) self.events.emit(SIGNAL_COMMUNITIES_UPDATE, CommunitiesArgs(communities: @[community])) @@ -712,11 +720,19 @@ QtObject: # My pending requests let myPendingRequestResponse = responseObj["myPendingRequestsToJoin"] + if myPendingRequestResponse{"result"}.kind != JNull: for jsonCommunityReqest in myPendingRequestResponse["result"]: let communityRequest = jsonCommunityReqest.toCommunityMembershipRequestDto() self.myCommunityRequests.add(communityRequest) + let myAwaitingRequestResponse = responseObj["myAwaitingAddressesRequestsToJoin"] + + if myAwaitingRequestResponse{"result"}.kind != JNull: + for jsonCommunityReqest in myAwaitingRequestResponse["result"]: + let communityRequest = jsonCommunityReqest.toCommunityMembershipRequestDto() + self.myAwaitingAddressesRequestsToJoin[communityRequest.communityId] = communityRequest + self.events.emit(SIGNAL_COMMUNITY_DATA_LOADED, Args()) except Exception as e: let errDesription = e.msg @@ -1641,7 +1657,7 @@ QtObject: error "error loading curated communities: ", errMsg self.events.emit(SIGNAL_CURATED_COMMUNITIES_LOADING_FAILED, Args()) - proc getCommunityMetrics*(self: Service, communityId: string, metricsType: CommunityMetricsType): CommunityMetricsDto = + proc getCommunityMetrics*(self: Service, communityId: string, metricsType: CommunityMetricsType): CommunityMetricsDto = # NOTE: use metricsType when other metrics types added if self.communityMetrics.hasKey(communityId): return self.communityMetrics[communityId] @@ -1807,12 +1823,17 @@ QtObject: var community = self.communities[communityId] if (indexPending != -1): - if @[RequestToJoinType.Declined, RequestToJoinType.Accepted, RequestToJoinType.Canceled].any(x => x == newState): + if @[RequestToJoinType.Declined, RequestToJoinType.Accepted, RequestToJoinType.Canceled, RequestToJoinType.AwaitingAddress].any(x => x == newState): # If the state is now declined, add to the declined requests if newState == RequestToJoinType.Declined: community.declinedRequestsToJoin.add(community.pendingRequestsToJoin[indexPending]) + # If the state is no longer pending, delete the request community.pendingRequestsToJoin.delete(indexPending) + # Delete if control node changed status for awaiting addresses request to join + if communityId in self.myAwaitingAddressesRequestsToJoin: + self.myAwaitingAddressesRequestsToJoin.del(communityId) + else: community.pendingRequestsToJoin[indexPending].state = newState.int else: @@ -1979,10 +2000,13 @@ QtObject: proc isCommunityRequestPending*(self: Service, communityId: string): bool {.slot.} = for communityRequest in self.myCommunityRequests: - if (communityRequest.communityId == communityId): + if (communityRequest.communityId == communityId and RequestToJoinType(communityRequest.state) == RequestToJoinType.Pending): return true return false + proc waitingOnNewCommunityOwnerToConfirmRequestToRejoin*(self: Service, communityId: string): bool {.slot.} = + return communityId in self.myAwaitingAddressesRequestsToJoin + proc requestExtractDiscordChannelsAndCategories*(self: Service, filesToImport: seq[string]) = try: discard status_go.requestExtractDiscordChannelsAndCategories(filesToImport) @@ -2120,7 +2144,7 @@ QtObject: memberPubkey: memberPubkey, ) self.threadpool.start(arg) - + proc onAsyncGetRevealedAccountsForMemberCompleted*(self: Service, response: string) {.slot.} = try: let rpcResponseObj = response.parseJson @@ -2150,7 +2174,7 @@ QtObject: communityId: communityId, ) self.threadpool.start(arg) - + proc onAsyncGetRevealedAccountsForAllMembersCompleted*(self: Service, response: string) {.slot.} = try: let rpcResponseObj = response.parseJson @@ -2179,13 +2203,13 @@ QtObject: communityId: communityId, ) self.threadpool.start(arg) - + proc onAsyncReevaluateCommunityMembersPermissionsCompleted*(self: Service, response: string) {.slot.} = try: let rpcResponseObj = response.parseJson if rpcResponseObj{"error"}.kind != JNull and rpcResponseObj{"error"}.getStr != "": raise newException(RpcException, rpcResponseObj["error"].getStr) - + except Exception as e: error "error while reevaluating community members permissions", msg = e.msg diff --git a/src/backend/communities.nim b/src/backend/communities.nim index 794f984fa4..d7f182f249 100644 --- a/src/backend/communities.nim +++ b/src/backend/communities.nim @@ -8,7 +8,7 @@ export response_type proc getCommunityTags*(): RpcResponse[JsonNode] {.raises: [Exception].} = result = callPrivateRPC("communityTags".prefix) - + proc muteCategory*(communityId: string, categoryId: string, interval: int): RpcResponse[JsonNode] {.raises: [Exception].} = result = callPrivateRPC("muteCommunityCategory".prefix, %* [ { @@ -82,7 +82,7 @@ proc reevaluateCommunityMembersPermissions*( result = callPrivateRPC("reevaluateCommunityMembersPermissions".prefix, %*[{ "communityId": communityId }]) - + proc checkCommunityChannelPermissions*(communityId: string, chatId: string): RpcResponse[JsonNode] {.raises: [Exception].} = result = callPrivateRPC("checkCommunityChannelPermissions".prefix, %*[{ "communityId": communityId, @@ -98,6 +98,9 @@ proc checkAllCommunityChannelsPermissions*(communityId: string, addresses: seq[s proc myPendingRequestsToJoin*(): RpcResponse[JsonNode] {.raises: [Exception].} = result = callPrivateRPC("myPendingRequestsToJoin".prefix) +proc myAwaitingAddressesRequestsToJoin*(): RpcResponse[JsonNode] {.raises: [Exception].} = + result = callPrivateRPC("myAwaitingAddressesRequestsToJoin".prefix) + proc myCanceledRequestsToJoin*(): RpcResponse[JsonNode] {.raises: [Exception].} = result = callPrivateRPC("myCanceledRequestsToJoin".prefix) @@ -255,7 +258,7 @@ proc deleteCommunityTokenPermission*(communityId: string, permissionId: string): "communityId": communityId, "permissionId": permissionId }]) - + proc requestCancelDiscordCommunityImport*(communityId: string): RpcResponse[JsonNode] {.raises: [Exception].} = result = callPrivateRPC("requestCancelDiscordCommunityImport".prefix, %*[communityId]) @@ -423,9 +426,9 @@ proc unbanUserFromCommunity*(communityId: string, pubKey: string): RpcResponse[J }]) proc setCommunityMuted*(communityId: string, mutedType: int): RpcResponse[JsonNode] {.raises: [Exception].} = - return callPrivateRPC("setCommunityMuted".prefix, %*[{ - "communityId": communityId, - "mutedType": mutedType + return callPrivateRPC("setCommunityMuted".prefix, %*[{ + "communityId": communityId, + "mutedType": mutedType }]) proc shareCommunityToUsers*(communityId: string, pubKeys: seq[string], inviteMessage: string): RpcResponse[JsonNode] {.raises: [Exception].} = @@ -467,3 +470,6 @@ proc getCommunityPublicKeyFromPrivateKey*(communityPrivateKey: string,): RpcResp proc getCommunityMembersForWalletAddresses*(communityId: string, chainId: int): RpcResponse[JsonNode] {.raises: [Exception].} = return callPrivateRPC("getCommunityMembersForWalletAddresses".prefix, %* [communityId, chainId]) + +proc promoteSelfToControlNode*(communityId: string): RpcResponse[JsonNode] {.raises: [Exception].} = + return callPrivateRPC("promoteSelfToControlNode".prefix, %* [communityId]) diff --git a/ui/app/AppLayouts/Chat/ChatLayout.qml b/ui/app/AppLayouts/Chat/ChatLayout.qml index 36955e1269..a442dab37d 100644 --- a/ui/app/AppLayouts/Chat/ChatLayout.qml +++ b/ui/app/AppLayouts/Chat/ChatLayout.qml @@ -54,7 +54,17 @@ StackLayout { Loader { id: mainViewLoader readonly property var chatItem: root.rootStore.chatCommunitySectionModule - sourceComponent: chatItem.isCommunity() && chatItem.requiresTokenPermissionToJoin && !chatItem.amIMember ? joinCommunityViewComponent : chatViewComponent + + sourceComponent: { + if (chatItem.isCommunity() && !chatItem.amIMember) { + if (chatItem.isWaitingOnNewCommunityOwnerToConfirmRequestToRejoin) { + return controlNodeOfflineComponent + } else if (chatItem.requiresTokenPermissionToJoin) { + return joinCommunityViewComponent + } + } + return chatViewComponent + } } Component { @@ -324,6 +334,25 @@ StackLayout { } } } + + Component { + id: controlNodeOfflineComponent + ControlNodeOfflineCommunityView { + id: controlNodeOfflineView + readonly property var communityData: sectionItemModel + readonly property string communityId: communityData.id + name: communityData.name + communityDesc: communityData.description + color: communityData.color + image: communityData.image + membersCount: communityData.members.count + communityItemsModel: root.rootStore.communityItemsModel + notificationCount: activityCenterStore.unreadNotificationsCount + hasUnseenNotifications: activityCenterStore.hasUnseenNotifications + onNotificationButtonClicked: Global.openActivityCenterPopup() + onAdHocChatButtonClicked: rootStore.openCloseCreateChatView() + } + } // End of components related to transfer community ownership flow. Connections { diff --git a/ui/app/AppLayouts/Communities/panels/ControlNodeOfflineCenterPanel.qml b/ui/app/AppLayouts/Communities/panels/ControlNodeOfflineCenterPanel.qml new file mode 100644 index 0000000000..e149116806 --- /dev/null +++ b/ui/app/AppLayouts/Communities/panels/ControlNodeOfflineCenterPanel.qml @@ -0,0 +1,138 @@ +import QtQuick 2.15 +import QtQuick.Layouts 1.15 +import QtGraphicalEffects 1.0 + +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 +import StatusQ.Components 0.1 +import StatusQ.Controls 0.1 +import StatusQ.Layout 0.1 + +ColumnLayout { + id: root + + property string name + property string chatDateTimeText + property string listUsersText + property var messagesModel + + spacing: 0 + + // Blur background: + Item { + Layout.fillWidth: true + Layout.preferredHeight: Math.min( + centralPanelData.implicitHeight, + parent.height) + + ColumnLayout { + id: centralPanelData + width: parent.width + layer.enabled: true + layer.effect: fastBlur + + StatusBaseText { + Layout.alignment: Qt.AlignHCenter + Layout.topMargin: 30 + Layout.bottomMargin: 30 + text: root.chatDateTimeText + font.pixelSize: 13 + color: Theme.palette.baseColor1 + } + + RowLayout { + Layout.alignment: Qt.AlignHCenter + + StatusBaseText { + text: root.listUsersText + font.pixelSize: 13 + } + } + + ListView { + Layout.fillWidth: true + Layout.preferredHeight: childrenRect.height + spacing + Layout.topMargin: 16 + spacing: 16 + model: root.messagesModel + delegate: StatusMessage { + width: ListView.view.width + timestamp: model.timestamp + enabled: false + messageDetails: StatusMessageDetails { + messageText: model.message + contentType: model.contentType + sender.displayName: model.senderDisplayName + sender.isContact: model.isContact + sender.trustIndicator: model.trustIndicator + sender.profileImage: StatusProfileImageSettings { + width: 40 + height: 40 + name: model.profileImage || "" + colorId: model.colorId + } + } + } + } + } + } + + // User information content + Rectangle { + id: panelBase + + Layout.fillWidth: true + Layout.fillHeight: true + color: Theme.palette.statusAppLayout.rightPanelBackgroundColor + gradient: Gradient { + GradientStop { + position: 0.000 + color: "transparent" + } + GradientStop { + position: 0.180 + color: panelBase.color + } + } + + ColumnLayout { + anchors.fill: parent + spacing: 0 + + Item { + Layout.fillHeight: true + } + + StatusBaseText { + Layout.maximumWidth: 405 + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + font.weight: Font.Bold + font.pixelSize: Constants.onboarding.titleFontSize + text: qsTr("%1 will be right back!").arg(root.name) + wrapMode: Text.WordWrap + } + + StatusBaseText { + Layout.maximumWidth: 405 + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + horizontalAlignment: Text.AlignHCenter + font.pixelSize: Constants.onboarding.titleFontSize + text: qsTr("You will automatically re-enter the community and be able to view and post as normal as soon as the community’s control node comes back online.") + wrapMode: Text.WordWrap + } + + Item { + Layout.fillHeight: true + } + } + } + + Component { + id: fastBlur + + FastBlur { + radius: 32 + transparentBorder: true + } + } +} diff --git a/ui/app/AppLayouts/Communities/panels/qmldir b/ui/app/AppLayouts/Communities/panels/qmldir index 656c1ba2d7..93569fda18 100644 --- a/ui/app/AppLayouts/Communities/panels/qmldir +++ b/ui/app/AppLayouts/Communities/panels/qmldir @@ -5,6 +5,7 @@ ChannelsAndCategoriesBannerPanel 1.0 ChannelsAndCategoriesBannerPanel.qml ChatPermissionQualificationPanel 1.0 ChatPermissionQualificationPanel.qml ColorPanel 1.0 ColorPanel.qml ColumnHeaderPanel 1.0 ColumnHeaderPanel.qml +ControlNodeOfflineCenterPanel 1.0 ControlNodeOfflineCenterPanel.qml EditSettingsPanel 1.0 EditSettingsPanel.qml FeesBox 1.0 FeesBox.qml FeesPanel 1.0 FeesPanel.qml diff --git a/ui/app/AppLayouts/Communities/views/ControlNodeOfflineCommunityView.qml b/ui/app/AppLayouts/Communities/views/ControlNodeOfflineCommunityView.qml new file mode 100644 index 0000000000..95f58a130d --- /dev/null +++ b/ui/app/AppLayouts/Communities/views/ControlNodeOfflineCommunityView.qml @@ -0,0 +1,117 @@ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtGraphicalEffects 1.0 + +import StatusQ.Core 0.1 +import StatusQ.Core.Theme 0.1 +import StatusQ.Components 0.1 +import StatusQ.Controls 0.1 + +import AppLayouts.Communities.panels 1.0 +import AppLayouts.Chat.views 1.0 + +import StatusQ.Layout 0.1 + +import utils 1.0 +import shared.popups 1.0 + +StatusSectionLayout { + id: root + + // General properties: + property string name + property string communityDesc + property color color + property string channelName + property string channelDesc + + // Blur view properties: + property int membersCount + property url image + property var communityItemsModel + property string chatDateTimeText + property string listUsersText + property var messagesModel + + signal adHocChatButtonClicked + + + QtObject { + id: d + + readonly property int blurryRadius: 32 + } + + headerContent: JoinCommunityHeaderPanel { + color: root.color + name: root.name + channelName: root.channelName + communityDesc: root.communityDesc + channelDesc: root.channelDesc + } + + // Blur background: + leftPanel: ColumnLayout { + anchors.fill: parent + + ColumnHeaderPanel { + Layout.fillWidth: true + name: root.name + membersCount: root.membersCount + image: root.image + color: root.color + amISectionAdmin: false + openCreateChat: false + onAdHocChatButtonClicked: root.adHocChatButtonClicked() + } + + ColumnLayout { + Layout.fillWidth: true + Layout.margins: Style.current.halfPadding + layer.enabled: true + layer.effect: fastBlur + + Repeater { + model: root.communityItemsModel + delegate: StatusChatListItem { + enabled: false + name: model.name + asset.color: root.color + selected: model.selected + type: StatusChatListItem.Type.CommunityChat + notificationsCount: model.notificationsCount + hasUnreadMessages: model.hasUnreadMessages + } + } + } + + Item { + // filler + Layout.fillHeight: true + Layout.fillWidth: true + } + } + + // Blur background + Control node offline information content: + centerPanel: ControlNodeOfflineCenterPanel { + id: joinCommunityCenterPanel + + anchors.fill: parent + name: root.name + chatDateTimeText: root.chatDateTimeText + listUsersText: root.listUsersText + messagesModel: root.messagesModel + } + + showRightPanel: false + + Component { + id: fastBlur + + FastBlur { + radius: d.blurryRadius + transparentBorder: true + } + } +} diff --git a/ui/app/AppLayouts/Communities/views/qmldir b/ui/app/AppLayouts/Communities/views/qmldir index 1148c73ce0..3b8864079a 100644 --- a/ui/app/AppLayouts/Communities/views/qmldir +++ b/ui/app/AppLayouts/Communities/views/qmldir @@ -3,6 +3,7 @@ CommunityColumnView 1.0 CommunityColumnView.qml CommunitiesGridView 1.0 CommunitiesGridView.qml CommunitySettingsView 1.0 CommunitySettingsView.qml CommunityTokenView 1.0 CommunityTokenView.qml +ControlNodeOfflineCommunityView 1.0 ControlNodeOfflineCommunityView.qml EditAirdropView 1.0 EditAirdropView.qml EditPermissionView 1.0 EditPermissionView.qml EditCommunityTokenView 1.0 EditCommunityTokenView.qml diff --git a/vendor/status-go b/vendor/status-go index d47b5733c0..eb437e9d8d 160000 --- a/vendor/status-go +++ b/vendor/status-go @@ -1 +1 @@ -Subproject commit d47b5733c06b3db02fc11f1284688d4f86a8a43f +Subproject commit eb437e9d8dd5bd1ca3b18fa05c4853d6ae8f4956