diff --git a/src/app/core/signals/remote_signals/messages.nim b/src/app/core/signals/remote_signals/messages.nim
index 6065154a6c..5701be966d 100644
--- a/src/app/core/signals/remote_signals/messages.nim
+++ b/src/app/core/signals/remote_signals/messages.nim
@@ -1,4 +1,4 @@
-import json, chronicles
+import json, chronicles, tables
import base
@@ -28,7 +28,8 @@ type MessageSignal* = ref object of Signal
membershipRequests*: seq[CommunityMembershipRequestDto]
activityCenterNotifications*: seq[ActivityCenterNotificationDto]
statusUpdates*: seq[StatusUpdateDto]
- deletedMessages*: seq[RemovedMessageDto]
+ removedMessages*: seq[RemovedMessageDto]
+ deletedMessages*: Table[string, seq[string]]
removedChats*: seq[string]
currentStatus*: seq[StatusUpdateDto]
settings*: seq[SettingsFieldDto]
@@ -117,7 +118,15 @@ proc fromEvent*(T: type MessageSignal, event: JsonNode): MessageSignal =
if e.contains("removedMessages"):
for jsonRemovedMessage in e["removedMessages"]:
- signal.deletedMessages.add(jsonRemovedMessage.toRemovedMessageDto())
+ signal.removedMessages.add(jsonRemovedMessage.toRemovedMessageDto())
+
+ if e.contains("deletedMessages"):
+ let deletedMessagesObj = e["deletedMessages"]
+ for chatId, messageIdsArrayJson in deletedMessagesObj:
+ if not signal.deletedMessages.hasKey(chatId):
+ signal.deletedMessages[chatId] = @[]
+ for messageId in messageIdsArrayJson:
+ signal.deletedMessages[chatId].add(messageId.getStr())
if e.contains("removedChats"):
for removedChatID in e["removedChats"]:
@@ -161,6 +170,5 @@ proc fromEvent*(T: type MessageSignal, event: JsonNode): MessageSignal =
if e.contains("updatedProfileShowcases"):
for jsonProfileShowcase in e["updatedProfileShowcases"]:
signal.updatedProfileShowcases.add(jsonProfileShowcase.toProfileShowcaseDto())
-
result = signal
diff --git a/src/app/modules/main/chat_section/chat_content/controller.nim b/src/app/modules/main/chat_section/chat_content/controller.nim
index d8a042b6c3..2f91617fc2 100644
--- a/src/app/modules/main/chat_section/chat_content/controller.nim
+++ b/src/app/modules/main/chat_section/chat_content/controller.nim
@@ -1,5 +1,4 @@
-import NimQml
-import json
+import NimQml, tables, json
import io_interface
import ../../../../../app_service/service/settings/service as settings_service
@@ -153,13 +152,20 @@ proc init*(self: Controller) =
self.delegate.onMutualContactChanged()
self.delegate.onContactDetailsUpdated(args.contactId)
- self.events.on(SIGNAL_MESSAGE_DELETION) do(e: Args):
- let args = MessageDeletedArgs(e)
+ self.events.on(SIGNAL_MESSAGE_REMOVED) do(e: Args):
+ let args = MessageRemovedArgs(e)
if(self.chatId != args.chatId):
return
# remove from pinned messages model
self.delegate.onUnpinMessage(args.messageId)
+ self.events.on(SIGNAL_MESSAGES_DELETED) do(e: Args):
+ let args = MessagesDeletedArgs(e)
+ if self.chatId in args.deletedMessages:
+ for deletedMessage in args.deletedMessages[self.chatId]:
+ # delete from pinned messages model
+ self.delegate.onUnpinMessage(deletedMessage)
+
self.events.on(SIGNAL_COMMUNITY_CHANNEL_EDITED) do(e:Args):
let args = CommunityChatArgs(e)
if(args.chat.communityId != self.sectionId or args.chat.id != self.chatId):
diff --git a/src/app/modules/main/chat_section/chat_content/input_area/controller.nim b/src/app/modules/main/chat_section/chat_content/input_area/controller.nim
index 61e6e30cfe..9961e4e411 100644
--- a/src/app/modules/main/chat_section/chat_content/input_area/controller.nim
+++ b/src/app/modules/main/chat_section/chat_content/input_area/controller.nim
@@ -131,7 +131,7 @@ proc getChatId*(self: Controller): string =
proc belongsToCommunity*(self: Controller): bool =
return self.belongsToCommunity
-
+
proc setLinkPreviewEnabledForThisMessage*(self: Controller, enabled: bool) =
self.linkPreviewCurrentMessageSetting = if enabled: UrlUnfurlingMode.Enabled else: UrlUnfurlingMode.Disabled
self.delegate.setAskToEnableLinkPreview(false)
@@ -142,18 +142,18 @@ proc resetLinkPreviews(self: Controller) =
self.linkPreviewCurrentMessageSetting = self.linkPreviewPersistentSetting
self.delegate.setAskToEnableLinkPreview(false)
-proc sendImages*(self: Controller,
- imagePathsAndDataJson: string,
- msg: string,
- replyTo: string,
+proc sendImages*(self: Controller,
+ imagePathsAndDataJson: string,
+ msg: string,
+ replyTo: string,
preferredUsername: string = "",
linkPreviews: seq[LinkPreview]): string =
self.resetLinkPreviews()
self.chatService.sendImages(
- self.chatId,
- imagePathsAndDataJson,
- msg,
- replyTo,
+ self.chatId,
+ imagePathsAndDataJson,
+ msg,
+ replyTo,
preferredUsername,
linkPreviews
)
@@ -165,10 +165,10 @@ proc sendChatMessage*(self: Controller,
preferredUsername: string = "",
linkPreviews: seq[LinkPreview]) =
self.resetLinkPreviews()
- self.chatService.sendChatMessage(self.chatId,
- msg,
- replyTo,
- contentType,
+ self.chatService.sendChatMessage(self.chatId,
+ msg,
+ replyTo,
+ contentType,
preferredUsername,
linkPreviews
)
@@ -288,7 +288,7 @@ proc asyncUnfurlUrls(self: Controller, urls: seq[string]) =
proc asyncUnfurlUnknownUrls(self: Controller, urls: seq[string]) =
let newUrls = self.linkPreviewCache.unknownUrls(urls)
self.asyncUnfurlUrls(newUrls)
-
+
proc linkPreviewsFromCache*(self: Controller, urls: seq[string]): Table[string, LinkPreview] =
return self.linkPreviewCache.linkPreviews(urls)
diff --git a/src/app/modules/main/chat_section/chat_content/messages/controller.nim b/src/app/modules/main/chat_section/chat_content/messages/controller.nim
index 144fbedbd3..da80f571a8 100644
--- a/src/app/modules/main/chat_section/chat_content/messages/controller.nim
+++ b/src/app/modules/main/chat_section/chat_content/messages/controller.nim
@@ -1,4 +1,4 @@
-import chronicles, uuids, times
+import chronicles, uuids, times, tables
import io_interface
import ../../../../../../app/global/global_singleton
@@ -182,11 +182,16 @@ proc init*(self: Controller) =
self.events.on(SIGNAL_LOGGEDIN_USER_IMAGE_CHANGED) do(e: Args):
self.delegate.updateContactDetails(singletonInstance.userProfile.getPubKey())
- self.events.on(SIGNAL_MESSAGE_DELETION) do(e: Args):
- let args = MessageDeletedArgs(e)
+ self.events.on(SIGNAL_MESSAGE_REMOVED) do(e: Args):
+ let args = MessageRemovedArgs(e)
if(self.chatId != args.chatId):
return
- self.delegate.onMessageDeleted(args.messageId, args.deletedBy)
+ self.delegate.onMessageRemoved(args.messageId, args.deletedBy)
+
+ self.events.on(SIGNAL_MESSAGES_DELETED) do(e: Args):
+ let args = MessagesDeletedArgs(e)
+ if self.chatId in args.deletedMessages:
+ self.delegate.onMessagesDeleted(args.deletedMessages[self.chatId])
self.events.on(SIGNAL_MESSAGE_EDITED) do(e: Args):
let args = MessageEditedArgs(e)
@@ -296,7 +301,7 @@ proc deleteMessage*(self: Controller, messageId: string) =
proc editMessage*(self: Controller, messageId: string, contentType: int, updatedMsg: string) =
self.messageService.editMessage(messageId, contentType, updatedMsg)
-
+
proc getSearchedMessageId*(self: Controller): string =
return self.searchedMessageId
diff --git a/src/app/modules/main/chat_section/chat_content/messages/io_interface.nim b/src/app/modules/main/chat_section/chat_content/messages/io_interface.nim
index 012c329bfe..d536206458 100644
--- a/src/app/modules/main/chat_section/chat_content/messages/io_interface.nim
+++ b/src/app/modules/main/chat_section/chat_content/messages/io_interface.nim
@@ -123,7 +123,10 @@ method getNumberOfPinnedMessages*(self: AccessInterface): int {.base.} =
method deleteMessage*(self: AccessInterface, messageId: string) {.base.} =
raise newException(ValueError, "No implementation available")
-method onMessageDeleted*(self: AccessInterface, messageId, deletedBy: string) {.base.} =
+method onMessageRemoved*(self: AccessInterface, messageId, removedBy: string) {.base.} =
+ raise newException(ValueError, "No implementation available")
+
+method onMessagesDeleted*(self: AccessInterface, messageIds: seq[string]) {.base.} =
raise newException(ValueError, "No implementation available")
method editMessage*(self: AccessInterface, messageId: string, contentType: int, updatedMsg: string) {.base.} =
diff --git a/src/app/modules/main/chat_section/chat_content/messages/module.nim b/src/app/modules/main/chat_section/chat_content/messages/module.nim
index ca57cc2ccd..1acda5a774 100644
--- a/src/app/modules/main/chat_section/chat_content/messages/module.nim
+++ b/src/app/modules/main/chat_section/chat_content/messages/module.nim
@@ -378,7 +378,7 @@ proc currentUserWalletContainsAddress(self: Module, address: string): bool =
return false
method reevaluateViewLoadingState*(self: Module) =
- self.view.setLoading(not self.initialMessagesLoaded or
+ self.view.setLoading(not self.initialMessagesLoaded or
not self.firstUnseenMessageState.initialized or
self.firstUnseenMessageState.fetching or
self.view.getMessageSearchOngoing())
@@ -564,16 +564,20 @@ method updateContactDetails*(self: Module, contactId: string) =
method deleteMessage*(self: Module, messageId: string) =
self.controller.deleteMessage(messageId)
-method onMessageDeleted*(self: Module, messageId, deletedBy: string) =
- var deletedByValue = deletedBy
- if deletedBy == "":
- # deletedBy is empty if it was deleted by the sender
+method onMessageRemoved*(self: Module, messageId, removedBy: string) =
+ var removedByValue = removedBy
+ if removedBy == "":
+ # removedBy is empty if it was removed by the sender
let messageItem = self.view.model().getItemWithMessageId(messageId)
if messageItem.id == "":
return
- deletedByValue = messageItem.senderId
- var deletedByContactDetails = self.controller.getContactDetails(deletedByValue)
- self.view.model().messageDeleted(messageId, deletedByValue, deletedByContactDetails)
+ removedByValue = messageItem.senderId
+ var removedByContactDetails = self.controller.getContactDetails(removedByValue)
+ self.view.model().messageRemoved(messageId, removedByValue, removedByContactDetails)
+
+method onMessagesDeleted*(self: Module, messageIds: seq[string]) =
+ for messageId in messageIds:
+ self.view.model().removeItem(messageId)
method editMessage*(self: Module, messageId: string, contentType: int, updatedMsg: string) =
self.controller.editMessage(messageId, contentType, updatedMsg)
@@ -730,7 +734,7 @@ proc updateItemsByAlbum(self: Module, items: var seq[Item], message: MessageDto)
for j in 0 ..< item.albumMessageIds.len:
if item.albumMessageIds[j] == message.id:
return true
-
+
var albumImages = item.albumMessageImages
var albumMessagesIds = item.albumMessageIds
albumMessagesIds.add(message.id)
@@ -770,21 +774,21 @@ proc updateLinkPreviewsContacts(self: Module, item: Item, requestFromMailserver:
if not requestFromMailserver:
continue
-
+
debug "updateLinkPreviewsContacts: contact not found, requesting from mailserver", contactId
item.linkPreviewModel.onContactDataRequested(contactId)
self.controller.requestContactInfo(contactId)
-
+
proc updateLinkPreviewsCommunities(self: Module, item: Item, requestFromMailserver: bool) =
for communityId, url in item.linkPreviewModel.getCommunityLinks().pairs:
let community = self.controller.getCommunityById(communityId)
-
+
if community.id != "":
item.linkPreviewModel.setCommunityInfo(community)
-
+
if not requestFromMailserver:
continue
-
+
debug "updateLinkPreviewsCommunites: requesting from mailserver", communityId
let urlData = self.controller.parseSharedUrl(url)
item.linkPreviewModel.onCommunityInfoRequested(communityId)
diff --git a/src/app/modules/main/chat_section/controller.nim b/src/app/modules/main/chat_section/controller.nim
index 0192fcf1d7..5d3d723834 100644
--- a/src/app/modules/main/chat_section/controller.nim
+++ b/src/app/modules/main/chat_section/controller.nim
@@ -600,8 +600,8 @@ proc leaveCommunity*(self: Controller) =
proc removeUserFromCommunity*(self: Controller, pubKey: string) =
self.communityService.asyncRemoveUserFromCommunity(self.sectionId, pubKey)
-proc banUserFromCommunity*(self: Controller, pubKey: string) =
- self.communityService.asyncBanUserFromCommunity(self.sectionId, pubKey)
+proc banUserFromCommunity*(self: Controller, pubKey: string, deleteAllMessages: bool) =
+ self.communityService.asyncBanUserFromCommunity(self.sectionId, pubKey, deleteAllMessages)
proc unbanUserFromCommunity*(self: Controller, pubKey: string) =
self.communityService.asyncUnbanUserFromCommunity(self.sectionId, pubKey)
diff --git a/src/app/modules/main/chat_section/io_interface.nim b/src/app/modules/main/chat_section/io_interface.nim
index 2a42385615..eb8bb757a6 100644
--- a/src/app/modules/main/chat_section/io_interface.nim
+++ b/src/app/modules/main/chat_section/io_interface.nim
@@ -279,7 +279,7 @@ method leaveCommunity*(self: AccessInterface) {.base.} =
method removeUserFromCommunity*(self: AccessInterface, pubKey: string) {.base.} =
raise newException(ValueError, "No implementation available")
-method banUserFromCommunity*(self: AccessInterface, pubKey: string) {.base.} =
+method banUserFromCommunity*(self: AccessInterface, pubKey: string, deleteAllMessages: bool) {.base.} =
raise newException(ValueError, "No implementation available")
method editCommunity*(self: AccessInterface, name: string, description, introMessage, outroMessage: string,
diff --git a/src/app/modules/main/chat_section/module.nim b/src/app/modules/main/chat_section/module.nim
index fbbd06414e..29e566de6a 100644
--- a/src/app/modules/main/chat_section/module.nim
+++ b/src/app/modules/main/chat_section/module.nim
@@ -1097,8 +1097,8 @@ method leaveCommunity*(self: Module) =
method removeUserFromCommunity*(self: Module, pubKey: string) =
self.controller.removeUserFromCommunity(pubKey)
-method banUserFromCommunity*(self: Module, pubKey: string) =
- self.controller.banUserFromCommunity(pubkey)
+method banUserFromCommunity*(self: Module, pubKey: string, deleteAllMessages: bool) =
+ self.controller.banUserFromCommunity(pubkey, deleteAllMessages)
method unbanUserFromCommunity*(self: Module, pubKey: string) =
self.controller.unbanUserFromCommunity(pubkey)
diff --git a/src/app/modules/main/chat_section/view.nim b/src/app/modules/main/chat_section/view.nim
index 1cc6a0eb63..9954e79909 100644
--- a/src/app/modules/main/chat_section/view.nim
+++ b/src/app/modules/main/chat_section/view.nim
@@ -298,8 +298,8 @@ QtObject:
proc removeUserFromCommunity*(self: View, pubKey: string) {.slot.} =
self.delegate.removeUserFromCommunity(pubKey)
- proc banUserFromCommunity*(self: View, pubKey: string) {.slot.} =
- self.delegate.banUserFromCommunity(pubKey)
+ proc banUserFromCommunity*(self: View, pubKey: string, deleteAllMessages: bool) {.slot.} =
+ self.delegate.banUserFromCommunity(pubKey, deleteAllMessages)
proc editCommunity*(self: View, name: string, description: string, introMessage: string, outroMessage: string, access: int,
color: string, tags: string, logoJsonData: string, bannerJsonData: string, historyArchiveSupportEnabled: bool,
diff --git a/src/app/modules/shared_models/message_model.nim b/src/app/modules/shared_models/message_model.nim
index d4790dad11..e605d6f5a3 100644
--- a/src/app/modules/shared_models/message_model.nim
+++ b/src/app/modules/shared_models/message_model.nim
@@ -498,7 +498,7 @@ QtObject:
self.countChanged()
self.updateMessagesWhenQuotedMessageDeleted(messageId)
- proc messageDeleted*(self: Model, messageId: string, deletedBy: string, deletedByContactDetails: ContactDetails) =
+ proc messageRemoved*(self: Model, messageId: string, deletedBy: string, deletedByContactDetails: ContactDetails) =
let i = self.findIndexForMessageId(messageId)
if(i == -1):
return
@@ -846,7 +846,7 @@ QtObject:
albumImages.add(messageImage)
item.albumMessageImages = albumImages
item.albumMessageIds = albumMessagesIds
-
+
let index = self.createIndex(i, 0, nil)
defer: index.delete
self.dataChanged(index, index, @[ModelRole.AlbumMessageImages.int])
diff --git a/src/app_service/service/activity_center/dto/notification.nim b/src/app_service/service/activity_center/dto/notification.nim
index e64ab91118..89300f91b5 100644
--- a/src/app_service/service/activity_center/dto/notification.nim
+++ b/src/app_service/service/activity_center/dto/notification.nim
@@ -30,6 +30,8 @@ type ActivityCenterNotificationType* {.pure.}= enum
ShareAccounts = 18
CommunityTokenReceived = 19
FirstCommunityTokenReceived = 20
+ CommunityBanned = 21
+ CommunityUnbanned = 22
type ActivityCenterGroup* {.pure.}= enum
All = 0,
@@ -174,7 +176,9 @@ proc activityCenterNotificationTypesByGroup*(group: ActivityCenterGroup) : seq[i
ActivityCenterNotificationType.OwnershipLost.int,
ActivityCenterNotificationType.ShareAccounts.int,
ActivityCenterNotificationType.CommunityTokenReceived.int,
- ActivityCenterNotificationType.FirstCommunityTokenReceived.int
+ ActivityCenterNotificationType.FirstCommunityTokenReceived.int,
+ ActivityCenterNotificationType.CommunityBanned.int,
+ ActivityCenterNotificationType.CommunityUnbanned.int
]
of ActivityCenterGroup.Mentions:
return @[ActivityCenterNotificationType.Mention.int]
@@ -186,7 +190,9 @@ proc activityCenterNotificationTypesByGroup*(group: ActivityCenterGroup) : seq[i
ActivityCenterNotificationType.CommunityInvitation.int,
ActivityCenterNotificationType.CommunityRequest.int,
ActivityCenterNotificationType.CommunityMembershipRequest.int,
- ActivityCenterNotificationType.CommunityKicked.int
+ ActivityCenterNotificationType.CommunityKicked.int,
+ ActivityCenterNotificationType.CommunityBanned.int,
+ ActivityCenterNotificationType.CommunityUnbanned.int
]
of ActivityCenterGroup.Admin:
return @[ActivityCenterNotificationType.CommunityMembershipRequest.int]
diff --git a/src/app_service/service/chat/dto/chat.nim b/src/app_service/service/chat/dto/chat.nim
index 0ef321556f..544e3d8bc3 100644
--- a/src/app_service/service/chat/dto/chat.nim
+++ b/src/app_service/service/chat/dto/chat.nim
@@ -240,9 +240,9 @@ proc toChannelMember*(jsonObj: JsonNode, memberId: string, joined: bool): ChatMe
if(jsonObj.getProp("roles", rolesObj)):
for roleObj in rolesObj:
roles.add(roleObj.getInt)
-
+
result.role = MemberRole.None
- if roles.contains(MemberRole.Owner.int):
+ if roles.contains(MemberRole.Owner.int):
result.role = MemberRole.Owner
elif roles.contains(MemberRole.Admin.int):
result.role = MemberRole.Admin
diff --git a/src/app_service/service/chat/service.nim b/src/app_service/service/chat/service.nim
index 4eca16c031..ad8486a9d2 100644
--- a/src/app_service/service/chat/service.nim
+++ b/src/app_service/service/chat/service.nim
@@ -108,7 +108,7 @@ const SIGNAL_CHAT_UPDATE* = "chatUpdate"
const SIGNAL_CHAT_LEFT* = "channelLeft"
const SIGNAL_SENDING_FAILED* = "messageSendingFailed"
const SIGNAL_SENDING_SUCCESS* = "messageSendingSuccess"
-const SIGNAL_MESSAGE_DELETED* = "messageDeleted"
+const SIGNAL_MESSAGE_REMOVE* = "messageRemove"
const SIGNAL_CHAT_MUTED* = "chatMuted"
const SIGNAL_CHAT_UNMUTED* = "chatUnmuted"
const SIGNAL_CHAT_HISTORY_CLEARED* = "chatHistoryCleared"
@@ -271,7 +271,7 @@ QtObject:
return i
i.inc()
return -1
-
+
proc chatsWithCategoryHaveUnreadMessages*(self: Service, communityId: string, categoryId: string): bool =
if communityId == "" or categoryId == "":
return false
@@ -336,7 +336,7 @@ QtObject:
self.channelGroups[channelGroupId].chats[index] = self.chats[chat.id]
proc updateMissingFieldsInCommunityChat(self: Service, channelGroupId: string, newChat: ChatDto): ChatDto =
-
+
if not self.channelGroups.contains(channelGroupId):
warn "unknown channel group", channelGroupId
return
@@ -359,11 +359,11 @@ QtObject:
# We need to update missing fields in the chats seq before saving
let newChats = channelGroup.chats.mapIt(self.updateMissingFieldsInCommunityChat(channelGroup.id, it))
newChannelGroup.chats = newChats
-
+
self.channelGroups[channelGroup.id] = newChannelGroup
for chat in newChannelGroup.chats:
self.updateOrAddChat(chat)
-
+
proc updateChannelMembers*(self: Service, channel: ChatDto) =
if not self.chats.hasKey(channel.id):
return
@@ -412,7 +412,8 @@ QtObject:
proc processUpdateForTransaction*(self: Service, messageId: string, response: RpcResponse[JsonNode]) =
var (chats, _) = self.processMessageUpdateAfterSend(response)
- self.events.emit(SIGNAL_MESSAGE_DELETED, MessageArgs(id: messageId, channel: chats[0].id))
+ # TODO: Signal is not handled anywhere
+ self.events.emit(SIGNAL_MESSAGE_REMOVE, MessageArgs(id: messageId, channel: chats[0].id))
proc emitUpdate(self: Service, response: RpcResponse[JsonNode]) =
var (chats, _) = self.parseChatResponse(response)
@@ -502,10 +503,10 @@ QtObject:
error "Error deleting channel", chatId, msg = e.msg
return
- proc sendImages*(self: Service,
- chatId: string,
- imagePathsAndDataJson: string,
- msg: string,
+ proc sendImages*(self: Service,
+ chatId: string,
+ imagePathsAndDataJson: string,
+ msg: string,
replyTo: string,
preferredUsername: string = "",
linkPreviews: seq[LinkPreview] = @[]): string =
diff --git a/src/app_service/service/community/async_tasks.nim b/src/app_service/service/community/async_tasks.nim
index 96c59cebfc..a03f626ba5 100644
--- a/src/app_service/service/community/async_tasks.nim
+++ b/src/app_service/service/community/async_tasks.nim
@@ -110,6 +110,7 @@ type
AsyncCommunityMemberActionTaskArg = ref object of QObjectTaskArg
communityId: string
pubKey: string
+ deleteAllMessages: bool
const asyncRemoveUserFromCommunityTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[AsyncCommunityMemberActionTaskArg](argEncoded)
@@ -131,14 +132,15 @@ const asyncRemoveUserFromCommunityTask: Task = proc(argEncoded: string) {.gcsafe
const asyncBanUserFromCommunityTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[AsyncCommunityMemberActionTaskArg](argEncoded)
try:
- let response = status_go.banUserFromCommunity(arg.communityId, arg.pubKey)
+ let response = status_go.banUserFromCommunity(arg.communityId, arg.pubKey, arg.deleteAllMessages)
let tpl: tuple[communityId: string, pubKey: string, response: RpcResponse[JsonNode], error: string] = (arg.communityId, arg.pubKey, response, "")
arg.finish(tpl)
except Exception as e:
arg.finish(%* {
"error": e.msg,
"communityId": arg.communityId,
- "pubKey": arg.pubKey
+ "pubKey": arg.pubKey,
+ "deleteAllMessages": arg.deleteAllMessages
})
const asyncUnbanUserFromCommunityTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
diff --git a/src/app_service/service/community/service.nim b/src/app_service/service/community/service.nim
index 4552bb9cb2..9a199bf87d 100644
--- a/src/app_service/service/community/service.nim
+++ b/src/app_service/service/community/service.nim
@@ -2059,13 +2059,14 @@ QtObject:
)
self.threadpool.start(arg)
- proc asyncBanUserFromCommunity*(self: Service, communityId, pubKey: string) =
+ proc asyncBanUserFromCommunity*(self: Service, communityId, pubKey: string, deleteAllMessages: bool) =
let arg = AsyncCommunityMemberActionTaskArg(
tptr: cast[ByteAddress](asyncBanUserFromCommunityTask),
vptr: cast[ByteAddress](self.vptr),
slot: "onAsyncCommunityMemberActionCompleted",
communityId: communityId,
pubKey: pubKey,
+ deleteAllMessages: deleteAllMessages
)
self.threadpool.start(arg)
diff --git a/src/app_service/service/message/service.nim b/src/app_service/service/message/service.nim
index 70cfe284a7..32ae9a89ef 100644
--- a/src/app_service/service/message/service.nim
+++ b/src/app_service/service/message/service.nim
@@ -54,7 +54,8 @@ const SIGNAL_MESSAGES_MARKED_AS_READ* = "messagesMarkedAsRead"
const SIGNAL_MESSAGE_REACTION_ADDED* = "messageReactionAdded"
const SIGNAL_MESSAGE_REACTION_REMOVED* = "messageReactionRemoved"
const SIGNAL_MESSAGE_REACTION_FROM_OTHERS* = "messageReactionFromOthers"
-const SIGNAL_MESSAGE_DELETION* = "messageDeleted"
+const SIGNAL_MESSAGE_REMOVED* = "messageRemoved"
+const SIGNAL_MESSAGES_DELETED* = "messagesDeleted"
const SIGNAL_MESSAGE_DELIVERED* = "messageDelivered"
const SIGNAL_MESSAGE_EDITED* = "messageEdited"
const SIGNAL_ENVELOPE_SENT* = "envelopeSent"
@@ -111,11 +112,14 @@ type
reactionId*: string
reactionFrom*: string
- MessageDeletedArgs* = ref object of Args
+ MessageRemovedArgs* = ref object of Args
chatId*: string
messageId*: string
deletedBy*: string
+ MessagesDeletedArgs* = ref object of Args
+ deletedMessages*: Table[string, seq[string]]
+
MessageDeliveredArgs* = ref object of Args
chatId*: string
messageId*: string
@@ -348,10 +352,14 @@ QtObject:
self.numOfPinnedMessagesPerChat[chatId] = self.getNumOfPinnedMessages(chatId) - 1
self.events.emit(SIGNAL_MESSAGE_UNPINNED, data)
- proc handleDeletedMessagesUpdate(self: Service, deletedMessages: seq[RemovedMessageDto]) =
- for dm in deletedMessages:
- let data = MessageDeletedArgs(chatId: dm.chatId, messageId: dm.messageId, deletedBy: dm.deletedBy)
- self.events.emit(SIGNAL_MESSAGE_DELETION, data)
+ proc handleRemovedMessagesUpdate(self: Service, removedMessages: seq[RemovedMessageDto]) =
+ for rm in removedMessages:
+ let data = MessageRemovedArgs(chatId: rm.chatId, messageId: rm.messageId, deletedBy: rm.deletedBy)
+ self.events.emit(SIGNAL_MESSAGE_REMOVED, data)
+
+ proc handleDeletedMessagesUpdate(self: Service, deletedMessages: Table[string, seq[string]]) =
+ let data = MessagesDeletedArgs(deletedMessages: deletedMessages)
+ self.events.emit(SIGNAL_MESSAGES_DELETED, data)
proc handleEmojiReactionsUpdate(self: Service, emojiReactions: seq[ReactionDto]) =
for r in emojiReactions:
@@ -416,6 +424,9 @@ QtObject:
# Handling pinned messages updates
if (receivedData.pinnedMessages.len > 0):
self.handlePinnedMessagesUpdate(receivedData.pinnedMessages)
+ # Handling removed messages updates
+ if (receivedData.removedMessages.len > 0):
+ self.handleRemovedMessagesUpdate(receivedData.removedMessages)
# Handling deleted messages updates
if (receivedData.deletedMessages.len > 0):
self.handleDeletedMessagesUpdate(receivedData.deletedMessages)
@@ -430,12 +441,12 @@ QtObject:
self.events.on(SignalType.DiscordCommunityImportFinished.event) do(e: Args):
var receivedData = DiscordCommunityImportFinishedSignal(e)
self.handleMessagesReload(receivedData.communityId)
-
+
self.events.on(SignalType.DiscordChannelImportFinished.event) do(e: Args):
var receivedData = DiscordChannelImportFinishedSignal(e)
self.resetMessageCursor(receivedData.channelId)
self.asyncLoadMoreMessagesForChat(receivedData.channelId)
-
+
self.events.on(SIGNAL_CHAT_LEFT) do(e: Args):
var chatArg = ChatArgs(e)
self.resetMessageCursor(chatArg.chatId)
@@ -637,7 +648,7 @@ QtObject:
messageId: responseObj["messageId"].getStr,
error: responseObj["error"].getStr,
)
-
+
if signalData.error == "":
signalData.message = responseObj["message"].toMessageDto()
@@ -942,7 +953,7 @@ QtObject:
if responseObj.kind != JObject:
warn "expected response is not a json object", methodName = "onAsyncUnfurlUrlsFinished"
return
-
+
let errMessage = responseObj["error"].getStr
if errMessage != "":
error "asyncUnfurlUrls failed", errMessage
@@ -1057,28 +1068,28 @@ proc deleteMessage*(self: Service, messageId: string) =
try:
let response = status_go.deleteMessageAndSend(messageId)
- var deletesMessagesObj: JsonNode
- if(not response.result.getProp("removedMessages", deletesMessagesObj) or deletesMessagesObj.kind != JArray):
- error "error: ", procName="deleteMessage", errDesription = "no messages deleted or it's not an array"
+ var removesMessagesObj: JsonNode
+ if(not response.result.getProp("removedMessages", removesMessagesObj) or removesMessagesObj.kind != JArray):
+ error "error: ", procName="removeMessage", errDesription = "no messages remove or it's not an array"
return
- let deletedMessagesArr = deletesMessagesObj.getElems()
- if(deletedMessagesArr.len == 0): # an array is returned
- error "error: ", procName="deleteMessage", errDesription = "array has no message to delete"
+ let removedMessagesArr = removesMessagesObj.getElems()
+ if(removedMessagesArr.len == 0): # an array is returned
+ error "error: ", procName="removeMessage", errDesription = "array has no message to remove"
return
- let deletedMessageObj = deletedMessagesArr[0]
+ let removedMessageObj = removedMessagesArr[0]
var chat_Id, message_Id: string
- if not deletedMessageObj.getProp("chatId", chat_Id) or not deletedMessageObj.getProp("messageId", message_Id):
- error "error: ", procName="deleteMessage", errDesription = "there is no set chat id or message id in response"
+ if not removedMessageObj.getProp("chatId", chat_Id) or not removedMessageObj.getProp("messageId", message_Id):
+ error "error: ", procName="removeMessage", errDesription = "there is no set chat id or message id in response"
return
- let data = MessageDeletedArgs(
+ let data = MessageRemovedArgs(
chatId: chat_Id,
messageId: message_Id,
deletedBy: singletonInstance.userProfile.getPubKey(),
)
- self.events.emit(SIGNAL_MESSAGE_DELETION, data)
+ self.events.emit(SIGNAL_MESSAGE_REMOVED, data)
except Exception as e:
error "error: ", procName="deleteMessage", errName = e.name, errDesription = e.msg
diff --git a/src/backend/chat.nim b/src/backend/chat.nim
index 1d6ed423eb..e6586d228f 100644
--- a/src/backend/chat.nim
+++ b/src/backend/chat.nim
@@ -86,9 +86,9 @@ proc sendChatMessage*(
}
])
-proc sendImages*(chatId: string,
- images: var seq[string],
- msg: string,
+proc sendImages*(chatId: string,
+ images: var seq[string],
+ msg: string,
replyTo: string,
preferredUsername: string,
linkPreviews: seq[LinkPreview],
diff --git a/src/backend/communities.nim b/src/backend/communities.nim
index 9d5a5cdaca..15500cf3d4 100644
--- a/src/backend/communities.nim
+++ b/src/backend/communities.nim
@@ -460,10 +460,11 @@ proc declineRequestToJoinCommunity*(requestId: string): RpcResponse[JsonNode] {.
"id": requestId
}])
-proc banUserFromCommunity*(communityId: string, pubKey: string): RpcResponse[JsonNode] {.raises: [Exception].} =
+proc banUserFromCommunity*(communityId: string, pubKey: string, deleteAllMessages: bool): RpcResponse[JsonNode] {.raises: [Exception].} =
return callPrivateRPC("banUserFromCommunity".prefix, %*[{
"communityId": communityId,
- "user": pubKey
+ "user": pubKey,
+ "deleteAllMessages": deleteAllMessages,
}])
proc unbanUserFromCommunity*(communityId: string, pubKey: string): RpcResponse[JsonNode] {.raises: [Exception].} =
diff --git a/ui/app/AppLayouts/Chat/stores/RootStore.qml b/ui/app/AppLayouts/Chat/stores/RootStore.qml
index 28096ef479..f94bdbca32 100644
--- a/ui/app/AppLayouts/Chat/stores/RootStore.qml
+++ b/ui/app/AppLayouts/Chat/stores/RootStore.qml
@@ -327,8 +327,8 @@ QtObject {
chatCommunitySectionModule.removeUserFromCommunity(pubKey);
}
- function banUserFromCommunity(pubKey) {
- chatCommunitySectionModule.banUserFromCommunity(pubKey);
+ function banUserFromCommunity(pubKey, deleteAllMessages) {
+ chatCommunitySectionModule.banUserFromCommunity(pubKey, deleteAllMessages);
}
function unbanUserFromCommunity(pubKey) {
diff --git a/ui/app/AppLayouts/Communities/panels/MembersSettingsPanel.qml b/ui/app/AppLayouts/Communities/panels/MembersSettingsPanel.qml
index a56c261601..80e896dd12 100644
--- a/ui/app/AppLayouts/Communities/panels/MembersSettingsPanel.qml
+++ b/ui/app/AppLayouts/Communities/panels/MembersSettingsPanel.qml
@@ -22,7 +22,7 @@ SettingsPage {
signal membershipRequestsClicked()
signal kickUserClicked(string id)
- signal banUserClicked(string id)
+ signal banUserClicked(string id, bool deleteAllMessages)
signal unbanUserClicked(string id)
signal acceptRequestToJoin(string id)
signal declineRequestToJoin(string id)
@@ -193,11 +193,7 @@ SettingsPage {
communityName: root.communityName
- onAccepted: {
- if (mode === KickBanPopup.Mode.Kick)
- root.kickUserClicked(userId)
- else
- root.banUserClicked(userId)
- }
+ onBanUserClicked: root.banUserClicked(userId, deleteAllMessages)
+ onKickUserClicked: root.kickUserClicked(userId)
}
}
diff --git a/ui/app/AppLayouts/Communities/popups/KickBanPopup.qml b/ui/app/AppLayouts/Communities/popups/KickBanPopup.qml
index 8c9ef88726..c3f92c4734 100644
--- a/ui/app/AppLayouts/Communities/popups/KickBanPopup.qml
+++ b/ui/app/AppLayouts/Communities/popups/KickBanPopup.qml
@@ -1,9 +1,11 @@
import QtQuick 2.15
import QtQml.Models 2.15
+import QtQuick.Layouts 1.15
import StatusQ.Controls 0.1
import StatusQ.Core 0.1
import StatusQ.Popups.Dialog 0.1
+import StatusQ.Components 0.1
import utils 1.0
@@ -15,6 +17,9 @@ StatusDialog {
property string communityName: ""
property int mode: KickBanPopup.Mode.Kick
+ signal banUserClicked(bool deleteAllMessages)
+ signal kickUserClicked()
+
enum Mode {
Kick, Ban
}
@@ -25,17 +30,40 @@ StatusDialog {
? qsTr("Kick %1").arg(root.username)
: qsTr("Ban %1").arg(root.username)
- contentItem: StatusBaseText {
+ contentItem: ColumnLayout {
anchors.centerIn: parent
- font.pixelSize: Style.current.primaryTextFontSize
- wrapMode: Text.Wrap
- text: root.mode === KickBanPopup.Mode.Kick
- ? qsTr("Are you sure you kick %1 from %2?")
- .arg(root.username).arg(root.communityName)
- : qsTr("Are you sure you ban %1 from %2?")
- .arg(root.username).arg(root.communityName)
- }
+ StatusBaseText {
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ font.pixelSize: Style.current.primaryTextFontSize
+ wrapMode: Text.Wrap
+
+ text: root.mode === KickBanPopup.Mode.Kick
+ ? qsTr("Are you sure you want to kick %1 from %2?")
+ .arg(root.username).arg(root.communityName)
+ : qsTr("Are you sure you want to ban %1 from %2? This means that they will be kicked from this community and banned from re-joining.")
+ .arg(root.username).arg(root.communityName)
+ }
+
+ RowLayout {
+ visible: root.mode === KickBanPopup.Mode.Ban
+
+ StatusBaseText {
+ Layout.fillWidth: true
+
+ text: qsTr("Delete all messages posted by the user")
+ font.pixelSize: Style.current.primaryTextFontSize
+ }
+
+ StatusSwitch {
+ id: deleteAllMessagesSwitch
+
+ checked: false
+ }
+ }
+ }
footer: StatusDialogFooter {
rightButtons: ObjectModel {
@@ -51,14 +79,17 @@ StatusDialog {
? "CommunityMembers_KickModal_KickButton"
: "CommunityMembers_BanModal_BanButton"
- text: root.mode === KickBanPopup.Mode.Kick ? qsTr("Kick")
- : qsTr("Ban")
+ text: root.mode === KickBanPopup.Mode.Kick ? qsTr("Kick %1").arg(root.username)
+ : qsTr("Ban %1").arg(root.username)
type: StatusBaseButton.Type.Danger
onClicked: {
- root.accept()
+ root.mode === KickBanPopup.Mode.Kick ? root.kickUserClicked()
+ : root.banUserClicked(deleteAllMessagesSwitch.checked)
root.close()
}
}
}
}
+
+ onClosed: deleteAllMessagesSwitch.checked = false
}
diff --git a/ui/app/AppLayouts/Communities/views/CommunityColumnView.qml b/ui/app/AppLayouts/Communities/views/CommunityColumnView.qml
index 479383a4f4..3cec4a8bfd 100644
--- a/ui/app/AppLayouts/Communities/views/CommunityColumnView.qml
+++ b/ui/app/AppLayouts/Communities/views/CommunityColumnView.qml
@@ -72,6 +72,8 @@ Item {
property bool invitationPending: root.store.isMyCommunityRequestPending(communityData.id)
property bool joiningCommunityInProgress: false
+
+ onShowJoinButtonChanged: invitationPending = root.store.isMyCommunityRequestPending(communityData.id)
}
ColumnHeaderPanel {
diff --git a/ui/app/AppLayouts/Communities/views/CommunitySettingsView.qml b/ui/app/AppLayouts/Communities/views/CommunitySettingsView.qml
index 640941ac85..01d0099420 100644
--- a/ui/app/AppLayouts/Communities/views/CommunitySettingsView.qml
+++ b/ui/app/AppLayouts/Communities/views/CommunitySettingsView.qml
@@ -273,7 +273,7 @@ StatusSectionLayout {
communityName: root.community.name
onKickUserClicked: root.rootStore.removeUserFromCommunity(id)
- onBanUserClicked: root.rootStore.banUserFromCommunity(id)
+ onBanUserClicked: root.rootStore.banUserFromCommunity(id, deleteAllMessages)
onUnbanUserClicked: root.rootStore.unbanUserFromCommunity(id)
onAcceptRequestToJoin: root.rootStore.acceptRequestToJoinCommunity(id, root.community.id)
onDeclineRequestToJoin: root.rootStore.declineRequestToJoinCommunity(id, root.community.id)
diff --git a/ui/app/mainui/activitycenter/popups/ActivityCenterPopup.qml b/ui/app/mainui/activitycenter/popups/ActivityCenterPopup.qml
index c53b136563..5b6dcda2d3 100644
--- a/ui/app/mainui/activitycenter/popups/ActivityCenterPopup.qml
+++ b/ui/app/mainui/activitycenter/popups/ActivityCenterPopup.qml
@@ -140,6 +140,10 @@ Popup {
return ownerTokenReceivedNotificationComponent
case ActivityCenterStore.ActivityCenterNotificationType.ShareAccounts:
return shareAccountsNotificationComponent
+ case ActivityCenterStore.ActivityCenterNotificationType.CommunityBanned:
+ return communityBannedNotificationComponent
+ case ActivityCenterStore.ActivityCenterNotificationType.CommunityUnbanned:
+ return communityUnbannedNotificationComponent
default:
return null
}
@@ -236,6 +240,32 @@ Popup {
}
}
+ Component {
+ id: communityBannedNotificationComponent
+
+ ActivityNotificationCommunityBanUnban {
+ banned: true
+ filteredIndex: parent.filteredIndex
+ notification: parent.notification
+ store: root.store
+ activityCenterStore: root.activityCenterStore
+ onCloseActivityCenter: root.close()
+ }
+ }
+
+ Component {
+ id: communityUnbannedNotificationComponent
+
+ ActivityNotificationCommunityBanUnban {
+ banned: false
+ filteredIndex: parent.filteredIndex
+ notification: parent.notification
+ store: root.store
+ activityCenterStore: root.activityCenterStore
+ onCloseActivityCenter: root.close()
+ }
+ }
+
Component {
id: contactRemovedComponent
diff --git a/ui/app/mainui/activitycenter/stores/ActivityCenterStore.qml b/ui/app/mainui/activitycenter/stores/ActivityCenterStore.qml
index 17ab185dd4..a913c2d12b 100644
--- a/ui/app/mainui/activitycenter/stores/ActivityCenterStore.qml
+++ b/ui/app/mainui/activitycenter/stores/ActivityCenterStore.qml
@@ -38,7 +38,9 @@ QtObject {
OwnershipDeclined = 17,
ShareAccounts = 18,
CommunityTokenReceived = 19,
- FirstCommunityTokenReceived = 20
+ FirstCommunityTokenReceived = 20,
+ CommunityBanned = 21,
+ CommunityUnbanned = 22
}
enum ActivityCenterReadType {
diff --git a/ui/app/mainui/activitycenter/views/ActivityNotificationCommunityBanUnban.qml b/ui/app/mainui/activitycenter/views/ActivityNotificationCommunityBanUnban.qml
new file mode 100644
index 0000000000..23c8d87eeb
--- /dev/null
+++ b/ui/app/mainui/activitycenter/views/ActivityNotificationCommunityBanUnban.qml
@@ -0,0 +1,78 @@
+import QtQuick 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 shared 1.0
+import shared.panels 1.0
+import shared.controls 1.0
+import utils 1.0
+
+import "../controls"
+
+ActivityNotificationBase {
+ id: root
+ property bool banned: true
+
+ bodyComponent: RowLayout {
+ width: parent.width
+ height: 50
+ readonly property var community: notification ?
+ root.store.getCommunityDetailsAsJson(notification.communityId) :
+ null
+
+ StatusSmartIdenticon {
+ Layout.preferredWidth: 40
+ Layout.preferredHeight: 40
+ Layout.alignment: Qt.AlignTop
+ Layout.leftMargin: Style.current.padding
+ Layout.topMargin: 2
+
+ asset {
+ width: 24
+ height: width
+ name: "communities"
+ color: root.banned ? "red" : "green"
+ bgWidth: 40
+ bgHeight: 40
+ bgColor: Theme.palette.getColor(asset.color, 0.1)
+ }
+ }
+
+ StatusBaseText {
+ text: root.banned ? qsTr("You were banned from") : qsTr("You've been unbanned from")
+ Layout.alignment: Qt.AlignVCenter
+ font.italic: true
+ color: Theme.palette.baseColor1
+ }
+
+ CommunityBadge {
+ communityName: community ? community.name : ""
+ communityImage: community ? community.image : ""
+ communityColor: community ? community.color : "black"
+ onCommunityNameClicked: root.store.setActiveCommunity(notification.communityId)
+ Layout.alignment: Qt.AlignVCenter
+ Layout.maximumWidth: 190
+ }
+
+ Item {
+ Layout.fillWidth: true
+ }
+ }
+
+ ctaComponent: root.banned ? undefined : visitCommunityCta
+
+ Component {
+ id: visitCommunityCta
+ StatusLinkText {
+ text: qsTr("Visit Community")
+ onClicked: {
+ root.store.setActiveCommunity(notification.communityId)
+ root.closeActivityCenter()
+ }
+ }
+ }
+}
diff --git a/vendor/status-go b/vendor/status-go
index 9b17fd6673..3959948c4c 160000
--- a/vendor/status-go
+++ b/vendor/status-go
@@ -1 +1 @@
-Subproject commit 9b17fd66734f810d465a1e463451260c0c0fd762
+Subproject commit 3959948c4c5ab560ae528c2d331241f2cc94fed1