From 86697c82e97475f1a0668d6131809ff55556c7c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Iv=C3=A1n=20Vieitez=20Parra?= <3857362+corrideat@users.noreply.github.com> Date: Wed, 7 Feb 2024 20:39:16 +0100 Subject: [PATCH] Unamiguous @all mention (using channel ID) --- frontend/model/contracts/chatroom.js | 8 ++++---- frontend/model/contracts/manifests.json | 2 +- frontend/model/contracts/shared/functions.js | 15 +++++++++++---- .../views/containers/chatroom/MessageBase.vue | 8 ++++---- frontend/views/containers/chatroom/SendArea.vue | 14 +++++++------- 5 files changed, 27 insertions(+), 20 deletions(-) diff --git a/frontend/model/contracts/chatroom.js b/frontend/model/contracts/chatroom.js index e229ccb1e5..b542027a05 100644 --- a/frontend/model/contracts/chatroom.js +++ b/frontend/model/contracts/chatroom.js @@ -422,7 +422,7 @@ sbp('chelonia/defineContract', { return } const newMessage = createMessage({ meta, data, hash, height, state, innerSigningContractID }) - const mentions = makeMentionFromUserID(me) + const mentions = makeMentionFromUserID(me, contractID) const isMentionedMe = data.type === MESSAGE_TYPES.TEXT && (newMessage.text.includes(mentions.me) || newMessage.text.includes(mentions.all)) @@ -467,7 +467,7 @@ sbp('chelonia/defineContract', { const isAlreadyAdded = !!sbp('state/vuex/getters') .chatRoomUnreadMessages(contractID).find(m => m.messageHash === data.hash) - const mentions = makeMentionFromUserID(me) + const mentions = makeMentionFromUserID(me, contractID) const isMentionedMe = data.text.includes(mentions.me) || data.text.includes(mentions.all) if (!isAlreadyAdded) { @@ -497,7 +497,7 @@ sbp('chelonia/defineContract', { }, 'gi.contracts/chatroom/deleteMessage': { validate: actionRequireInnerSignature(objectOf({ hash: string })), - process ({ data, meta, innerSigningContractID }, { state }) { + process ({ data, meta, contractID, innerSigningContractID }, { state }) { if (!state.onlyRenderMessage) { return } @@ -510,7 +510,7 @@ sbp('chelonia/defineContract', { if (message.replyingMessage?.hash === data.hash) { message.replyingMessage.hash = null message.replyingMessage.text = L('Original message was removed by {user}', { - user: makeMentionFromUserID(innerSigningContractID).me + user: makeMentionFromUserID(innerSigningContractID, contractID).me }) } } diff --git a/frontend/model/contracts/manifests.json b/frontend/model/contracts/manifests.json index 8fd47c2cf7..cc00792550 100644 --- a/frontend/model/contracts/manifests.json +++ b/frontend/model/contracts/manifests.json @@ -1,6 +1,6 @@ { "manifests": { - "gi.contracts/chatroom": "z9brRu3VRwA9WQ6nhRbJz8KvZ3W6a43vhXrx1iES6yRsExsXzTpG", + "gi.contracts/chatroom": "z9brRu3VRMJTR6qQiaqFxvfUgZP6RJkcpwpG5gX5DdCnS83vTXJn", "gi.contracts/group": "z9brRu3VNeHviRAc7DLPBQqyagTrpUHoXF9YdMFr1gtrgYGMzfSB", "gi.contracts/identity": "z9brRu3VSVRddCxKg3YRMP8niKH7gwNq5TexdjvBEDfoLRv97DBh" } diff --git a/frontend/model/contracts/shared/functions.js b/frontend/model/contracts/shared/functions.js index c83388efbf..cd505b7e89 100644 --- a/frontend/model/contracts/shared/functions.js +++ b/frontend/model/contracts/shared/functions.js @@ -130,23 +130,30 @@ export function findMessageIdx (hash: string, messages: Array): number { return -1 } +// This function serves two purposes, depending on the forceUsername parameter +// If forceUsername is true, mentions will be like @username, @all, for display +// purposes. +// If forceUsername is false (default), mentions like @username will be converted +// to @, for internal representation purposes. // forceUsername is used for display purposes in the UI, so that we can show // a mention like @username instead of @userID in SendArea -export function makeMentionFromUsername (username: string, forceUsername: ?boolean): { +export function makeMentionFromUsername (username: string, channelID: string, forceUsername: ?boolean): { me: string, all: string } { const rootGetters = sbp('state/vuex/getters') // Even if forceUsername is true, we want to look up the contract ID to ensure // that it exists, so that we know it'll later succeed. const userID = rootGetters.ourContactProfiles[username]?.contractID - return makeMentionFromUserID(forceUsername && userID ? username : userID) + return forceUsername + ? makeMentionFromUserID(userID ? username : userID, 'all') + : makeMentionFromUserID(username === 'all' ? channelID : userID, channelID) } -export function makeMentionFromUserID (userID: string): { +export function makeMentionFromUserID (userID: string, channelID: string): { me: string, all: string } { return { me: userID ? `@${userID}` : '', - all: '@all' + all: `@${channelID}` } } diff --git a/frontend/views/containers/chatroom/MessageBase.vue b/frontend/views/containers/chatroom/MessageBase.vue index eeff17da5b..6769d80cfe 100644 --- a/frontend/views/containers/chatroom/MessageBase.vue +++ b/frontend/views/containers/chatroom/MessageBase.vue @@ -131,7 +131,7 @@ export default ({ convertTextToMarkdown: Boolean }, computed: { - ...mapGetters(['chatRoomMembers', 'usernameFromID']), + ...mapGetters(['chatRoomMembers', 'currentChatRoomId', 'usernameFromID']), textObjects () { return this.generateTextObjectsFromText(this.text) }, @@ -200,8 +200,8 @@ export default ({ } ] } - const allMention = makeMentionFromUserID('').all - const possibleMentions = Object.keys(this.chatRoomMembers).map(u => makeMentionFromUserID(u).me).filter(v => !!v) + const allMention = makeMentionFromUserID('', this.currentChatRoomId).all + const possibleMentions = Object.keys(this.chatRoomMembers).map(u => makeMentionFromUserID(u, this.currentChatRoomId).me).filter(v => !!v) return text // We try to find all the mentions and render them as mentions instead @@ -212,7 +212,7 @@ export default ({ .split(new RegExp(`(?<=\\s|^)(${allMention}|${possibleMentions.join('|')})(?=[^\\w\\d]|$)`)) .map(t => { if (t === allMention) { - return { type: TextObjectType.Mention, text: t } + return { type: TextObjectType.Mention, text: t[0] + 'all' } } return possibleMentions.includes(t) ? { type: TextObjectType.Mention, text: t[0] + this.usernameFromID(t.slice(1)) } diff --git a/frontend/views/containers/chatroom/SendArea.vue b/frontend/views/containers/chatroom/SendArea.vue index 2d20cca3bf..bd9c54495f 100644 --- a/frontend/views/containers/chatroom/SendArea.vue +++ b/frontend/views/containers/chatroom/SendArea.vue @@ -492,7 +492,7 @@ export default ({ const curPosition = this.$refs.textarea.selectionStart const selection = this.ephemeral.mention.options[index] - const mentionObj = makeMentionFromUsername(selection.username || selection.memberID, true) + const mentionObj = makeMentionFromUsername(selection.username || selection.memberID, this.currentChatRoomId, true) const mention = selection.memberID === mentionObj.all ? mentionObj.all : mentionObj.me const value = curValue.slice(0, this.ephemeral.mention.position) + mention + ' ' + curValue.slice(curPosition) @@ -565,15 +565,15 @@ export default ({ } /* Process mentions in the form @username => @userID */ - const mentionStart = makeMentionFromUsername('').all[0] + const allMention = makeMentionFromUsername('', this.currentChatRoomId, true).all + const mentionStart = allMention[0] const availableMentions = this.members.map(memberID => memberID.username) msgToSend = msgToSend.replace( // This regular expression matches all @username mentions that are // standing alone between spaces - new RegExp(`(?<=\\s|^)${mentionStart}(${availableMentions.join('|')})(?=[^\\w\\d]|$)`, 'g'), + new RegExp(`(?<=\\s|^)${mentionStart}(${allMention.slice(1)}|${availableMentions.join('|')})(?=[^\\w\\d]|$)`, 'g'), (_, username) => { - console.log() - return makeMentionFromUsername(username).me + return makeMentionFromUsername(username, this.currentChatRoomId).me } ) @@ -653,13 +653,13 @@ export default ({ this.updateTextWithLines() }, startMention (keyword, position) { - const all = makeMentionFromUsername('').all + const all = makeMentionFromUsername('', this.currentChatRoomId, true).all const availableMentions = Array.from(this.members) // NOTE: '@all' mention should only be needed when the members are more than 3 if (availableMentions.length > 2) { availableMentions.push({ memberID: all, - displayName: all.slice(1), + displayName: L('all'), picture: '/assets/images/horn.png' }) }