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.trustStatus,
|
||||||
contactDetails.details.ensVerified,
|
contactDetails.details.ensVerified,
|
||||||
message.discordMessage,
|
message.discordMessage,
|
||||||
resendError = ""
|
resendError = "",
|
||||||
|
message.mentioned
|
||||||
))
|
))
|
||||||
|
|
||||||
method convertToItems*(
|
method convertToItems*(
|
||||||
|
|
|
@ -100,7 +100,8 @@ proc createFetchMoreMessagesItem(self: Module): Item =
|
||||||
senderTrustStatus = TrustStatus.Unknown,
|
senderTrustStatus = TrustStatus.Unknown,
|
||||||
senderEnsVerified = false,
|
senderEnsVerified = false,
|
||||||
DiscordMessage(),
|
DiscordMessage(),
|
||||||
resendError = ""
|
resendError = "",
|
||||||
|
mentioned = false
|
||||||
)
|
)
|
||||||
|
|
||||||
proc createChatIdentifierItem(self: Module): Item =
|
proc createChatIdentifierItem(self: Module): Item =
|
||||||
|
@ -142,7 +143,8 @@ proc createChatIdentifierItem(self: Module): Item =
|
||||||
senderTrustStatus = TrustStatus.Unknown,
|
senderTrustStatus = TrustStatus.Unknown,
|
||||||
senderEnsVerified = false,
|
senderEnsVerified = false,
|
||||||
DiscordMessage(),
|
DiscordMessage(),
|
||||||
resendError = ""
|
resendError = "",
|
||||||
|
mentioned = false
|
||||||
)
|
)
|
||||||
|
|
||||||
proc checkIfMessageLoadedAndScrollToItIfItIs(self: Module) =
|
proc checkIfMessageLoadedAndScrollToItIfItIs(self: Module) =
|
||||||
|
@ -223,7 +225,8 @@ method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: se
|
||||||
sender.details.trustStatus,
|
sender.details.trustStatus,
|
||||||
sender.details.ensVerified,
|
sender.details.ensVerified,
|
||||||
m.discordMessage,
|
m.discordMessage,
|
||||||
resendError = ""
|
resendError = "",
|
||||||
|
m.mentioned
|
||||||
)
|
)
|
||||||
|
|
||||||
for r in reactions:
|
for r in reactions:
|
||||||
|
@ -323,7 +326,8 @@ method messageAdded*(self: Module, message: MessageDto) =
|
||||||
sender.details.trustStatus,
|
sender.details.trustStatus,
|
||||||
sender.details.ensVerified,
|
sender.details.ensVerified,
|
||||||
message.discordMessage,
|
message.discordMessage,
|
||||||
resendError = ""
|
resendError = "",
|
||||||
|
message.mentioned
|
||||||
)
|
)
|
||||||
|
|
||||||
self.view.model().insertItemBasedOnClock(item)
|
self.view.model().insertItemBasedOnClock(item)
|
||||||
|
@ -609,7 +613,8 @@ method getMessageById*(self: Module, messageId: string): message_item.Item =
|
||||||
sender.details.trustStatus,
|
sender.details.trustStatus,
|
||||||
sender.details.ensVerified,
|
sender.details.ensVerified,
|
||||||
m.discordMessage,
|
m.discordMessage,
|
||||||
resendError = ""
|
resendError = "",
|
||||||
|
m.mentioned
|
||||||
)
|
)
|
||||||
return item
|
return item
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -198,7 +198,8 @@ proc buildPinnedMessageItem(self: Module, messageId: string, actionInitiatedBy:
|
||||||
contactDetails.details.trustStatus,
|
contactDetails.details.trustStatus,
|
||||||
contactDetails.details.ensVerified,
|
contactDetails.details.ensVerified,
|
||||||
m.discordMessage,
|
m.discordMessage,
|
||||||
resendError = ""
|
resendError = "",
|
||||||
|
m.mentioned
|
||||||
)
|
)
|
||||||
item.pinned = true
|
item.pinned = true
|
||||||
item.pinnedBy = actionInitiatedBy
|
item.pinnedBy = actionInitiatedBy
|
||||||
|
|
|
@ -43,6 +43,7 @@ type
|
||||||
senderEnsVerified: bool
|
senderEnsVerified: bool
|
||||||
messageAttachments: seq[string]
|
messageAttachments: seq[string]
|
||||||
resendError: string
|
resendError: string
|
||||||
|
mentioned: bool
|
||||||
|
|
||||||
proc initItem*(
|
proc initItem*(
|
||||||
id,
|
id,
|
||||||
|
@ -72,7 +73,8 @@ proc initItem*(
|
||||||
senderTrustStatus: TrustStatus,
|
senderTrustStatus: TrustStatus,
|
||||||
senderEnsVerified: bool,
|
senderEnsVerified: bool,
|
||||||
discordMessage: DiscordMessage,
|
discordMessage: DiscordMessage,
|
||||||
resendError: string
|
resendError: string,
|
||||||
|
mentioned: bool
|
||||||
): Item =
|
): Item =
|
||||||
result = Item()
|
result = Item()
|
||||||
result.id = id
|
result.id = id
|
||||||
|
@ -109,6 +111,7 @@ proc initItem*(
|
||||||
result.senderEnsVerified = senderEnsVerified
|
result.senderEnsVerified = senderEnsVerified
|
||||||
result.messageAttachments = @[]
|
result.messageAttachments = @[]
|
||||||
result.resendError = resendError
|
result.resendError = resendError
|
||||||
|
result.mentioned = mentioned
|
||||||
|
|
||||||
if ContentType.DiscordMessage == contentType:
|
if ContentType.DiscordMessage == contentType:
|
||||||
if result.messageText == "":
|
if result.messageText == "":
|
||||||
|
@ -157,7 +160,8 @@ proc initNewMessagesMarkerItem*(timestamp: int64): Item =
|
||||||
senderTrustStatus = TrustStatus.Unknown,
|
senderTrustStatus = TrustStatus.Unknown,
|
||||||
senderEnsVerified = false,
|
senderEnsVerified = false,
|
||||||
discordMessage = DiscordMessage(),
|
discordMessage = DiscordMessage(),
|
||||||
resendError = ""
|
resendError = "",
|
||||||
|
mentioned = false
|
||||||
)
|
)
|
||||||
|
|
||||||
proc `$`*(self: Item): string =
|
proc `$`*(self: Item): string =
|
||||||
|
@ -401,3 +405,8 @@ proc gapTo*(self: Item): int64 {.inline.} =
|
||||||
proc `gapTo=`*(self: Item, value: int64) {.inline.} =
|
proc `gapTo=`*(self: Item, value: int64) {.inline.} =
|
||||||
self.gapTo = value
|
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:
|
QtProperty[bool] amISender:
|
||||||
read = 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
|
proc senderIcon*(self: MessageItem): string {.slot.} = result = ?.self.messageItem.senderIcon
|
||||||
QtProperty[string] senderIcon:
|
QtProperty[string] senderIcon:
|
||||||
read = senderIcon
|
read = senderIcon
|
||||||
|
|
|
@ -43,6 +43,7 @@ type
|
||||||
SenderEnsVerified
|
SenderEnsVerified
|
||||||
MessageAttachments
|
MessageAttachments
|
||||||
ResendError
|
ResendError
|
||||||
|
Mentioned
|
||||||
|
|
||||||
QtObject:
|
QtObject:
|
||||||
type
|
type
|
||||||
|
@ -103,6 +104,7 @@ QtObject:
|
||||||
ModelRole.Seen.int:"seen",
|
ModelRole.Seen.int:"seen",
|
||||||
ModelRole.OutgoingStatus.int:"outgoingStatus",
|
ModelRole.OutgoingStatus.int:"outgoingStatus",
|
||||||
ModelRole.ResendError.int:"resendError",
|
ModelRole.ResendError.int:"resendError",
|
||||||
|
ModelRole.Mentioned.int:"mentioned",
|
||||||
ModelRole.MessageText.int:"messageText",
|
ModelRole.MessageText.int:"messageText",
|
||||||
ModelRole.MessageImage.int:"messageImage",
|
ModelRole.MessageImage.int:"messageImage",
|
||||||
ModelRole.MessageContainsMentions.int:"messageContainsMentions",
|
ModelRole.MessageContainsMentions.int:"messageContainsMentions",
|
||||||
|
@ -173,6 +175,8 @@ QtObject:
|
||||||
result = newQVariant(item.outgoingStatus)
|
result = newQVariant(item.outgoingStatus)
|
||||||
of ModelRole.ResendError:
|
of ModelRole.ResendError:
|
||||||
result = newQVariant(item.resendError)
|
result = newQVariant(item.resendError)
|
||||||
|
of ModelRole.Mentioned:
|
||||||
|
result = newQVariant(item.mentioned)
|
||||||
of ModelRole.MessageText:
|
of ModelRole.MessageText:
|
||||||
result = newQVariant(item.messageText)
|
result = newQVariant(item.messageText)
|
||||||
of ModelRole.MessageImage:
|
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 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 =
|
proc isCompressedPubKey*(strPubKey: string): bool =
|
||||||
return strPubKey.startsWith("zQ3") and allCharsInSet(strPubKey, CompressedKeyChars)
|
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 =
|
proc parseAddress*(strAddress: string): Address =
|
||||||
var hexAddressValue: Address
|
var hexAddressValue: Address
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import sequtils, strutils, sugar, re
|
import sequtils, strutils, sugar, re
|
||||||
import ../service/contacts/dto/contacts
|
import ../service/contacts/dto/contacts
|
||||||
|
from conversion import SystemTagMapping
|
||||||
|
|
||||||
proc replaceMentionsWithPubKeys*(allKnownContacts: seq[ContactsDto], message: string): string =
|
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})
|
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)
|
let nameMentions = findAll(message, namePattern)
|
||||||
var updatedMessage = message
|
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 following lines we're free to compare to `x.userDefaultDisplayName()` cause that's actually what we're displaying
|
||||||
# in the mentions suggestion list.
|
# in the mentions suggestion list.
|
||||||
for mention in aliasMentions:
|
for mention in aliasMentions:
|
||||||
|
|
|
@ -4,6 +4,8 @@ import json, strutils
|
||||||
|
|
||||||
include ../../../common/json_utils
|
include ../../../common/json_utils
|
||||||
|
|
||||||
|
from ../../../common/conversion import SystemTagMapping
|
||||||
|
|
||||||
const PARSED_TEXT_TYPE_PARAGRAPH* = "paragraph"
|
const PARSED_TEXT_TYPE_PARAGRAPH* = "paragraph"
|
||||||
const PARSED_TEXT_TYPE_BLOCKQUOTE* = "blockquote"
|
const PARSED_TEXT_TYPE_BLOCKQUOTE* = "blockquote"
|
||||||
const PARSED_TEXT_TYPE_CODEBLOCK* = "codeblock"
|
const PARSED_TEXT_TYPE_CODEBLOCK* = "codeblock"
|
||||||
|
@ -108,6 +110,7 @@ type MessageDto* = object
|
||||||
deleted*: bool
|
deleted*: bool
|
||||||
deletedForMe*: bool
|
deletedForMe*: bool
|
||||||
transactionParameters*: TransactionParameters
|
transactionParameters*: TransactionParameters
|
||||||
|
mentioned*: bool
|
||||||
|
|
||||||
proc toParsedText*(jsonObj: JsonNode): ParsedText =
|
proc toParsedText*(jsonObj: JsonNode): ParsedText =
|
||||||
result = ParsedText()
|
result = ParsedText()
|
||||||
|
@ -213,6 +216,7 @@ proc toMessageDto*(jsonObj: JsonNode): MessageDto =
|
||||||
discard jsonObj.getProp("editedAt", result.editedAt)
|
discard jsonObj.getProp("editedAt", result.editedAt)
|
||||||
discard jsonObj.getProp("deleted", result.deleted)
|
discard jsonObj.getProp("deleted", result.deleted)
|
||||||
discard jsonObj.getProp("deletedForMe", result.deletedForMe)
|
discard jsonObj.getProp("deletedForMe", result.deletedForMe)
|
||||||
|
discard jsonObj.getProp("mentioned", result.mentioned)
|
||||||
|
|
||||||
var quotedMessageObj: JsonNode
|
var quotedMessageObj: JsonNode
|
||||||
if(jsonObj.getProp("quotedMessage", quotedMessageObj)):
|
if(jsonObj.getProp("quotedMessage", quotedMessageObj)):
|
||||||
|
@ -259,7 +263,13 @@ proc isPersonalMention*(self: MessageDto, publicKey: string): bool =
|
||||||
return false
|
return false
|
||||||
|
|
||||||
proc isGlobalMention*(self: MessageDto): bool =
|
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
|
return false
|
||||||
|
|
||||||
proc mentionedUsersPks*(self: MessageDto): seq[string] =
|
proc mentionedUsersPks*(self: MessageDto): seq[string] =
|
||||||
|
|
|
@ -703,6 +703,14 @@ proc renderInline(self: Service, parsedText: ParsedText): string =
|
||||||
result = fmt(" <strong><em>{value}</em></strong> ")
|
result = fmt(" <strong><em>{value}</em></strong> ")
|
||||||
of PARSED_TEXT_CHILD_TYPE_MENTION:
|
of PARSED_TEXT_CHILD_TYPE_MENTION:
|
||||||
var id = value
|
var id = value
|
||||||
|
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):
|
if isCompressedPubKey(id):
|
||||||
id = status_accounts.decompressPk(id).result
|
id = status_accounts.decompressPk(id).result
|
||||||
let contactDto = self.contactService.getContactById(id)
|
let contactDto = self.contactService.getContactById(id)
|
||||||
|
|
|
@ -13,6 +13,7 @@ Item {
|
||||||
property int cursorPosition: 0
|
property int cursorPosition: 0
|
||||||
property int lastAtPosition: 0
|
property int lastAtPosition: 0
|
||||||
property var property: ([])
|
property var property: ([])
|
||||||
|
property bool addSystemSuggestions: false
|
||||||
|
|
||||||
onFilterChanged: invalidateFilter()
|
onFilterChanged: invalidateFilter()
|
||||||
onPropertyChanged: invalidateFilter()
|
onPropertyChanged: invalidateFilter()
|
||||||
|
@ -78,6 +79,15 @@ Item {
|
||||||
filterModel.append(item)
|
filterModel.append(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const everyoneItem = {
|
||||||
|
publicKey: "0x00001",
|
||||||
|
name: "@everyone",
|
||||||
|
icon: ""
|
||||||
|
}
|
||||||
|
if (suggestionsPanelRoot.addSystemSuggestions && isAcceptedItem(filter, everyoneItem)) {
|
||||||
|
filterModel.append(everyoneItem)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFilter() {
|
function getFilter() {
|
||||||
|
|
|
@ -190,6 +190,7 @@ ColumnLayout {
|
||||||
isActiveChannel: root.isActiveChannel
|
isActiveChannel: root.isActiveChannel
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
chatType: chatContentModule? chatContentModule.chatDetails.type : Constants.chatType.unknown
|
chatType: chatContentModule? chatContentModule.chatDetails.type : Constants.chatType.unknown
|
||||||
|
suggestions.suggestionFilter.addSystemSuggestions: chatType == Constants.chatType.communityChat
|
||||||
|
|
||||||
Binding on chatInputPlaceholder {
|
Binding on chatInputPlaceholder {
|
||||||
when: root.isBlocked
|
when: root.isBlocked
|
||||||
|
|
|
@ -276,7 +276,7 @@ Item {
|
||||||
linkUrls: model.links
|
linkUrls: model.links
|
||||||
messageAttachments: model.messageAttachments
|
messageAttachments: model.messageAttachments
|
||||||
transactionParams: model.transactionParameters
|
transactionParams: model.transactionParameters
|
||||||
hasMention: model.mentionedUsersPks.split(" ").includes(root.rootStore.userProfileInst.pubKey)
|
hasMention: model.mentioned
|
||||||
|
|
||||||
gapFrom: model.gapFrom
|
gapFrom: model.gapFrom
|
||||||
gapTo: model.gapTo
|
gapTo: model.gapTo
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 4a0eb56574a3cfd8f5732f0069cc62cb04f9dd29
|
Subproject commit b4bdfd3df6cf5fb91ab2d0e9f3b38e8d1b9703e5
|
Loading…
Reference in New Issue