feat: ban/unban/kick system and ephemeral notifications

This commit is contained in:
Mykhailo Prakhov 2024-03-01 12:24:09 +01:00 committed by Jonathan Rainville
parent b92974ffff
commit 9b8c6aa673
10 changed files with 184 additions and 84 deletions

View File

@ -23,7 +23,10 @@ type
CommunityTokenPermissionDeleted, CommunityTokenPermissionDeleted,
CommunityTokenPermissionCreationFailed, CommunityTokenPermissionCreationFailed,
CommunityTokenPermissionUpdateFailed, CommunityTokenPermissionUpdateFailed,
CommunityTokenPermissionDeletionFailed CommunityTokenPermissionDeletionFailed,
CommunityMemberKicked,
CommunityMemberBanned,
CommunityMemberUnbanned
NotificationDetails* = object NotificationDetails* = object
notificationType*: NotificationType # the default value is `UnknownNotification` notificationType*: NotificationType # the default value is `UnknownNotification`
@ -41,14 +44,14 @@ proc isEmpty*(self: NotificationDetails): bool =
proc toNotificationDetails*(jsonObj: JsonNode): NotificationDetails = proc toNotificationDetails*(jsonObj: JsonNode): NotificationDetails =
var notificationType: int var notificationType: int
if (not (jsonObj.getProp("notificationType", notificationType) and if (not (jsonObj.getProp("notificationType", notificationType) and
jsonObj.getProp("sectionId", result.sectionId) and jsonObj.getProp("sectionId", result.sectionId) and
jsonObj.getProp("isCommunitySection", result.isCommunitySection) and jsonObj.getProp("isCommunitySection", result.isCommunitySection) and
jsonObj.getProp("sectionActive", result.sectionActive) and jsonObj.getProp("sectionActive", result.sectionActive) and
jsonObj.getProp("chatId", result.chatId) and jsonObj.getProp("chatId", result.chatId) and
jsonObj.getProp("chatActive", result.chatActive) and jsonObj.getProp("chatActive", result.chatActive) and
jsonObj.getProp("isOneToOne", result.isOneToOne) and jsonObj.getProp("isOneToOne", result.isOneToOne) and
jsonObj.getProp("isGroupChat", result.isGroupChat) and jsonObj.getProp("isGroupChat", result.isGroupChat) and
jsonObj.getProp("messageId", result.messageId))): jsonObj.getProp("messageId", result.messageId))):
return NotificationDetails() return NotificationDetails()

View File

