diff --git a/imports/NeoChat/Component/Timeline/LinkPreviewDelegate.qml b/imports/NeoChat/Component/Timeline/LinkPreviewDelegate.qml
index 4e170a227..f8ae1b393 100644
--- a/imports/NeoChat/Component/Timeline/LinkPreviewDelegate.qml
+++ b/imports/NeoChat/Component/Timeline/LinkPreviewDelegate.qml
@@ -11,9 +11,22 @@ import org.kde.neochat 1.0
RowLayout {
id: row
+ readonly property var customEmojiLinksRegex: /data-mx-emoticon="" src="(\bhttps?:\/\/[^\s\<\>\"\']*[^\s\<\>\"\'])/g
+ readonly property var customEmojiLinks: {
+ let links = [];
+ // we need all this because QML JS doesn't support String.matchAll introduced in ECMAScript 2020
+ let match = customEmojiLinksRegex.exec(model.display);
+ while (match !== null) {
+ links.push(match[1])
+ match = customEmojiLinksRegex.exec(model.display);
+ }
+ return links;
+ }
property var links: model.display.match(/(\bhttps?:\/\/[^\s\<\>\"\']*[^\s\<\>\"\'])/g)
- // don't show previews for room links or user mentions
- .filter(link => !link.includes("https://matrix.to"))
+ // don't show previews for room links or user mentions or custom emojis
+ .filter(link => !(
+ link.includes("https://matrix.to") || (customEmojiLinks && customEmojiLinks.includes(link))
+ ))
// remove ending fullstops and commas
.map(link => (link.length && [".", ","].includes(link[link.length-1])) ? link.substring(0, link.length-1) : link)
LinkPreviewer {
diff --git a/imports/NeoChat/Component/Timeline/RichLabel.qml b/imports/NeoChat/Component/Timeline/RichLabel.qml
index bfa098665..8457d7013 100644
--- a/imports/NeoChat/Component/Timeline/RichLabel.qml
+++ b/imports/NeoChat/Component/Timeline/RichLabel.qml
@@ -17,20 +17,33 @@ TextEdit {
property bool isEmote: false
/* Turn all links which aren't already in tags into hyperlinks */
+ readonly property var customEmojiLinksRegex: /data-mx-emoticon="" src="(\bhttps?:\/\/[^\s\<\>\"\']*[^\s\<\>\"\'])/g
+ readonly property var customEmojiLinks: {
+ let links = [];
+ // we need all this because QML JS doesn't support String.matchAll introduced in ECMAScript 2020
+ let match = customEmojiLinksRegex.exec(model.display);
+ while (match !== null) {
+ links.push(match[1])
+ match = customEmojiLinksRegex.exec(model.display);
+ }
+ return links;
+ }
readonly property var linkRegex: /(href=["'])?(\b(https?):\/\/[^\s\<\>\"\'\\]+)/g
property string textMessage: model.display.includes("http")
? model.display.replace(linkRegex, function() {
+ if (customEmojiLinks && customEmojiLinks.includes(arguments[0])) {
+ return arguments[0];
+ }
if (arguments[1]) {
return arguments[0];
- } else {
- var l = arguments[2];
- if ([".", ","].includes(l[l.length-1])) {
- var link = l.substring(0, l.length-1);
- var leftover = l[l.length-1];
- return "" + link + "" + leftover;
- }
- return "" + l + "";
- }
+ }
+ const l = arguments[2];
+ if ([".", ","].includes(l[l.length-1])) {
+ const link = l.substring(0, l.length-1);
+ const leftover = l[l.length-1];
+ return `${link}${leftover}`;
+ }
+ return `${l}`;
})
: model.display
property bool spoilerRevealed: !hasSpoiler.test(textMessage)