fix(@desktop/chat): mention suggestion list fixed
This commit is contained in:
parent
485d6a370d
commit
aa6036b78b
|
@ -0,0 +1,35 @@
|
|||
import sequtils, strutils, sugar, re
|
||||
import ../service/contacts/dto/contacts
|
||||
|
||||
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 ensPattern = re(r"(@\w+(?=(\.stateofus)?\.eth))", flags = {reStudy, reIgnoreCase})
|
||||
let namePattern = re(r"(@\w+)", flags = {reStudy, reIgnoreCase})
|
||||
|
||||
let aliasMentions = findAll(message, aliasPattern)
|
||||
let ensMentions = findAll(message, ensPattern)
|
||||
let nameMentions = findAll(message, namePattern)
|
||||
var updatedMessage = message
|
||||
|
||||
# In the following lines we're free to compare to `x.userNameOrAlias()` cause that's actually what we're displaying
|
||||
# in the mentions suggestion list.
|
||||
for mention in aliasMentions:
|
||||
let listOfMatched = allKnownContacts.filter(x => "@" & x.userNameOrAlias().toLowerAscii == mention.toLowerAscii)
|
||||
echo "EX1: mention: ", mention, " list: ", repr(listOfMatched)
|
||||
if(listOfMatched.len > 0):
|
||||
updatedMessage = updatedMessage.replaceWord(mention, '@' & listOfMatched[0].id)
|
||||
|
||||
for mention in ensMentions:
|
||||
let listOfMatched = allKnownContacts.filter(x => "@" & x.userNameOrAlias().toLowerAscii == mention.toLowerAscii)
|
||||
echo "EX2: mention: ", mention, " list: ", repr(listOfMatched)
|
||||
if(listOfMatched.len > 0):
|
||||
updatedMessage = updatedMessage.replaceWord(mention, '@' & listOfMatched[0].id)
|
||||
|
||||
for mention in nameMentions:
|
||||
let listOfMatched = allKnownContacts.filter(x => x.userNameOrAlias().toLowerAscii == mention.toLowerAscii or
|
||||
"@" & x.userNameOrAlias().toLowerAscii == mention.toLowerAscii)
|
||||
echo "EX3: mention: ", mention, " list: ", repr(listOfMatched)
|
||||
if(listOfMatched.len > 0):
|
||||
updatedMessage = updatedMessage.replaceWord(mention, '@' & listOfMatched[0].id)
|
||||
|
||||
return updatedMessage
|
|
@ -10,6 +10,7 @@ import ../../../app/global/global_singleton
|
|||
import ../../../app/core/eventemitter
|
||||
import ../../../constants
|
||||
|
||||
import ../../common/message as message_common
|
||||
from ../../common/account_constants import ZERO_ADDRESS
|
||||
|
||||
export chat_dto
|
||||
|
@ -271,9 +272,12 @@ QtObject:
|
|||
preferredUsername: string = "",
|
||||
communityId: string = "") =
|
||||
try:
|
||||
let allKnownContacts = self.contactService.getContacts()
|
||||
let processedMsg = message_common.replaceMentionsWithPubKeys(allKnownContacts, msg)
|
||||
|
||||
let response = status_chat.sendChatMessage(
|
||||
chatId,
|
||||
msg,
|
||||
processedMsg,
|
||||
replyTo,
|
||||
contentType,
|
||||
preferredUsername,
|
||||
|
|
|
@ -13,6 +13,8 @@ import ../chat/dto/chat as chat_dto
|
|||
import ./dto/pinned_message_update as pinned_msg_update_dto
|
||||
import ./dto/removed_message as removed_msg_dto
|
||||
|
||||
import ../../common/message as message_common
|
||||
|
||||
export message_dto
|
||||
export pinned_msg_dto
|
||||
export reaction_dto
|
||||
|
@ -652,9 +654,12 @@ proc deleteMessage*(self: Service, messageId: string) =
|
|||
except Exception as e:
|
||||
error "error: ", methodName="deleteMessage", errName = e.name, errDesription = e.msg
|
||||
|
||||
proc editMessage*(self: Service, messageId: string, updatedMsg: string) =
|
||||
proc editMessage*(self: Service, messageId: string, msg: string) =
|
||||
try:
|
||||
let response = status_go.editMessage(messageId, updatedMsg)
|
||||
let allKnownContacts = self.contactService.getContacts()
|
||||
let processedMsg = message_common.replaceMentionsWithPubKeys(allKnownContacts, msg)
|
||||
|
||||
let response = status_go.editMessage(messageId, processedMsg)
|
||||
|
||||
var messagesArr: JsonNode
|
||||
var messages: seq[MessageDto]
|
||||
|
|
|
@ -33,7 +33,7 @@ import shared.panels 1.0
|
|||
Rectangle {
|
||||
id: container
|
||||
|
||||
property QtObject model
|
||||
property var model
|
||||
property Item delegate
|
||||
property alias suggestionsModel: filterItem.model
|
||||
property alias filter: filterItem.filter
|
||||
|
@ -193,8 +193,8 @@ Rectangle {
|
|||
anchors.leftMargin: Style.current.smallPadding
|
||||
image.width: 32
|
||||
image.height: 32
|
||||
image.source: model.identicon
|
||||
image.isIdenticon: true
|
||||
image.source: model.icon
|
||||
image.isIdenticon: model.isIdenticon
|
||||
}
|
||||
|
||||
StyledText {
|
||||
|
|
|
@ -2,11 +2,11 @@ import QtQuick 2.13
|
|||
import utils 1.0
|
||||
|
||||
Item {
|
||||
id: component
|
||||
id: suggestionsPanelRoot
|
||||
property alias model: filterModel
|
||||
|
||||
property string formattedFilter
|
||||
property QtObject sourceModel: undefined
|
||||
property var sourceModel
|
||||
property string filter: ""
|
||||
property int cursorPosition: 0
|
||||
property int lastAtPosition: 0
|
||||
|
@ -17,6 +17,23 @@ Item {
|
|||
onSourceModelChanged: invalidateFilter()
|
||||
Component.onCompleted: invalidateFilter()
|
||||
|
||||
ListView {
|
||||
// This is a fake list (invisible), used just for the sake of accessing items of the `sourceModel`
|
||||
// without exposing explicit methods from the model which would return item detail.
|
||||
// In general the whole thing about preparing/displaying suggestion panel and list there should
|
||||
// be handled in a much better way, at least using `ListView` and `DelegateModel` which will
|
||||
// filter out the list instead doing all that manually here.
|
||||
id: sourceModelList
|
||||
visible: false
|
||||
model: suggestionsPanelRoot.sourceModel
|
||||
delegate: Item {
|
||||
property string publicKey: model.id
|
||||
property string name: model.name
|
||||
property string icon: model.icon
|
||||
property bool isIdenticon: model.isIdenticon
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: filterModel
|
||||
}
|
||||
|
@ -43,14 +60,13 @@ Item {
|
|||
|
||||
const all = shouldShowAll(filter)
|
||||
|
||||
for (var i = 0; i < sourceModel.rowCount(); ++i) {
|
||||
const publicKey = sourceModel.rowData(i, "publicKey");
|
||||
for (var i = 0; i < sourceModelList.count; ++i) {
|
||||
let listItem = sourceModelList.itemAtIndex(i)
|
||||
const item = {
|
||||
alias: sourceModel.rowData(i, "alias"),
|
||||
userName: sourceModel.rowData(i, "userName"),
|
||||
publicKey: publicKey,
|
||||
identicon: Global.getProfileImage(publicKey, false, false) || sourceModel.rowData(i, "identicon"),
|
||||
localName: sourceModel.rowData(i, "localName")
|
||||
publicKey: listItem.publicKey,
|
||||
name: listItem.name,
|
||||
icon: listItem.icon,
|
||||
isIdenticon: listItem.isIdenticon
|
||||
}
|
||||
if (all || isAcceptedItem(filter, item)) {
|
||||
filterModel.append(item)
|
||||
|
@ -63,9 +79,7 @@ Item {
|
|||
return
|
||||
}
|
||||
|
||||
// Not Refactored Yet
|
||||
return ""
|
||||
// return chatsModel.plainText(this.filter)
|
||||
return globalUtils.plainText(this.filter)
|
||||
}
|
||||
|
||||
function shouldShowAll(filter) {
|
||||
|
@ -92,7 +106,7 @@ Item {
|
|||
|
||||
let filterWithoutAt = filter.substring(this.lastAtPosition + 1, this.cursorPosition)
|
||||
filterWithoutAt = filterWithoutAt.replace(/\*/g, "")
|
||||
component.formattedFilter = filterWithoutAt
|
||||
suggestionsPanelRoot.formattedFilter = filterWithoutAt
|
||||
|
||||
return !properties.every(p => item[p].toLowerCase().match(filterWithoutAt.toLowerCase()) === null)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import QtQuick 2.13
|
||||
|
||||
QtObject {
|
||||
id: root
|
||||
|
||||
property var usersModule
|
||||
property var usersModel
|
||||
|
||||
onUsersModuleChanged: {
|
||||
if(!usersModule)
|
||||
return
|
||||
root.usersModel = usersModule.model
|
||||
}
|
||||
}
|
|
@ -31,6 +31,12 @@ ColumnLayout {
|
|||
property var chatContentModule
|
||||
property var rootStore
|
||||
property var contactsStore
|
||||
property UsersStore usersStore: UsersStore {}
|
||||
|
||||
onChatContentModuleChanged: {
|
||||
chatContentRoot.usersStore.usersModule = chatContentRoot.chatContentModule.usersModule
|
||||
}
|
||||
|
||||
|
||||
property Component sendTransactionNoEnsModal
|
||||
property Component receiveTransactionModal
|
||||
|
@ -70,7 +76,7 @@ ColumnLayout {
|
|||
//% "Public chat"
|
||||
return qsTrId("public-chat")
|
||||
case Constants.chatType.privateGroupChat:
|
||||
let cnt = chatContentModule.usersModule.model.count
|
||||
let cnt = chatContentRoot.usersStore.usersModule.count
|
||||
//% "%1 members"
|
||||
if(cnt > 1) return qsTrId("-1-members").arg(cnt);
|
||||
//% "1 member"
|
||||
|
@ -344,6 +350,7 @@ ColumnLayout {
|
|||
contactsStore: chatContentRoot.contactsStore
|
||||
messageContextMenuInst: contextmenu
|
||||
messageStore: messageStore
|
||||
usersStore: chatContentRoot.usersStore
|
||||
stickersLoaded: chatContentRoot.stickersLoaded
|
||||
onShowReplyArea: {
|
||||
let obj = messageStore.getMessageByIdAsJson(messageId)
|
||||
|
@ -377,6 +384,9 @@ ColumnLayout {
|
|||
|
||||
StatusChatInput {
|
||||
id: chatInput
|
||||
|
||||
usersStore: chatContentRoot.usersStore
|
||||
|
||||
visible: {
|
||||
// Not Refactored Yet
|
||||
return true
|
||||
|
|
|
@ -23,6 +23,7 @@ Item {
|
|||
|
||||
property var store
|
||||
property var messageStore
|
||||
property var usersStore
|
||||
property var contactsStore
|
||||
|
||||
property bool stickersLoaded: false
|
||||
|
@ -296,6 +297,7 @@ Item {
|
|||
id: msgDelegate
|
||||
|
||||
messageStore: root.messageStore
|
||||
usersStore: root.usersStore
|
||||
contactsStore: root.contactsStore
|
||||
|
||||
messageContextMenu: messageContextMenuInst
|
||||
|
|
|
@ -28,6 +28,8 @@ Rectangle {
|
|||
signal stickerSelected(string hashId, string packId)
|
||||
signal sendMessage(var event)
|
||||
|
||||
property var usersStore
|
||||
|
||||
property bool emojiEvent: false;
|
||||
property bool paste: false;
|
||||
property bool isColonPressed: false;
|
||||
|
@ -288,9 +290,7 @@ Rectangle {
|
|||
|
||||
const deparsedEmoji = Emoji.deparse(textWithoutMention);
|
||||
|
||||
// Not Refactored Yet
|
||||
return ""
|
||||
//return RootStore.chatsModelInst.plainText(deparsedEmoji);
|
||||
return globalUtils.plainText(deparsedEmoji)
|
||||
}
|
||||
|
||||
function removeMentions(currentText) {
|
||||
|
@ -622,26 +622,16 @@ Rectangle {
|
|||
|
||||
SuggestionBoxPanel {
|
||||
id: suggestionsBox
|
||||
// Not Refactored Yet
|
||||
// model: {
|
||||
// if (RootStore.chatsModelInst.communities.activeCommunity.active) {
|
||||
// return RootStore.chatsModelInst.communities.activeCommunity.members
|
||||
// }
|
||||
// return RootStore.chatsModelInst.messageView.messageList.userList
|
||||
// }
|
||||
model: control.usersStore.usersModel
|
||||
x : messageInput.x
|
||||
y: -height - Style.current.smallPadding
|
||||
width: messageInput.width
|
||||
filter: messageInputField.text
|
||||
cursorPosition: messageInputField.cursorPosition
|
||||
property: ["userName", "localName", "alias"]
|
||||
property: ["name"]
|
||||
onItemSelected: function (item, lastAtPosition, lastCursorPosition) {
|
||||
const properties = "userName, alias"; // Ignore localName
|
||||
let aliasName = item[properties.split(",").map(p => p.trim()).find(p => !!item[p])]
|
||||
aliasName = aliasName.replace("@", "")
|
||||
aliasName = aliasName.replace(/(\.stateofus)?\.eth/, "")
|
||||
|
||||
insertMention(aliasName, lastAtPosition, lastCursorPosition)
|
||||
let name = item.name.replace("@", "")
|
||||
insertMention(name, lastAtPosition, lastCursorPosition)
|
||||
suggestionsBox.suggestionsModel.clear()
|
||||
}
|
||||
}
|
||||
|
@ -1091,8 +1081,7 @@ Rectangle {
|
|||
anchors.rightMargin: Style.current.halfPadding
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: imageBtn2.visible
|
||||
// Not Refactored Yet
|
||||
// enabled: (RootStore.chatsModelInst.plainText(Emoji.deparse(messageInputField.text)).length > 0 || isImage) && messageInputField.length < messageLimit
|
||||
enabled: (globalUtils.plainText(Emoji.deparse(messageInputField.text)).length > 0 || isImage) && messageInputField.length < messageLimit
|
||||
onClicked: function (event) {
|
||||
control.sendMessage(event)
|
||||
control.hideExtendedArea();
|
||||
|
|
|
@ -11,9 +11,7 @@ Item {
|
|||
|
||||
property var store
|
||||
property bool longChatText: true
|
||||
// Not Refactored Yet
|
||||
property bool veryLongChatText: false // !!root.store ? root.store.chatsModelInst.plainText(message).length >
|
||||
//Constants.limitLongChatTextCompactMode : false
|
||||
property bool veryLongChatText: globalUtils.plainText(message).length > Constants.limitLongChatTextCompactMode
|
||||
property bool readMore: false
|
||||
property alias textField: chatText
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ Item {
|
|||
id: root
|
||||
|
||||
property var messageStore
|
||||
property var usersStore
|
||||
property var contactsStore
|
||||
|
||||
property var messageContextMenu
|
||||
|
@ -364,12 +365,13 @@ Item {
|
|||
if (index < 0) {
|
||||
break
|
||||
}
|
||||
let endIndex = message.indexOf("</a>", index)
|
||||
let startIndex = index
|
||||
let endIndex = message.indexOf("</a>", index) + 4
|
||||
if (endIndex < 0) {
|
||||
index += 8 // "<a href="
|
||||
continue
|
||||
}
|
||||
let addrIndex = rmessage.indexOf("0x", index + 8)
|
||||
let addrIndex = message.indexOf("0x", index + 8)
|
||||
if (addrIndex < 0) {
|
||||
index += 8 // "<a href="
|
||||
continue
|
||||
|
@ -379,21 +381,19 @@ Item {
|
|||
index += 8 // "<a href="
|
||||
continue
|
||||
}
|
||||
const address = '@' + message.substring(addrIndex, addrEndIndex)
|
||||
const linkTag = message.substring(index, endIndex + 5)
|
||||
const mentionLink = message.substring(startIndex, endIndex)
|
||||
const linkTag = message.substring(index, endIndex)
|
||||
const linkText = linkTag.replace(/(<([^>]+)>)/ig,"").trim()
|
||||
const atSymbol = linkText.startsWith("@") ? '' : '@'
|
||||
const mentionTag = Constants.mentionSpanTag + atSymbol + linkText + '</span> '
|
||||
mentionsMap.set(address, mentionTag)
|
||||
mentionsMap.set(mentionLink, mentionTag)
|
||||
index += linkTag.length
|
||||
}
|
||||
|
||||
sourceText = rootStore.plainText(Emoji.deparse(message))
|
||||
sourceText = message
|
||||
for (let [key, value] of mentionsMap) {
|
||||
sourceText = sourceText.replace(new RegExp(key, 'g'), value)
|
||||
}
|
||||
sourceText = sourceText.replace(/\n/g, "<br />")
|
||||
sourceText = Utils.getMessageWithStyle(sourceText, isCurrentUser)
|
||||
}
|
||||
|
||||
sourceComponent: Item {
|
||||
|
@ -410,6 +410,9 @@ Item {
|
|||
|
||||
StatusChatInput {
|
||||
id: editTextInput
|
||||
|
||||
usersStore: root.usersStore
|
||||
|
||||
chatInputPlaceholder: qsTrId("type-a-message-")
|
||||
chatType: messageStore.getChatType()
|
||||
isEdit: true
|
||||
|
|
|
@ -18,6 +18,7 @@ Column {
|
|||
z: (typeof chatLogView === "undefined") ? 1 : (chatLogView.count - index)
|
||||
|
||||
property var messageStore
|
||||
property var usersStore
|
||||
property var contactsStore
|
||||
property var messageContextMenu
|
||||
|
||||
|
@ -342,6 +343,7 @@ Column {
|
|||
|
||||
CompactMessageView {
|
||||
messageStore: root.messageStore
|
||||
usersStore: root.usersStore
|
||||
contactsStore: root.contactsStore
|
||||
messageContextMenu: root.messageContextMenu
|
||||
contentType: root.messageContentType
|
||||
|
|
Loading…
Reference in New Issue