@ -63,21 +63,21 @@ QtObject:
self.soundManager = newStatusSoundManager() self.soundManager = newStatusSoundManager()
signalConnect(self.osNotification, "notificationClicked(QString)", self, "onOSNotificationClicked(QString)", 2) signalConnect(self.osNotification, "notificationClicked(QString)", self, "onOSNotificationClicked(QString)", 2)
signalConnect(singletonInstance.globalEvents, "showTestNotification(QString, QString)", signalConnect(singletonInstance.globalEvents, "showTestNotification(QString, QString)",
self, "onShowTestNotification(QString, QString)", 2) self, "onShowTestNotification(QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "showMessageNotification(QString, QString, QString, bool, bool, QString, bool, QString, int, bool, bool)", signalConnect(singletonInstance.globalEvents, "showMessageNotification(QString, QString, QString, bool, bool, QString, bool, QString, int, bool, bool)",
self, "onShowMessageNotification(QString, QString, QString, bool, bool, QString, bool, QString, int, bool, bool)", 2) self, "onShowMessageNotification(QString, QString, QString, bool, bool, QString, bool, QString, int, bool, bool)", 2)
signalConnect(singletonInstance.globalEvents, "showNewContactRequestNotification(QString, QString, QString)", signalConnect(singletonInstance.globalEvents, "showNewContactRequestNotification(QString, QString, QString)",
self, "onShowNewContactRequestNotification(QString, QString, QString)", 2) self, "onShowNewContactRequestNotification(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "showAcceptedContactRequest(QString, QString, QString)", signalConnect(singletonInstance.globalEvents, "showAcceptedContactRequest(QString, QString, QString)",
self, "onShowAcceptedContactRequest(QString, QString, QString)", 2) self, "onShowAcceptedContactRequest(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "showContactRemoved(QString, QString, QString)", signalConnect(singletonInstance.globalEvents, "showContactRemoved(QString, QString, QString)",
self, "onShowContactRemoved(QString, QString, QString)", 2) self, "onShowContactRemoved(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "newCommunityMembershipRequestNotification(QString, QString, QString)", signalConnect(singletonInstance.globalEvents, "newCommunityMembershipRequestNotification(QString, QString, QString)",
self, "onNewCommunityMembershipRequestNotification(QString, QString, QString)", 2) self, "onNewCommunityMembershipRequestNotification(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "myRequestToJoinCommunityAcccepted(QString, QString, QString)", signalConnect(singletonInstance.globalEvents, "myRequestToJoinCommunityAcccepted(QString, QString, QString)",
self, "onMyRequestToJoinCommunityAcccepted(QString, QString, QString)", 2) self, "onMyRequestToJoinCommunityAcccepted(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "myRequestToJoinCommunityRejected(QString, QString, QString)", signalConnect(singletonInstance.globalEvents, "myRequestToJoinCommunityRejected(QString, QString, QString)",
self, "onMyRequestToJoinCommunityRejected(QString, QString, QString)", 2) self, "onMyRequestToJoinCommunityRejected(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "meMentionedIconBadgeNotification(int)", signalConnect(singletonInstance.globalEvents, "meMentionedIconBadgeNotification(int)",
self, "onMeMentionedIconBadgeNotification(int)", 2) self, "onMeMentionedIconBadgeNotification(int)", 2)
@ -88,12 +88,16 @@ QtObject:
signalConnect(singletonInstance.globalEvents, "showCommunityTokenPermissionUpdateFailedNotification(QString, QString, QString)", self, "onShowCommunityTokenPermissionUpdateFailedNotification(QString, QString, QString)", 2) signalConnect(singletonInstance.globalEvents, "showCommunityTokenPermissionUpdateFailedNotification(QString, QString, QString)", self, "onShowCommunityTokenPermissionUpdateFailedNotification(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "showCommunityTokenPermissionDeletionFailedNotification(QString, QString, QString)", self, "onShowCommunityTokenPermissionDeletionFailedNotification(QString, QString, QString)", 2) signalConnect(singletonInstance.globalEvents, "showCommunityTokenPermissionDeletionFailedNotification(QString, QString, QString)", self, "onShowCommunityTokenPermissionDeletionFailedNotification(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "showCommunityMemberKickedNotification(QString, QString, QString)", self, "onShowCommunityMemberKickedNotification(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "showCommunityMemberBannedNotification(QString, QString, QString)", self, "onShowCommunityMemberBannedNotification(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "showCommunityMemberUnbannedNotification(QString, QString, QString)", self, "onShowCommunityMemberUnbannedNotification(QString, QString, QString)", 2)
self.notificationSetUp = true self.notificationSetUp = true
proc init*(self: NotificationsManager) = proc init*(self: NotificationsManager) =
self.events.once(FAKE_LOADING_SCREEN_FINISHED) do(e:Args): self.events.once(FAKE_LOADING_SCREEN_FINISHED) do(e:Args):
self.onAppReady() self.onAppReady()
proc showOSNotification(self: NotificationsManager, title: string, message: string, identifier: string) = proc showOSNotification(self: NotificationsManager, title: string, message: string, identifier: string) =
if defined(windows): if defined(windows):
let data = NotificationArgs(title: title, message: message) let data = NotificationArgs(title: title, message: message)
@ -107,7 +111,7 @@ QtObject:
## This slot is called once user clicks OS notificaiton bubble, "identifier" ## This slot is called once user clicks OS notificaiton bubble, "identifier"
## contains data which uniquely define that notification. ## contains data which uniquely define that notification.
debug "OS notification clicked", identifier=identifier debug "OS notification clicked", identifier=identifier
# Make the app the top most window. # Make the app the top most window.
app_makeItActive(singletonInstance.engine) app_makeItActive(singletonInstance.engine)
@ -119,7 +123,7 @@ QtObject:
info "Test notification was clicked" info "Test notification was clicked"
return return
if(details.notificationType == NotificationType.NewMessage or if(details.notificationType == NotificationType.NewMessage or
details.notificationType == NotificationType.NewMessageWithPersonalMention or details.notificationType == NotificationType.NewMessageWithPersonalMention or
details.notificationType == NotificationType.NewMessageWithGlobalMention): details.notificationType == NotificationType.NewMessageWithGlobalMention):
let data = ActiveSectionChatArgs(sectionId: details.sectionId, chatId: details.chatId, messageId: details.messageId) let data = ActiveSectionChatArgs(sectionId: details.sectionId, chatId: details.chatId, messageId: details.messageId)
@ -131,15 +135,15 @@ QtObject:
let details = NotificationDetails(notificationType: NotificationType.TestNotification) let details = NotificationDetails(notificationType: NotificationType.TestNotification)
self.processNotification(title, message, details) self.processNotification(title, message, details)
proc onShowMessageNotification(self: NotificationsManager, title: string, message: string, sectionId: string, proc onShowMessageNotification(self: NotificationsManager, title: string, message: string, sectionId: string,
isCommunitySection: bool, isSectionActive: bool, chatId: string, isChatActive: bool, messageId: string, isCommunitySection: bool, isSectionActive: bool, chatId: string, isChatActive: bool, messageId: string,
notificationType: int, isOneToOne: bool, isGroupChat: bool) {.slot.} = notificationType: int, isOneToOne: bool, isGroupChat: bool) {.slot.} =
let details = NotificationDetails( let details = NotificationDetails(
notificationType: notificationType.NotificationType, notificationType: notificationType.NotificationType,
sectionId: sectionId, sectionId: sectionId,
isCommunitySection: isCommunitySection, isCommunitySection: isCommunitySection,
sectionActive: isSectionActive, sectionActive: isSectionActive,
chatId: chatId, chatId: chatId,
chatActive: isChatActive, chatActive: isChatActive,
isOneToOne: isOneToOne, isOneToOne: isOneToOne,
isGroupChat: isGroupChat, isGroupChat: isGroupChat,
@ -170,12 +174,12 @@ QtObject:
let details = NotificationDetails(notificationType: NotificationType.CommunityTokenPermissionDeletionFailed, sectionId: sectionId, isCommunitySection: true) let details = NotificationDetails(notificationType: NotificationType.CommunityTokenPermissionDeletionFailed, sectionId: sectionId, isCommunitySection: true)
self.processNotification(title, message, details) self.processNotification(title, message, details)
proc onShowNewContactRequestNotification*(self: NotificationsManager, title: string, message: string, proc onShowNewContactRequestNotification*(self: NotificationsManager, title: string, message: string,
sectionId: string) {.slot.} = sectionId: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.NewContactRequest, sectionId: sectionId) let details = NotificationDetails(notificationType: NotificationType.NewContactRequest, sectionId: sectionId)
self.processNotification(title, message, details) self.processNotification(title, message, details)
proc onShowAcceptedContactRequest*(self: NotificationsManager, title: string, message: string, proc onShowAcceptedContactRequest*(self: NotificationsManager, title: string, message: string,
sectionId: string) {.slot.} = sectionId: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.AcceptedContactRequest, sectionId: sectionId) let details = NotificationDetails(notificationType: NotificationType.AcceptedContactRequest, sectionId: sectionId)
self.processNotification(title, message, details) self.processNotification(title, message, details)
@ -185,26 +189,38 @@ QtObject:
let details = NotificationDetails(notificationType: NotificationType.ContactRemoved, sectionId: sectionId) let details = NotificationDetails(notificationType: NotificationType.ContactRemoved, sectionId: sectionId)
self.processNotification(title, message, details) self.processNotification(title, message, details)
proc onNewCommunityMembershipRequestNotification*(self: NotificationsManager, title: string, message: string, proc onNewCommunityMembershipRequestNotification*(self: NotificationsManager, title: string, message: string,
sectionId: string) {.slot.} = sectionId: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.JoinCommunityRequest, sectionId: sectionId) let details = NotificationDetails(notificationType: NotificationType.JoinCommunityRequest, sectionId: sectionId)
self.processNotification(title, message, details) self.processNotification(title, message, details)
proc onMyRequestToJoinCommunityAcccepted*(self: NotificationsManager, title: string, message: string, proc onMyRequestToJoinCommunityAcccepted*(self: NotificationsManager, title: string, message: string,
sectionId: string) {.slot.} = sectionId: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.MyRequestToJoinCommunityAccepted, let details = NotificationDetails(notificationType: NotificationType.MyRequestToJoinCommunityAccepted,
sectionId: sectionId) sectionId: sectionId)
self.processNotification(title, message, details) self.processNotification(title, message, details)
proc onMyRequestToJoinCommunityRejected*(self: NotificationsManager, title: string, message: string, proc onMyRequestToJoinCommunityRejected*(self: NotificationsManager, title: string, message: string,
sectionId: string) {.slot.} = sectionId: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.MyRequestToJoinCommunityRejected, let details = NotificationDetails(notificationType: NotificationType.MyRequestToJoinCommunityRejected,
sectionId: sectionId) sectionId: sectionId)
self.processNotification(title, message, details) self.processNotification(title, message, details)
proc onMeMentionedIconBadgeNotification(self: NotificationsManager, allMentions: int) {.slot.} = proc onMeMentionedIconBadgeNotification(self: NotificationsManager, allMentions: int) {.slot.} =
self.osNotification.showIconBadgeNotification(allMentions) self.osNotification.showIconBadgeNotification(allMentions)
proc onShowCommunityMemberKickedNotification*(self: NotificationsManager, title: string, message: string, sectionId: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.CommunityMemberKicked, sectionId: sectionId, isCommunitySection: true)
self.processNotification(title, message, details)
proc onShowCommunityMemberBannedNotification*(self: NotificationsManager, title: string, message: string, sectionId: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.CommunityMemberBanned, sectionId: sectionId, isCommunitySection: true)
self.processNotification(title, message, details)
proc onShowCommunityMemberUnbannedNotification*(self: NotificationsManager, title: string, message: string, sectionId: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.CommunityMemberUnbanned, sectionId: sectionId, isCommunitySection: true)
self.processNotification(title, message, details)
proc notificationCheck(self: NotificationsManager, title: string, message: string, details: NotificationDetails, proc notificationCheck(self: NotificationsManager, title: string, message: string, details: NotificationDetails,
notificationWay: string) = notificationWay: string) =
var data = NotificationArgs(title: title, message: message, details: details) var data = NotificationArgs(title: title, message: message, details: details)
@ -213,32 +229,32 @@ QtObject:
debug "Add AC notification", title=title, message=message debug "Add AC notification", title=title, message=message
self.events.emit(SIGNAL_ADD_NOTIFICATION_TO_ACTIVITY_CENTER, data) self.events.emit(SIGNAL_ADD_NOTIFICATION_TO_ACTIVITY_CENTER, data)
# An exemption from the diagrams, at least for now, is that we don't need to implement the "Badge Check" block here, # An exemption from the diagrams, at least for now, is that we don't need to implement the "Badge Check" block here,
# cause that's already handled in appropriate modules. # cause that's already handled in appropriate modules.
let appIsActive = app_isActive(singletonInstance.engine) let appIsActive = app_isActive(singletonInstance.engine)
if details.notificationType == NotificationType.NewMessage or if details.notificationType == NotificationType.NewMessage or
details.notificationType == NotificationType.NewMessageWithPersonalMention or details.notificationType == NotificationType.NewMessageWithPersonalMention or
details.notificationType == NotificationType.NewMessageWithGlobalMention or details.notificationType == NotificationType.NewMessageWithGlobalMention or
details.notificationType == NotificationType.NewContactRequest or details.notificationType == NotificationType.NewContactRequest or
details.notificationType == NotificationType.ContactRemoved or details.notificationType == NotificationType.ContactRemoved or
details.notificationType == NotificationType.IdentityVerificationRequest: details.notificationType == NotificationType.IdentityVerificationRequest:
if notificationWay == VALUE_NOTIF_DELIVER_QUIETLY: if notificationWay == VALUE_NOTIF_DELIVER_QUIETLY:
return return
if (details.notificationType == NotificationType.NewMessage or if (details.notificationType == NotificationType.NewMessage or
details.notificationType == NotificationType.NewMessageWithPersonalMention or details.notificationType == NotificationType.NewMessageWithPersonalMention or
details.notificationType == NotificationType.NewMessageWithGlobalMention) and details.notificationType == NotificationType.NewMessageWithGlobalMention) and
details.sectionActive and details.sectionActive and
details.chatActive and appIsActive: details.chatActive and appIsActive:
return return
if appIsActive: if appIsActive:
debug "Add APP notification", title=title, message=message debug "Add APP notification", title=title, message=message
self.events.emit(SIGNAL_DISPLAY_APP_NOTIFICATION, data) self.events.emit(SIGNAL_DISPLAY_APP_NOTIFICATION, data)
if not appIsActive or details.notificationType == NotificationType.TestNotification: if not appIsActive or details.notificationType == NotificationType.TestNotification:
# Check anonymity level # Check anonymity level
if(self.settingsService.getNotificationMessagePreview() == PREVIEW_ANONYMOUS): if(self.settingsService.getNotificationMessagePreview() == PREVIEW_ANONYMOUS):
@ -249,18 +265,18 @@ QtObject:
let identifier = $(details.toJsonNode()) let identifier = $(details.toJsonNode())
debug "Add OS notification", title=data.title, message=data.message, identifier=identifier debug "Add OS notification", title=data.title, message=data.message, identifier=identifier
self.showOSNotification(data.title, data.message, identifier) self.showOSNotification(data.title, data.message, identifier)
if self.settingsService.getNotificationSoundsEnabled(): if self.settingsService.getNotificationSoundsEnabled():
self.soundManager.setPlayerVolume(self.settingsService.getNotificationVolume()) self.soundManager.setPlayerVolume(self.settingsService.getNotificationVolume())
self.soundManager.playSound(NOTIFICATION_SOUND) self.soundManager.playSound(NOTIFICATION_SOUND)
proc processNotification(self: NotificationsManager, title: string, message: string, details: NotificationDetails) = proc processNotification(self: NotificationsManager, title: string, message: string, details: NotificationDetails) =
## This is the main method which need to be called to process an event according to the preferences set in the ## This is the main method which need to be called to process an event according to the preferences set in the
## "Notifications & Sounds" panel of the "Settings" section. ## "Notifications & Sounds" panel of the "Settings" section.
## ##
## This method determines whether a notification need to be displayed or not, what notification to display, whether ## This method determines whether a notification need to be displayed or not, what notification to display, whether
## to display App or OS notification and/or add notification to Activity Center, what level of anonymous to apply, ## to display App or OS notification and/or add notification to Activity Center, what level of anonymous to apply,
## whether to play sound or not and so... ## whether to play sound or not and so...
# The flow used here follows these diagrams: # The flow used here follows these diagrams:
@ -274,7 +290,7 @@ QtObject:
if(details.notificationType == NotificationType.NewContactRequest): if(details.notificationType == NotificationType.NewContactRequest):
if(self.settingsService.getNotifSettingContactRequests() != VALUE_NOTIF_TURN_OFF): if(self.settingsService.getNotifSettingContactRequests() != VALUE_NOTIF_TURN_OFF):
self.notificationCheck(title, message, details, self.settingsService.getNotifSettingContactRequests()) self.notificationCheck(title, message, details, self.settingsService.getNotifSettingContactRequests())
return return
# In case of identity verification request # In case of identity verification request
elif(details.notificationType == NotificationType.IdentityVerificationRequest): elif(details.notificationType == NotificationType.IdentityVerificationRequest):
@ -283,7 +299,7 @@ QtObject:
return return
# In case of new message (regardless it's message with mention or not) # In case of new message (regardless it's message with mention or not)
elif(details.notificationType == NotificationType.NewMessage or elif(details.notificationType == NotificationType.NewMessage or
details.notificationType == NotificationType.NewMessageWithPersonalMention or details.notificationType == NotificationType.NewMessageWithPersonalMention or
details.notificationType == NotificationType.NewMessageWithGlobalMention): details.notificationType == NotificationType.NewMessageWithGlobalMention):
if(self.settingsService.getNotifSettingAllMessages() != VALUE_NOTIF_TURN_OFF): if(self.settingsService.getNotifSettingAllMessages() != VALUE_NOTIF_TURN_OFF):
@ -296,17 +312,17 @@ QtObject:
if(exemptions.muteAllMessages): if(exemptions.muteAllMessages):
return return
if(details.notificationType == NotificationType.NewMessageWithPersonalMention and if(details.notificationType == NotificationType.NewMessageWithPersonalMention and
exemptions.personalMentions != VALUE_NOTIF_TURN_OFF): exemptions.personalMentions != VALUE_NOTIF_TURN_OFF):
self.notificationCheck(title, message, details, exemptions.personalMentions) self.notificationCheck(title, message, details, exemptions.personalMentions)
return return
if(details.notificationType == NotificationType.NewMessageWithGlobalMention and if(details.notificationType == NotificationType.NewMessageWithGlobalMention and
exemptions.globalMentions != VALUE_NOTIF_TURN_OFF): exemptions.globalMentions != VALUE_NOTIF_TURN_OFF):
self.notificationCheck(title, message, details, exemptions.globalMentions) self.notificationCheck(title, message, details, exemptions.globalMentions)
return return
if(details.notificationType == NotificationType.NewMessage and if(details.notificationType == NotificationType.NewMessage and
exemptions.otherMessages != VALUE_NOTIF_TURN_OFF): exemptions.otherMessages != VALUE_NOTIF_TURN_OFF):
self.notificationCheck(title, message, details, exemptions.otherMessages) self.notificationCheck(title, message, details, exemptions.otherMessages)
return return
@ -320,16 +336,16 @@ QtObject:
(details.isGroupChat and details.notificationType != NotificationType.NewMessageWithPersonalMention): (details.isGroupChat and details.notificationType != NotificationType.NewMessageWithPersonalMention):
return return
if(details.notificationType == NotificationType.NewMessageWithPersonalMention and if(details.notificationType == NotificationType.NewMessageWithPersonalMention and
self.settingsService.getNotifSettingPersonalMentions() != VALUE_NOTIF_TURN_OFF): self.settingsService.getNotifSettingPersonalMentions() != VALUE_NOTIF_TURN_OFF):
self.notificationCheck(title, message, details, self.settingsService.getNotifSettingPersonalMentions()) self.notificationCheck(title, message, details, self.settingsService.getNotifSettingPersonalMentions())
return return
if(details.notificationType == NotificationType.NewMessageWithGlobalMention and if(details.notificationType == NotificationType.NewMessageWithGlobalMention and
self.settingsService.getNotifSettingGlobalMentions() != VALUE_NOTIF_TURN_OFF): self.settingsService.getNotifSettingGlobalMentions() != VALUE_NOTIF_TURN_OFF):
self.notificationCheck(title, message, details, self.settingsService.getNotifSettingGlobalMentions()) self.notificationCheck(title, message, details, self.settingsService.getNotifSettingGlobalMentions())
return return
if(details.notificationType == NotificationType.NewMessage): if(details.notificationType == NotificationType.NewMessage):
if(details.isOneToOne and if(details.isOneToOne and
self.settingsService.getNotifSettingOneToOneChats() != VALUE_NOTIF_TURN_OFF): self.settingsService.getNotifSettingOneToOneChats() != VALUE_NOTIF_TURN_OFF):

View File

@ -14,7 +14,7 @@ QtObject:
result.setup result.setup
proc showTestNotification*(self: GlobalEvents, title: string, message: string) {.signal.} proc showTestNotification*(self: GlobalEvents, title: string, message: string) {.signal.}
proc showCommunityTokenPermissionCreatedNotification*(self: GlobalEvents, sectionId: string, title: string, message: string) {.signal.} proc showCommunityTokenPermissionCreatedNotification*(self: GlobalEvents, sectionId: string, title: string, message: string) {.signal.}
proc showCommunityTokenPermissionUpdatedNotification*(self: GlobalEvents, sectionId: string, title: string, message: string) {.signal.} proc showCommunityTokenPermissionUpdatedNotification*(self: GlobalEvents, sectionId: string, title: string, message: string) {.signal.}
@ -27,10 +27,10 @@ QtObject:
proc showCommunityTokenPermissionDeletionFailedNotification*(self: GlobalEvents, sectionId: string, title: string, message: string) {.signal.} proc showCommunityTokenPermissionDeletionFailedNotification*(self: GlobalEvents, sectionId: string, title: string, message: string) {.signal.}
proc showMessageNotification*(self: GlobalEvents, title: string, message: string, sectionId: string, proc showMessageNotification*(self: GlobalEvents, title: string, message: string, sectionId: string,
isCommunitySection: bool, isSectionActive: bool, chatId: string, isChatActive: bool, messageId: string, isCommunitySection: bool, isSectionActive: bool, chatId: string, isChatActive: bool, messageId: string,
notificationType: int, isOneToOne: bool, isGroupChat: bool) {.signal.} notificationType: int, isOneToOne: bool, isGroupChat: bool) {.signal.}
proc showNewContactRequestNotification*(self: GlobalEvents, title: string, message: string, proc showNewContactRequestNotification*(self: GlobalEvents, title: string, message: string,
sectionId: string) {.signal.} sectionId: string) {.signal.}
@ -39,14 +39,20 @@ QtObject:
proc showContactRemoved*(self: GlobalEvents, title: string, message: string, proc showContactRemoved*(self: GlobalEvents, title: string, message: string,
sectionId: string) {.signal.} sectionId: string) {.signal.}
proc newCommunityMembershipRequestNotification*(self: GlobalEvents, title: string, message: string, proc newCommunityMembershipRequestNotification*(self: GlobalEvents, title: string, message: string,
sectionId: string) {.signal.}
proc myRequestToJoinCommunityAcccepted*(self: GlobalEvents, title: string, message: string,
sectionId: string) {.signal.} sectionId: string) {.signal.}
proc myRequestToJoinCommunityRejected*(self: GlobalEvents, title: string, message: string, proc myRequestToJoinCommunityAcccepted*(self: GlobalEvents, title: string, message: string,
sectionId: string) {.signal.}
proc myRequestToJoinCommunityRejected*(self: GlobalEvents, title: string, message: string,
sectionId: string) {.signal.} sectionId: string) {.signal.}
proc meMentionedIconBadgeNotification*(self: GlobalEvents, allMentions: int) {.signal.} proc meMentionedIconBadgeNotification*(self: GlobalEvents, allMentions: int) {.signal.}
proc showCommunityMemberKickedNotification*(self: GlobalEvents, sectionId: string, title: string, message: string) {.signal.}
proc showCommunityMemberBannedNotification*(self: GlobalEvents, sectionId: string, title: string, message: string) {.signal.}
proc showCommunityMemberUnbannedNotification*(self: GlobalEvents, sectionId: string, title: string, message: string) {.signal.}

View File

@ -6,6 +6,14 @@ type
Success Success
Danger Danger
type EphemeralActionType* {.pure} = enum
None = 0
NavigateToCommunityAdmin
OpenFinaliseOwnershipPopup
OpenSendModalPopup
ViewTransactionDetails
OpenFirstCommunityTokenPopup
type type
Item* = object Item* = object
id: int64 id: int64
@ -19,7 +27,7 @@ type
loading: bool loading: bool
ephNotifType: EphemeralNotificationType ephNotifType: EphemeralNotificationType
url: string url: string
actionType: int actionType: EphemeralActionType
actionData: string actionData: string
details: NotificationDetails details: NotificationDetails
@ -33,7 +41,7 @@ proc initItem*(id: int64,
loading = false, loading = false,
ephNotifType = EphemeralNotificationType.Default, ephNotifType = EphemeralNotificationType.Default,
url = "", url = "",
actionType = 0, # It means, no action enabled actionType = EphemeralActionType.None, # It means, no action enabled
actionData = "", actionData = "",
details: NotificationDetails): Item = details: NotificationDetails): Item =
result = Item() result = Item()
@ -63,7 +71,7 @@ proc title*(self: Item): string =
proc durationInMs*(self: Item): int = proc durationInMs*(self: Item): int =
self.durationInMs self.durationInMs
proc subTitle*(self: Item): string = proc subTitle*(self: Item): string =
self.subTitle self.subTitle
@ -85,7 +93,7 @@ proc ephNotifType*(self: Item): EphemeralNotificationType =
proc url*(self: Item): string = proc url*(self: Item): string =
self.url self.url
proc actionType*(self: Item): int = proc actionType*(self: Item): EphemeralActionType =
self.actionType self.actionType
proc actionData*(self: Item): string = proc actionData*(self: Item): string =

View File

@ -84,7 +84,7 @@ QtObject:
of ModelRole.Url: of ModelRole.Url:
result = newQVariant(item.url) result = newQVariant(item.url)
of ModelRole.ActionType: of ModelRole.ActionType:
result = newQVariant(item.actionType) result = newQVariant(item.actionType.int)
of ModelRole.ActionData: of ModelRole.ActionData:
result = newQVariant(item.actionData) result = newQVariant(item.actionData)
@ -93,7 +93,7 @@ QtObject:
if(self.items[i].id == id): if(self.items[i].id == id):
return i return i
return -1 return -1
proc getItemWithId*(self: Model, id: int64): Item = proc getItemWithId*(self: Model, id: int64): Item =
let ind = self.findIndexById(id) let ind = self.findIndexById(id)
if(ind == -1): if(ind == -1):

View File

@ -822,7 +822,10 @@ method setActiveSection*[T](self: Module[T], item: SectionItem, skipSavingInSett
method setActiveSectionById*[T](self: Module[T], id: string) = method setActiveSectionById*[T](self: Module[T], id: string) =
let item = self.view.model().getItemById(id) let item = self.view.model().getItemById(id)
self.setActiveSection(item) if item.isEmpty():
discard self.communitiesModule.spectateCommunity(id)
else:
self.setActiveSection(item)
proc notifySubModulesAboutChange[T](self: Module[T], sectionId: string) = proc notifySubModulesAboutChange[T](self: Module[T], sectionId: string) =
for cModule in self.channelGroupModules.values: for cModule in self.channelGroupModules.values:
@ -1231,9 +1234,36 @@ method onAcceptRequestToJoinSuccess*[T](self: Module[T], communityId: string, me
item.updatePendingRequestLoadingState(memberKey, false) item.updatePendingRequestLoadingState(memberKey, false)
method onMembershipStatusUpdated*[T](self: Module[T], communityId: string, memberPubkey: string, status: MembershipRequestState) = method onMembershipStatusUpdated*[T](self: Module[T], communityId: string, memberPubkey: string, status: MembershipRequestState) =
let item = self.view.model().getItemById(communityId) let myPublicKey = singletonInstance.userProfile.getPubKey()
if item.id != "": let communityDto = self.controller.getCommunityById(communityId)
item.updateMembershipStatus(memberPubkey, status)
if myPublicKey == memberPubkey:
case status:
of MembershipRequestState.Banned:
singletonInstance.globalEvents.showCommunityMemberBannedNotification(fmt "You've been banned from {communityDto.name}", "", communityId)
of MembershipRequestState.Kicked:
singletonInstance.globalEvents.showCommunityMemberKickedNotification(fmt "You were kicked from {communityDto.name}", "", communityId)
of MembershipRequestState.Unbanned:
singletonInstance.globalEvents.showCommunityMemberUnbannedNotification(fmt "You were unbanned from {communityDto.name}", "", communityId)
else:
discard
elif communityDto.isControlNode:
let (contactName, _, _) = self.controller.getContactNameAndImage(memberPubkey)
let item = self.view.model().getItemById(communityId)
if item.id != "":
item.updateMembershipStatus(memberPubkey, status)
case status:
of MembershipRequestState.Banned:
self.displayEphemeralNotification(fmt "{contactName} was banned from {communityDto.name}", "" , "checkmark-circle", false, EphemeralNotificationType.Success.int, "")
of MembershipRequestState.Kicked:
self.displayEphemeralNotification(fmt "{contactName} was kicked from {communityDto.name}", "" , "checkmark-circle", false, EphemeralNotificationType.Success.int, "")
of MembershipRequestState.Unbanned:
self.displayEphemeralNotification(fmt "{contactName} unbanned from {communityDto.name}", "" , "checkmark-circle", false, EphemeralNotificationType.Success.int, "")
else:
discard
method calculateProfileSectionHasNotification*[T](self: Module[T]): bool = method calculateProfileSectionHasNotification*[T](self: Module[T]): bool =
return not self.controller.isMnemonicBackedUp() return not self.controller.isMnemonicBackedUp()
@ -1280,7 +1310,7 @@ method displayEphemeralNotification*[T](self: Module[T], title: string, subTitle
finalEphNotifType = EphemeralNotificationType.Danger finalEphNotifType = EphemeralNotificationType.Danger
let item = ephemeral_notification_item.initItem(id, title, TOAST_MESSAGE_VISIBILITY_DURATION_IN_MS, subTitle, "", icon, "", let item = ephemeral_notification_item.initItem(id, title, TOAST_MESSAGE_VISIBILITY_DURATION_IN_MS, subTitle, "", icon, "",
loading, finalEphNotifType, url, 0, "", details) loading, finalEphNotifType, url, EphemeralActionType.None, "", details)
self.view.ephemeralNotificationModel().addItem(item) self.view.ephemeralNotificationModel().addItem(item)
# TO UNIFY with the one above. # TO UNIFY with the one above.
@ -1296,7 +1326,7 @@ method displayEphemeralWithActionNotification*[T](self: Module[T], title: string
finalEphNotifType = EphemeralNotificationType.Danger finalEphNotifType = EphemeralNotificationType.Danger
let item = ephemeral_notification_item.initItem(id, title, TOAST_MESSAGE_VISIBILITY_DURATION_IN_MS, subTitle, "", icon, iconColor, let item = ephemeral_notification_item.initItem(id, title, TOAST_MESSAGE_VISIBILITY_DURATION_IN_MS, subTitle, "", icon, iconColor,
loading, finalEphNotifType, "", actionType, actionData, details) loading, finalEphNotifType, "", EphemeralActionType(actionType), actionData, details)
self.view.ephemeralNotificationModel().addItem(item) self.view.ephemeralNotificationModel().addItem(item)
# TO UNIFY with the one above. # TO UNIFY with the one above.
@ -1313,11 +1343,11 @@ method displayEphemeralImageWithActionNotification*[T](self: Module[T], title: s
let item = ephemeral_notification_item.initItem(id, title, TOAST_MESSAGE_VISIBILITY_DURATION_IN_MS, subTitle, image, "", "", false, let item = ephemeral_notification_item.initItem(id, title, TOAST_MESSAGE_VISIBILITY_DURATION_IN_MS, subTitle, image, "", "", false,
finalEphNotifType, "", actionType, actionData, details) finalEphNotifType, "", EphemeralActionType(actionType), actionData, details)
self.view.ephemeralNotificationModel().addItem(item) self.view.ephemeralNotificationModel().addItem(item)
method displayEphemeralNotification*[T](self: Module[T], title: string, subTitle: string, details: NotificationDetails) = method displayEphemeralNotification*[T](self: Module[T], title: string, subTitle: string, details: NotificationDetails) =
if(details.notificationType == NotificationType.NewMessage or if details.notificationType == NotificationType.NewMessage or
details.notificationType == NotificationType.NewMessageWithPersonalMention or details.notificationType == NotificationType.NewMessageWithPersonalMention or
details.notificationType == NotificationType.CommunityTokenPermissionCreated or details.notificationType == NotificationType.CommunityTokenPermissionCreated or
details.notificationType == NotificationType.CommunityTokenPermissionUpdated or details.notificationType == NotificationType.CommunityTokenPermissionUpdated or
@ -1325,17 +1355,26 @@ method displayEphemeralNotification*[T](self: Module[T], title: string, subTitle
details.notificationType == NotificationType.CommunityTokenPermissionCreationFailed or details.notificationType == NotificationType.CommunityTokenPermissionCreationFailed or
details.notificationType == NotificationType.CommunityTokenPermissionUpdateFailed or details.notificationType == NotificationType.CommunityTokenPermissionUpdateFailed or
details.notificationType == NotificationType.CommunityTokenPermissionDeletionFailed or details.notificationType == NotificationType.CommunityTokenPermissionDeletionFailed or
details.notificationType == NotificationType.NewMessageWithGlobalMention): details.notificationType == NotificationType.NewMessageWithGlobalMention:
self.displayEphemeralNotification(title, subTitle, "", false, EphemeralNotificationType.Default.int, "", details) self.displayEphemeralNotification(title, subTitle, "", false, EphemeralNotificationType.Default.int, "", details)
elif(details.notificationType == NotificationType.NewContactRequest or elif details.notificationType == NotificationType.NewContactRequest or
details.notificationType == NotificationType.IdentityVerificationRequest or details.notificationType == NotificationType.IdentityVerificationRequest or
details.notificationType == NotificationType.ContactRemoved): details.notificationType == NotificationType.ContactRemoved:
self.displayEphemeralNotification(title, subTitle, "contact", false, EphemeralNotificationType.Default.int, "", details) self.displayEphemeralNotification(title, subTitle, "contact", false, EphemeralNotificationType.Default.int, "", details)
elif(details.notificationType == NotificationType.AcceptedContactRequest): elif details.notificationType == NotificationType.AcceptedContactRequest:
self.displayEphemeralNotification(title, subTitle, "checkmark-circle", false, EphemeralNotificationType.Success.int, "", details) self.displayEphemeralNotification(title, subTitle, "checkmark-circle", false, EphemeralNotificationType.Success.int, "", details)
elif details.notificationType == NotificationType.CommunityMemberKicked:
self.displayEphemeralNotification(title, subTitle, "communities", false, EphemeralNotificationType.Danger.int, "", details)
elif details.notificationType == NotificationType.CommunityMemberBanned:
self.displayEphemeralNotification(title, subTitle, "communities", false, EphemeralNotificationType.Danger.int, "", details)
elif details.notificationType == NotificationType.CommunityMemberUnbanned:
self.displayEphemeralWithActionNotification(title, "Visit community" , "communities", "", false, EphemeralNotificationType.Success.int, EphemeralActionType.NavigateToCommunityAdmin.int, details.sectionId)
method removeEphemeralNotification*[T](self: Module[T], id: int64) = method removeEphemeralNotification*[T](self: Module[T], id: int64) =
self.view.ephemeralNotificationModel().removeItemWithId(id) self.view.ephemeralNotificationModel().removeItemWithId(id)

View File

@ -71,6 +71,7 @@ type MembershipRequestState* {.pure} = enum
UnbannedPending = 9, UnbannedPending = 9,
KickedPending = 10, KickedPending = 10,
AwaitingAddress = 11, AwaitingAddress = 11,
Unbanned = 12,
type type
ContractTransactionStatus* {.pure.} = enum ContractTransactionStatus* {.pure.} = enum

View File

@ -41,6 +41,8 @@ type
BanPending, BanPending,
UnbanPending, UnbanPending,
KickPending KickPending
Unbanned,
Kicked
type CommunityMembershipRequestDto* = object type CommunityMembershipRequestDto* = object
id*: string id*: string
@ -479,7 +481,8 @@ proc toMembershipRequestState*(state: CommunityMemberPendingBanOrKick): Membersh
return MembershipRequestState.UnbannedPending return MembershipRequestState.UnbannedPending
of CommunityMemberPendingBanOrKick.KickPending: of CommunityMemberPendingBanOrKick.KickPending:
return MembershipRequestState.KickedPending return MembershipRequestState.KickedPending
return MembershipRequestState.None else:
return MembershipRequestState.None
proc toCommunitySettingsDto*(jsonObj: JsonNode): CommunitySettingsDto = proc toCommunitySettingsDto*(jsonObj: JsonNode): CommunitySettingsDto =
result = CommunitySettingsDto() result = CommunitySettingsDto()

View File

@ -731,11 +731,31 @@ QtObject:
self.events.emit(SIGNAL_COMMUNITY_JOINED, CommunityArgs(community: community, fromUserAction: false)) self.events.emit(SIGNAL_COMMUNITY_JOINED, CommunityArgs(community: community, fromUserAction: false))
self.events.emit(SIGNAL_COMMUNITIES_UPDATE, CommunitiesArgs(communities: @[community])) self.events.emit(SIGNAL_COMMUNITIES_UPDATE, CommunitiesArgs(communities: @[community]))
if wasJoined and not community.joined and not community.isMember: if wasJoined and not community.joined and not community.isMember:
if not community.spectated: # If we were kicked due to ownership change - we will stay in a spectate mode
self.events.emit(SIGNAL_COMMUNITY_LEFT, CommunityIdArgs(communityId: community.id)) if community.spectated:
else:
self.events.emit(SIGNAL_COMMUNITY_KICKED, CommunityArgs(community: community)) self.events.emit(SIGNAL_COMMUNITY_KICKED, CommunityArgs(community: community))
else:
# We were kicked or banned, leave the community
self.events.emit(SIGNAL_COMMUNITY_LEFT, CommunityIdArgs(communityId: community.id))
var status = MembershipRequestState.Kicked
if community.pendingAndBannedMembers.hasKey(myPublicKey) and
community.pendingAndBannedMembers[myPublicKey] == CommunityMemberPendingBanOrKick.Banned:
status = MembershipRequestState.Banned
self.events.emit(SIGNAL_COMMUNITY_MEMBER_STATUS_CHANGED, CommunityMemberStatusUpdatedArgs(
communityId: community.id,
memberPubkey: myPublicKey,
status: status))
# Check if we were unbanned
if not wasJoined and not community.joined and prevCommunity.pendingAndBannedMembers.hasKey(myPublicKey) and not
community.pendingAndBannedMembers.hasKey(myPublicKey):
self.events.emit(SIGNAL_COMMUNITY_MEMBER_STATUS_CHANGED, CommunityMemberStatusUpdatedArgs(
communityId: community.id,
memberPubkey: myPublicKey,
status: MembershipRequestState.Unbanned))
except Exception as e: except Exception as e:
error "Error handling community updates", msg = e.msg error "Error handling community updates", msg = e.msg
@ -2133,10 +2153,13 @@ QtObject:
var status: MembershipRequestState = MembershipRequestState.None var status: MembershipRequestState = MembershipRequestState.None
if community.pendingAndBannedMembers.hasKey(memberPubkey): if community.pendingAndBannedMembers.hasKey(memberPubkey):
status = community.pendingAndBannedMembers[memberPubkey].toMembershipRequestState() status = community.pendingAndBannedMembers[memberPubkey].toMembershipRequestState()
else:
for member in community.members: if status == MembershipRequestState.None:
if member.id == memberPubkey: let prevCommunity = self.communities[community.id]
status = MembershipRequestState.Accepted if prevCommunity.pendingAndBannedMembers.hasKey(memberPubkey):
status = MembershipRequestState.Unbanned
elif len(prevCommunity.members) > len(community.members):
status = MembershipRequestState.Kicked
self.events.emit(SIGNAL_COMMUNITY_MEMBER_STATUS_CHANGED, CommunityMemberStatusUpdatedArgs( self.events.emit(SIGNAL_COMMUNITY_MEMBER_STATUS_CHANGED, CommunityMemberStatusUpdatedArgs(
communityId: community.id, communityId: community.id,

View File

@ -1229,7 +1229,8 @@ QtObject {
BannedPending, BannedPending,
UnbannedPending, UnbannedPending,
KickedPending, KickedPending,
AwaitingAddress AwaitingAddress,
Unbanned
} }
readonly property QtObject walletAccountColors: QtObject { readonly property QtObject walletAccountColors: QtObject {