feat(ActivityCenter): Community membership status handling

This commit is contained in:
MishkaRogachev 2022-10-13 19:52:44 +04:00 committed by Mikhail Rogachev
parent d4e4e66fc6
commit 9c8fee09cd
14 changed files with 135 additions and 36 deletions

View File

@ -146,7 +146,7 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
)
result.chatService = chat_service.newService(statusFoundation.events, result.contactsService)
result.communityService = community_service.newService(statusFoundation.events,
statusFoundation.threadpool, result.chatService)
statusFoundation.threadpool, result.chatService, result.activityCenterService)
result.tokenService = token_service.newService(
statusFoundation.events, statusFoundation.threadpool, result.networkService
)

View File

@ -5,6 +5,7 @@ type Item* = ref object
id: string # ID is the id of the chat, for public chats it is the name e.g. status, for one-to-one is the hex encoded public key and for group chats is a random uuid appended with the hex encoded pk of the creator of the chat
chatId: string
communityId: string
membershipStatus: int
sectionId: string
name: string
author: string
@ -20,6 +21,7 @@ proc initItem*(
id: string,
chatId: string,
communityId: string,
membershipStatus: int,
sectionId: string,
name: string,
author: string,
@ -35,6 +37,7 @@ proc initItem*(
result.id = id
result.chatId = chatId
result.communityId = communityId
result.membershipStatus = membershipStatus
result.sectionId = sectionId
result.name = name
result.author = author
@ -52,6 +55,7 @@ proc `$`*(self: Item): string =
name: {$self.name},
chatId: {$self.chatId},
communityId: {$self.communityId},
membershipStatus: {$self.membershipStatus},
sectionId: {$self.sectionId},
author: {$self.author},
notificationType: {$self.notificationType},
@ -78,6 +82,9 @@ proc chatId*(self: Item): string =
proc communityId*(self: Item): string =
return self.communityId
proc membershipStatus*(self: Item): int =
return self.membershipStatus
proc sectionId*(self: Item): string =
return self.sectionId

View File

@ -6,6 +6,7 @@ type
Id = UserRole + 1
ChatId
CommunityId
MembershipStatus
SectionId
Name
NotificationType
@ -74,6 +75,7 @@ QtObject:
of NotifRoles.Id: result = newQVariant(acitivityNotificationItem.id)
of NotifRoles.ChatId: result = newQVariant(acitivityNotificationItem.chatId)
of NotifRoles.CommunityId: result = newQVariant(acitivityNotificationItem.communityId)
of NotifRoles.MembershipStatus: result = newQVariant(acitivityNotificationItem.membershipStatus.int)
of NotifRoles.SectionId: result = newQVariant(acitivityNotificationItem.sectionId)
of NotifRoles.Name: result = newQVariant(acitivityNotificationItem.name)
of NotifRoles.Author: result = newQVariant(acitivityNotificationItem.author)
@ -93,6 +95,7 @@ QtObject:
of "id": result = notif.id
of "chatId": result = notif.chatId
of "communityId": result = notif.communityId
of "membershipStatus": result = $(notif.membershipStatus.int)
of "sectionId": result = notif.sectionId
of "name": result = notif.name
of "author": result = notif.author
@ -108,6 +111,7 @@ QtObject:
NotifRoles.Id.int:"id",
NotifRoles.ChatId.int:"chatId",
NotifRoles.CommunityId.int:"communityId",
NotifRoles.MembershipStatus.int: "membershipStatus",
NotifRoles.SectionId.int: "sectionId",
NotifRoles.Name.int: "name",
NotifRoles.Author.int: "author",

View File

@ -128,6 +128,7 @@ method convertToItems*(
n.id,
n.chatId,
n.communityId,
n.membershipStatus.int,
sectionId,
n.name,
n.author,

View File

@ -18,10 +18,17 @@ type ActivityCenterNotificationType* {.pure.}= enum
CommunityMembershipRequest = 8
CommunityKicked = 9
type ActivityCenterMembershipStatus* {.pure.}= enum
Idle = 0,
Pending = 1,
Accepted = 2,
Declined = 3
type ActivityCenterNotificationDto* = ref object of RootObj
id*: string # ID is the id of the chat, for public chats it is the name e.g. status, for one-to-one is the hex encoded public key and for group chats is a random uuid appended with the hex encoded pk of the creator of the chat
chatId*: string
communityId*: string
membershipStatus*: ActivityCenterMembershipStatus
name*: string
author*: string
notificationType*: ActivityCenterNotificationType
@ -36,6 +43,7 @@ proc `$`*(self: ActivityCenterNotificationDto): string =
id: {$self.id},
chatId: {self.chatId},
communityId: {self.communityId},
membershipStatus: {self.membershipStatus},
author: {self.author},
notificationType: {$self.notificationType.int},
timestamp: {self.timestamp},
@ -50,6 +58,14 @@ proc toActivityCenterNotificationDto*(jsonObj: JsonNode): ActivityCenterNotifica
discard jsonObj.getProp("id", result.id)
discard jsonObj.getProp("chatId", result.chatId)
discard jsonObj.getProp("communityId", result.communityId)
result.membershipStatus = ActivityCenterMembershipStatus.Idle
var membershipStatusInt: int
if (jsonObj.getProp("membershipStatus", membershipStatusInt) and
(membershipStatusInt >= ord(low(ActivityCenterMembershipStatus)) or
membershipStatusInt <= ord(high(ActivityCenterMembershipStatus)))):
result.membershipStatus = ActivityCenterMembershipStatus(membershipStatusInt)
discard jsonObj.getProp("author", result.author)
result.notificationType = ActivityCenterNotificationType.Unknown

View File

@ -2,6 +2,7 @@ import NimQml, Tables, json, sequtils, std/algorithm, strformat, strutils, chron
import ./dto/community as community_dto
import ../activity_center/service as activity_center_service
import ../chat/service as chat_service
import ../../../app/global/global_singleton
@ -126,6 +127,7 @@ QtObject:
threadpool: ThreadPool
events: EventEmitter
chatService: chat_service.Service
activityCenterService: activity_center_service.Service
communityTags: string # JSON string contraining tags map
joinedCommunities: Table[string, CommunityDto] # [community_id, CommunityDto]
curatedCommunities: Table[string, CuratedCommunity] # [community_id, CuratedCommunity]
@ -150,13 +152,15 @@ QtObject:
proc newService*(
events: EventEmitter,
threadpool: ThreadPool,
chatService: chat_service.Service
chatService: chat_service.Service,
activityCenterService: activity_center_service.Service
): Service =
result = Service()
result.QObject.setup
result.events = events
result.threadpool = threadpool
result.chatService = chatService
result.activityCenterService = activityCenterService
result.communityTags = newString(0)
result.joinedCommunities = initTable[string, CommunityDto]()
result.curatedCommunities = initTable[string, CuratedCommunity]()
@ -1209,7 +1213,8 @@ QtObject:
proc acceptRequestToJoinCommunity*(self: Service, communityId: string, requestId: string) =
try:
discard status_go.acceptRequestToJoinCommunity(requestId)
let response = status_go.acceptRequestToJoinCommunity(requestId)
self.activityCenterService.parseACNotificationResponse(response)
let newMemberPubkey = self.removeMembershipRequestFromCommunityAndGetMemberPubkey(communityId, requestId)
@ -1223,7 +1228,8 @@ QtObject:
proc declineRequestToJoinCommunity*(self: Service, communityId: string, requestId: string) =
try:
discard status_go.declineRequestToJoinCommunity(requestId)
let response = status_go.declineRequestToJoinCommunity(requestId)
self.activityCenterService.parseACNotificationResponse(response)
self.moveRequestToDeclined(communityId, requestId)

View File

@ -8,6 +8,7 @@ import StatusQ.Core.Theme 0.1
Rectangle {
id: root
z: 100 // NOTE: workaround for message overlay
height: visible ? 24 : 0
width: childrenRect.width + Style.current.smallPadding * 2
radius: height / 2

View File

@ -1,13 +1,14 @@
import QtQuick 2.3
import QtGraphicalEffects 1.13
import StatusQ.Components 0.1
import utils 1.0
import shared.controls 1.0
import shared 1.0
import shared.panels 1.0
import shared.status 1.0
import shared.controls 1.0
Badge {
id: root

View File

@ -47,7 +47,8 @@ Item {
AcceptRejectOptionsButtonsPanel {
id: buttons
visible: pending
anchors.centerIn: parent
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
onAcceptClicked: root.acceptClicked()
onDeclineClicked: root.declineClicked()
onProfileClicked: root.profileClicked()

View File

@ -35,7 +35,7 @@ Item {
color: {
if (root.accepted) {
return Theme.palette.successColor1
} else if (root.dismissed) {
} else if (root.declined) {
return Theme.palette.dangerColor1
}
return Theme.palette.directColor1

View File

@ -248,9 +248,6 @@ Popup {
width: listView.availableWidth
store: root.store
notification: model
messageContextMenu: root.messageContextMenu
previousNotificationIndex: Math.min(listView.count - 1, index + 1)
onActivityCenterClose: root.close()
}
}
}

View File

@ -43,6 +43,24 @@ ActivityNotificationBase {
prevMessageIndex: root.previousNotificationIndex
prevMsgTimestamp: root.previousNotificationTimestamp
onImageClicked: Global.openImagePopup(image, root.messageContextMenu)
messageClickHandler: (sender,
point,
isProfileClick,
isSticker = false,
isImage = false,
image = null,
isEmoji = false,
ideEmojiPicker = false,
isReply = false,
isRightClickOnImage = false,
imageSource = "") => {
if (isProfileClick) {
return Global.openProfilePopup(notification.author)
}
root.activityCenterClose()
root.store.activityCenterModuleInst.switchTo(notification.sectionId, notification.chatId, notification.id)
}
CommunityBadge {
readonly property var community: root.store.getCommunityDetailsAsJson(notification.communityId)
@ -55,21 +73,21 @@ ActivityNotificationBase {
communityImage: community.image
communityColor: community.color
onCommunityNameClicked: {
root.store.setActiveCommunity(notification.message.communityId)
}
onChannelNameClicked: {
root.activityCenterClose()
root.store.activityCenterModuleInst.switchTo(notification.sectionId, notification.chatId, notification.id)
}
onCommunityNameClicked: root.store.setActiveCommunity(notification.communityId)
}
}
ctaComponent: MembershipCta {
pending: true
accepted: false
declined: false
// onAcceptRequestToJoinCommunity: communitySectionModule.acceptRequestToJoinCommunity(id)
// onDeclineRequestToJoinCommunity: communitySectionModule.declineRequestToJoinCommunity(id)
pending: notification.membershipStatus === Constants.activityCenterMembershipStatusPending
accepted: notification.membershipStatus === Constants.activityCenterMembershipStatusAccepted
declined: notification.membershipStatus === Constants.activityCenterMembershipStatusDeclined
onAcceptRequestToJoinCommunity: {
root.store.setActiveCommunity(message.communityId)
root.store.acceptRequestToJoinCommunity(notification.id)
}
onDeclineRequestToJoinCommunity: {
root.store.setActiveCommunity(message.communityId)
root.store.declineRequestToJoinCommunity(notification.id)
}
}
}

View File

@ -7,28 +7,71 @@ import StatusQ.Components 0.1
import shared 1.0
import shared.panels 1.0
import shared.controls 1.0
import utils 1.0
import "../controls"
ActivityNotificationMessage {
ActivityNotificationBase {
id: root
badgeComponent: CommunityBadge {
id: communityBadge
bodyComponent: RowLayout {
readonly property var community: root.store.getCommunityDetailsAsJson(notification.communityId)
property var community: root.store.getCommunityDetailsAsJson(notification.message.communityId)
communityName: community.name
communityImage: community.image
communityColor: community.color
onCommunityNameClicked: {
root.store.setActiveCommunity(notification.message.communityId)
StatusSmartIdenticon {
id: identicon
name: community.name
asset.width: 40
asset.height: 40
asset.color: community.color
asset.letterSize: width / 2.4
asset.name: community.image
asset.isImage: true
}
onChannelNameClicked: {
root.activityCenterClose()
root.store.activityCenterModuleInst.switchTo(notification.sectionId, notification.chatId, notification.id)
StyledText {
text: qsTr("Request to join")
font.weight: Font.Medium
font.pixelSize: 13
Layout.alignment: Qt.AlignVCenter
}
CommunityBadge {
communityName: community.name
communityImage: community.image
communityColor: community.color
onCommunityNameClicked: root.store.setActiveCommunity(notification.communityId)
Layout.alignment: Qt.AlignVCenter
}
StyledText {
text: {
if (notification.membershipStatus === Constants.activityCenterMembershipStatusPending)
return qsTr("pending")
if (notification.membershipStatus === Constants.activityCenterMembershipStatusAccepted)
return qsTr("accepted")
if (notification.membershipStatus === Constants.activityCenterMembershipStatusDeclined)
return qsTr("declined")
return ""
}
font.weight: Font.Medium
font.pixelSize: 13
Layout.alignment: Qt.AlignVCenter
}
}
ctaComponent: notification.membershipStatus === Constants.activityCenterMembershipStatusPending ? visitComponent : null
Component {
id: visitComponent
StyledTextEdit {
text: Utils.getLinkStyle(qsTr("Visit Community"), hoveredLink, Style.current.blue)
readOnly: true
textFormat: Text.RichText
color: Style.current.blue
font.pixelSize: 13
onLinkActivated: root.store.setActiveCommunity(notification.communityId)
}
}
}

View File

@ -523,6 +523,10 @@ QtObject {
readonly property int activityCenterNotificationTypeCommunityRequest: 7
readonly property int activityCenterNotificationTypeCommunityMembershipRequest: 8
readonly property int activityCenterMembershipStatusPending: 1
readonly property int activityCenterMembershipStatusAccepted: 2
readonly property int activityCenterMembershipStatusDeclined: 3
readonly property int contactRequestStateNone: 0
readonly property int contactRequestStatePending: 1
readonly property int contactRequestStateAccepted: 2