feat: introduce ability to @everyone
Closes #8479 This needs: status-im/status-go#3026
This commit is contained in:
parent
bf324f273a
commit
865ed32deb
|
@ -98,7 +98,8 @@ proc createMessageItemFromDto(self: Module, message: MessageDto, chatDetails: Ch
|
|||
contactDetails.details.trustStatus,
|
||||
contactDetails.details.ensVerified,
|
||||
message.discordMessage,
|
||||
resendError = ""
|
||||
resendError = "",
|
||||
message.mentioned
|
||||
))
|
||||
|
||||
method convertToItems*(
|
||||
|
@ -257,4 +258,4 @@ method getChatDetailsAsJson*(self: Module, chatId: string): string =
|
|||
jsonObject["icon"] = %* chatDto.icon
|
||||
jsonObject["color"] = %* chatDto.color
|
||||
jsonObject["emoji"] = %* chatDto.emoji
|
||||
return $jsonObject
|
||||
return $jsonObject
|
||||
|
|
|
@ -100,7 +100,8 @@ proc createFetchMoreMessagesItem(self: Module): Item =
|
|||
senderTrustStatus = TrustStatus.Unknown,
|
||||
senderEnsVerified = false,
|
||||
DiscordMessage(),
|
||||
resendError = ""
|
||||
resendError = "",
|
||||
mentioned = false
|
||||
)
|
||||
|
||||
proc createChatIdentifierItem(self: Module): Item =
|
||||
|
@ -142,7 +143,8 @@ proc createChatIdentifierItem(self: Module): Item =
|
|||
senderTrustStatus = TrustStatus.Unknown,
|
||||
senderEnsVerified = false,
|
||||
DiscordMessage(),
|
||||
resendError = ""
|
||||
resendError = "",
|
||||
mentioned = false
|
||||
)
|
||||
|
||||
proc checkIfMessageLoadedAndScrollToItIfItIs(self: Module) =
|
||||
|
@ -223,7 +225,8 @@ method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: se
|
|||
sender.details.trustStatus,
|
||||
sender.details.ensVerified,
|
||||
m.discordMessage,
|
||||
resendError = ""
|
||||
resendError = "",
|
||||
m.mentioned
|
||||
)
|
||||
|
||||
for r in reactions:
|
||||
|
@ -323,7 +326,8 @@ method messageAdded*(self: Module, message: MessageDto) =
|
|||
sender.details.trustStatus,
|
||||
sender.details.ensVerified,
|
||||
message.discordMessage,
|
||||
resendError = ""
|
||||
resendError = "",
|
||||
message.mentioned
|
||||
)
|
||||
|
||||
self.view.model().insertItemBasedOnClock(item)
|
||||
|
@ -609,7 +613,8 @@ method getMessageById*(self: Module, messageId: string): message_item.Item =
|
|||
sender.details.trustStatus,
|
||||
sender.details.ensVerified,
|
||||
m.discordMessage,
|
||||
resendError = ""
|
||||
resendError = "",
|
||||
m.mentioned
|
||||
)
|
||||
return item
|
||||
return nil
|
||||
|
|
|
@ -198,7 +198,8 @@ proc buildPinnedMessageItem(self: Module, messageId: string, actionInitiatedBy:
|
|||
contactDetails.details.trustStatus,
|
||||
contactDetails.details.ensVerified,
|
||||
m.discordMessage,
|
||||
resendError = ""
|
||||
resendError = "",
|
||||
m.mentioned
|
||||
)
|
||||
item.pinned = true
|
||||
item.pinnedBy = actionInitiatedBy
|
||||
|
|
|
@ -43,6 +43,7 @@ type
|
|||
senderEnsVerified: bool
|
||||
messageAttachments: seq[string]
|
||||
resendError: string
|
||||
mentioned: bool
|
||||
|
||||
proc initItem*(
|
||||
id,
|
||||
|
@ -72,7 +73,8 @@ proc initItem*(
|
|||
senderTrustStatus: TrustStatus,
|
||||
senderEnsVerified: bool,
|
||||
discordMessage: DiscordMessage,
|
||||
resendError: string
|
||||
resendError: string,
|
||||
mentioned: bool
|
||||
): Item =
|
||||
result = Item()
|
||||
result.id = id
|
||||
|
@ -109,6 +111,7 @@ proc initItem*(
|
|||
result.senderEnsVerified = senderEnsVerified
|
||||
result.messageAttachments = @[]
|
||||
result.resendError = resendError
|
||||
result.mentioned = mentioned
|
||||
|
||||
if ContentType.DiscordMessage == contentType:
|
||||
if result.messageText == "":
|
||||
|
@ -157,7 +160,8 @@ proc initNewMessagesMarkerItem*(timestamp: int64): Item =
|
|||
senderTrustStatus = TrustStatus.Unknown,
|
||||
senderEnsVerified = false,
|
||||
discordMessage = DiscordMessage(),
|
||||
resendError = ""
|
||||
resendError = "",
|
||||
mentioned = false
|
||||
)
|
||||
|
||||
proc `$`*(self: Item): string =
|
||||
|
@ -401,3 +405,8 @@ proc gapTo*(self: Item): int64 {.inline.} =
|
|||
proc `gapTo=`*(self: Item, value: int64) {.inline.} =
|
||||
self.gapTo = value
|
||||
|
||||
proc mentioned*(self: Item): bool {.inline.} =
|
||||
self.mentioned
|
||||
|
||||
proc `mentioned=`*(self: Item, value: bool) {.inline.} =
|
||||
self.mentioned = value
|
||||
|
|
|
@ -57,6 +57,10 @@ QtObject:
|
|||
QtProperty[bool] amISender:
|
||||
read = amISender
|
||||
|
||||
proc mentioned*(self: MessageItem): bool {.slot.} = result = ?.self.messageItem.mentioned
|
||||
QtProperty[bool] mentioned:
|
||||
read = mentioned
|
||||
|
||||
proc senderIcon*(self: MessageItem): string {.slot.} = result = ?.self.messageItem.senderIcon
|
||||
QtProperty[string] senderIcon:
|
||||
read = senderIcon
|
||||
|
|
|
@ -43,6 +43,7 @@ type
|
|||
SenderEnsVerified
|
||||
MessageAttachments
|
||||
ResendError
|
||||
Mentioned
|
||||
|
||||
QtObject:
|
||||
type
|
||||
|
@ -103,6 +104,7 @@ QtObject:
|
|||
ModelRole.Seen.int:"seen",
|
||||
ModelRole.OutgoingStatus.int:"outgoingStatus",
|
||||
ModelRole.ResendError.int:"resendError",
|
||||
ModelRole.Mentioned.int:"mentioned",
|
||||
ModelRole.MessageText.int:"messageText",
|
||||
ModelRole.MessageImage.int:"messageImage",
|
||||
ModelRole.MessageContainsMentions.int:"messageContainsMentions",
|
||||
|
@ -173,6 +175,8 @@ QtObject:
|
|||
result = newQVariant(item.outgoingStatus)
|
||||
of ModelRole.ResendError:
|
||||
result = newQVariant(item.resendError)
|
||||
of ModelRole.Mentioned:
|
||||
result = newQVariant(item.mentioned)
|
||||
of ModelRole.MessageText:
|
||||
result = newQVariant(item.messageText)
|
||||
of ModelRole.MessageImage:
|
||||
|
|
|
@ -3,9 +3,16 @@ from web3 import Address, fromHex
|
|||
|
||||
const CompressedKeyChars* = {'0'..'9', 'A','B','C','D','E','F','G','H','J','K','L','M','N','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}
|
||||
|
||||
const SystemMentionChars* = {'0'..'9', 'x'}
|
||||
|
||||
const SystemTagMapping* = [("@everyone", "@0x00001")]
|
||||
|
||||
proc isCompressedPubKey*(strPubKey: string): bool =
|
||||
return strPubKey.startsWith("zQ3") and allCharsInSet(strPubKey, CompressedKeyChars)
|
||||
|
||||
proc isSystemMention*(mention: string) : bool =
|
||||
mention.startsWith("0x") and allCharsInSet(mention, SystemMentionChars)
|
||||
|
||||
proc parseAddress*(strAddress: string): Address =
|
||||
var hexAddressValue: Address
|
||||
try:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import sequtils, strutils, sugar, re
|
||||
import ../service/contacts/dto/contacts
|
||||
from conversion import SystemTagMapping
|
||||
|
||||
proc replaceMentionsWithPubKeys*(allKnownContacts: seq[ContactsDto], message: string): string =
|
||||
let aliasPattern = re(r"(@[A-z][a-z]+ [A-z][a-z]* [A-z][a-z]*)", flags = {reStudy, reIgnoreCase})
|
||||
|
@ -11,6 +12,10 @@ proc replaceMentionsWithPubKeys*(allKnownContacts: seq[ContactsDto], message: st
|
|||
let nameMentions = findAll(message, namePattern)
|
||||
var updatedMessage = message
|
||||
|
||||
# replace system tag with system ID
|
||||
for pair in SystemTagMapping:
|
||||
updatedMessage = updatedMessage.replaceWord(pair[0], pair[1])
|
||||
|
||||
# In the following lines we're free to compare to `x.userDefaultDisplayName()` cause that's actually what we're displaying
|
||||
# in the mentions suggestion list.
|
||||
for mention in aliasMentions:
|
||||
|
|
|
@ -4,6 +4,8 @@ import json, strutils
|
|||
|
||||
include ../../../common/json_utils
|
||||
|
||||
from ../../../common/conversion import SystemTagMapping
|
||||
|
||||
const PARSED_TEXT_TYPE_PARAGRAPH* = "paragraph"
|
||||
const PARSED_TEXT_TYPE_BLOCKQUOTE* = "blockquote"
|
||||
const PARSED_TEXT_TYPE_CODEBLOCK* = "codeblock"
|
||||
|
@ -108,6 +110,7 @@ type MessageDto* = object
|
|||
deleted*: bool
|
||||
deletedForMe*: bool
|
||||
transactionParameters*: TransactionParameters
|
||||
mentioned*: bool
|
||||
|
||||
proc toParsedText*(jsonObj: JsonNode): ParsedText =
|
||||
result = ParsedText()
|
||||
|
@ -213,6 +216,7 @@ proc toMessageDto*(jsonObj: JsonNode): MessageDto =
|
|||
discard jsonObj.getProp("editedAt", result.editedAt)
|
||||
discard jsonObj.getProp("deleted", result.deleted)
|
||||
discard jsonObj.getProp("deletedForMe", result.deletedForMe)
|
||||
discard jsonObj.getProp("mentioned", result.mentioned)
|
||||
|
||||
var quotedMessageObj: JsonNode
|
||||
if(jsonObj.getProp("quotedMessage", quotedMessageObj)):
|
||||
|
@ -259,7 +263,13 @@ proc isPersonalMention*(self: MessageDto, publicKey: string): bool =
|
|||
return false
|
||||
|
||||
proc isGlobalMention*(self: MessageDto): bool =
|
||||
# TODO: we should check here if message contains global mention.
|
||||
for pText in self.parsedText:
|
||||
for child in pText.children:
|
||||
if child.type == PARSED_TEXT_CHILD_TYPE_MENTION:
|
||||
for pair in SystemTagMapping:
|
||||
if child.literal.contains(pair[1]):
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
proc mentionedUsersPks*(self: MessageDto): seq[string] =
|
||||
|
|
|
@ -703,10 +703,18 @@ proc renderInline(self: Service, parsedText: ParsedText): string =
|
|||
result = fmt(" <strong><em>{value}</em></strong> ")
|
||||
of PARSED_TEXT_CHILD_TYPE_MENTION:
|
||||
var id = value
|
||||
if isCompressedPubKey(id):
|
||||
id = status_accounts.decompressPk(id).result
|
||||
let contactDto = self.contactService.getContactById(id)
|
||||
result = fmt("<a href=\"//{id}\" class=\"mention\">{contactDto.userDefaultDisplayName()}</a>")
|
||||
if isSystemMention(id):
|
||||
var tag = id
|
||||
for pair in SystemTagMapping:
|
||||
if pair[1] == "@" & id:
|
||||
tag = pair[0]
|
||||
break
|
||||
result = fmt("<a href=\"\" class=\"mention\">{tag}</a>")
|
||||
else:
|
||||
if isCompressedPubKey(id):
|
||||
id = status_accounts.decompressPk(id).result
|
||||
let contactDto = self.contactService.getContactById(id)
|
||||
result = fmt("<a href=\"//{id}\" class=\"mention\">{contactDto.userDefaultDisplayName()}</a>")
|
||||
of PARSED_TEXT_CHILD_TYPE_STATUS_TAG:
|
||||
result = fmt("<a href=\"#{value}\" class=\"status-tag\">#{value}</a>")
|
||||
of PARSED_TEXT_CHILD_TYPE_DEL:
|
||||
|
|
|
@ -13,6 +13,7 @@ Item {
|
|||
property int cursorPosition: 0
|
||||
property int lastAtPosition: 0
|
||||
property var property: ([])
|
||||
property bool addSystemSuggestions: false
|
||||
|
||||
onFilterChanged: invalidateFilter()
|
||||
onPropertyChanged: invalidateFilter()
|
||||
|
@ -78,6 +79,15 @@ Item {
|
|||
filterModel.append(item)
|
||||
}
|
||||
}
|
||||
|
||||
const everyoneItem = {
|
||||
publicKey: "0x00001",
|
||||
name: "@everyone",
|
||||
icon: ""
|
||||
}
|
||||
if (suggestionsPanelRoot.addSystemSuggestions && isAcceptedItem(filter, everyoneItem)) {
|
||||
filterModel.append(everyoneItem)
|
||||
}
|
||||
}
|
||||
|
||||
function getFilter() {
|
||||
|
|
|
@ -190,6 +190,7 @@ ColumnLayout {
|
|||
isActiveChannel: root.isActiveChannel
|
||||
anchors.bottom: parent.bottom
|
||||
chatType: chatContentModule? chatContentModule.chatDetails.type : Constants.chatType.unknown
|
||||
suggestions.suggestionFilter.addSystemSuggestions: chatType == Constants.chatType.communityChat
|
||||
|
||||
Binding on chatInputPlaceholder {
|
||||
when: root.isBlocked
|
||||
|
|
|
@ -276,7 +276,7 @@ Item {
|
|||
linkUrls: model.links
|
||||
messageAttachments: model.messageAttachments
|
||||
transactionParams: model.transactionParameters
|
||||
hasMention: model.mentionedUsersPks.split(" ").includes(root.rootStore.userProfileInst.pubKey)
|
||||
hasMention: model.mentioned
|
||||
|
||||
gapFrom: model.gapFrom
|
||||
gapTo: model.gapTo
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 4a0eb56574a3cfd8f5732f0069cc62cb04f9dd29
|
||||
Subproject commit b4bdfd3df6cf5fb91ab2d0e9f3b38e8d1b9703e5
|
Loading…
Reference in New Issue