fix(@desktop/chat): mention suggestion list fixed

This commit is contained in:
Sale Djenic 2022-02-08 13:08:02 +01:00 committed by Iuri Matias
parent 485d6a370d
commit aa6036b78b
12 changed files with 126 additions and 50 deletions

View File

@ -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

View File

@ -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,

View File

@ -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]

View File

@ -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 {

View File

@ -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)
}

View File

@ -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
}
}

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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