mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-19 18:18:38 +00:00
refactor and add support for converting to emoji after pasting text
This commit is contained in:
parent
542020d6a6
commit
e77b6d193e
@ -6,7 +6,6 @@ import QtQuick.Dialogs 1.0
|
|||||||
import "../components"
|
import "../components"
|
||||||
import "../../../../shared"
|
import "../../../../shared"
|
||||||
import "../../../../imports"
|
import "../../../../imports"
|
||||||
import "../components/emojiList.js" as EmojiJSON
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: rectangle
|
id: rectangle
|
||||||
@ -18,6 +17,8 @@ Rectangle {
|
|||||||
visible: chatsModel.activeChannel.chatType !== Constants.chatTypePrivateGroupChat || chatsModel.activeChannel.isMember(profileModel.profile.pubKey)
|
visible: chatsModel.activeChannel.chatType !== Constants.chatTypePrivateGroupChat || chatsModel.activeChannel.isMember(profileModel.profile.pubKey)
|
||||||
|
|
||||||
property bool emojiEvent: false;
|
property bool emojiEvent: false;
|
||||||
|
property bool paste: false;
|
||||||
|
property bool isColonPressed: false;
|
||||||
|
|
||||||
Audio {
|
Audio {
|
||||||
id: sendMessageSound
|
id: sendMessageSound
|
||||||
@ -56,125 +57,140 @@ Rectangle {
|
|||||||
if (event.modifiers === Qt.NoModifier && (event.key === Qt.Key_Enter || event.key === Qt.Key_Return)) {
|
if (event.modifiers === Qt.NoModifier && (event.key === Qt.Key_Enter || event.key === Qt.Key_Return)) {
|
||||||
sendMsg(event);
|
sendMsg(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((event.key == Qt.Key_V) && (event.modifiers & Qt.ControlModifier)) {
|
||||||
|
paste = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
isColonPressed = (event.key == Qt.Key_Colon) && (event.modifiers & Qt.ShiftModifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onRelease(event) {
|
function onRelease(event) {
|
||||||
emojiEvent = emojiHandler(emojiEvent, event);
|
// the text doesn't get registered to the textarea fast enough
|
||||||
|
// we can only get it in the `released` event
|
||||||
|
if (paste) {
|
||||||
|
paste = false;
|
||||||
|
interrogateMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
emojiEvent = emojiHandler(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMouseClicked() {
|
function onMouseClicked() {
|
||||||
emojiEvent = emojiHandler(emojiEvent, {key: null});
|
emojiEvent = emojiHandler({key: null});
|
||||||
}
|
}
|
||||||
|
|
||||||
function countEmojis(value) {
|
function interrogateMessage() {
|
||||||
let match = value.match(/<img class=\"emoji\" draggable=\"false\" alt=\"(.+?)\" src=\"qrc:\/imports\/twemoji\/.+?"\/>/g, "$1");
|
const text = chatsModel.plainText(Emoji.deparse(txtData.text));
|
||||||
var length = 0;
|
var words = text.split(' ');
|
||||||
|
|
||||||
if (match && match.length > 0) {
|
for (var i = 0; i < words.length; i++) {
|
||||||
for (var i = 0; i < match.length; i++) {
|
var transform = true;
|
||||||
var deparse = Emoji.deparse(match[i]);
|
if (words[i].charAt(0) === ':') {
|
||||||
length += deparse.length;
|
for (var j = 0; j < words[i].length; j++) {
|
||||||
|
if (isSpace(words[i].charAt(j)) === true || isPunct(words[i].charAt(j)) === true) {
|
||||||
|
transform = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transform) {
|
||||||
|
const codePoint = Emoji.getEmojiUnicode(words[i]);
|
||||||
|
words[i] = words[i].replace(words[i], (codePoint !== undefined) ? Emoji.fromCodePoint(codePoint) : words[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
console.log("cursorPosition: ", length - match.length, "[", length,"]", "[",match.length,"]");
|
|
||||||
length = length - match.length;
|
|
||||||
}
|
}
|
||||||
return length;
|
|
||||||
|
txtData.remove(0, txtData.length);
|
||||||
|
txtData.insert(0, Emoji.parse(words.join(' '), '26x26'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function extraPolatePosition(text, cursorPosition) {
|
function emojiHandler(event) {
|
||||||
|
let message = extrapolateCursorPosition();
|
||||||
|
pollEmojiEvent(message);
|
||||||
|
|
||||||
|
// state machine to handle different forms of the emoji event state
|
||||||
|
if (!emojiEvent && isColonPressed) {
|
||||||
|
return (message.data.length <= 1 || isSpace(message.data.charAt(message.cursor - 1))) ? true : false;
|
||||||
|
} else if (emojiEvent && isColonPressed) {
|
||||||
|
const index = message.data.lastIndexOf(':', message.cursor - 2);
|
||||||
|
if (index >= 0 && message.cursor > 0) {
|
||||||
|
const shortname = message.data.substr(index, message.cursor);
|
||||||
|
const codePoint = Emoji.getEmojiUnicode(shortname);
|
||||||
|
const newMessage = message.data.replace(shortname, (codePoint !== undefined) ? Emoji.fromCodePoint(codePoint) : shortname);
|
||||||
|
txtData.remove(0, txtData.cursorPosition);
|
||||||
|
txtData.insert(0, Emoji.parse(newMessage, '26x26'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else if (emojiEvent && isKeyValid(event.key) && !isColonPressed) {
|
||||||
|
console.log('popup');
|
||||||
|
return true;
|
||||||
|
} else if (emojiEvent && !isKeyValid(event.key) && !isColonPressed) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// since emoji length is not 1 we need to match that position that TextArea returns
|
||||||
|
// to the actual position in the string.
|
||||||
|
function extrapolateCursorPosition() {
|
||||||
|
// we need only the message part to be html
|
||||||
|
const text = chatsModel.plainText(Emoji.deparse(txtData.text));
|
||||||
|
const plainText = Emoji.parse(text, '26x26');
|
||||||
|
|
||||||
var bracketEvent = false;
|
var bracketEvent = false;
|
||||||
var length = 0;
|
var length = 0;
|
||||||
|
|
||||||
for (var i =0; i < text.length;) {
|
for (var i = 0; i < plainText.length;) {
|
||||||
|
if (length >= txtData.cursorPosition) break;
|
||||||
|
|
||||||
if (length >= cursorPosition)
|
if (!bracketEvent && plainText.charAt(i) !== '<') {
|
||||||
break;
|
|
||||||
|
|
||||||
if (!bracketEvent && text.charAt(i) !== '<') {
|
|
||||||
i++;
|
i++;
|
||||||
length++;
|
length++;
|
||||||
} else if (!bracketEvent && text.charAt(i) === '<') {
|
} else if (!bracketEvent && plainText.charAt(i) === '<') {
|
||||||
bracketEvent = true;
|
bracketEvent = true;
|
||||||
i++;
|
i++;
|
||||||
} else if (bracketEvent && text.charAt(i) !== '>') {
|
} else if (bracketEvent && plainText.charAt(i) !== '>') {
|
||||||
i++;
|
i++;
|
||||||
} else if (bracketEvent && text.charAt(i) === '>') {
|
} else if (bracketEvent && plainText.charAt(i) === '>') {
|
||||||
bracketEvent = false;
|
bracketEvent = false;
|
||||||
i++;
|
i++;
|
||||||
length++;
|
length++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var substr = text.substr(0, i);
|
let textBeforeCursor = Emoji.deparseFromParse(plainText.substr(0, i));
|
||||||
substr = substr.replace(/<img class=\"emoji\" draggable=\"false\" alt=\"(.+?)\" src=\"qrc:\/imports\/twemoji\/.+?"\/>/g, "$1");
|
|
||||||
return substr;
|
return {
|
||||||
|
cursor: countEmojiLengths(plainText.substr(0, i)) + txtData.cursorPosition,
|
||||||
|
data: chatsModel.plainText(Emoji.deparseFromParse(textBeforeCursor)),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function deparseFromParse(substr) {
|
function countEmojiLengths(value) {
|
||||||
return substr.replace(/<img class=\"emoji\" draggable=\"false\" alt=\"(.+?)\" src=\"qrc:\/imports\/twemoji\/.+?"\/>/g, "$1");
|
const match = Emoji.getEmojis(value);
|
||||||
|
var length = 0;
|
||||||
|
|
||||||
|
if (match && match.length > 0) {
|
||||||
|
for (var i = 0; i < match.length; i++) {
|
||||||
|
length += Emoji.deparseFromParse(match[i]).length;
|
||||||
|
}
|
||||||
|
length = length - match.length;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
function emojiHandler(emojiEvent, event) {
|
// check if user has placed cursor near valid emoji colon token
|
||||||
var deparse = Emoji.deparse(txtData.text);
|
function pollEmojiEvent(message) {
|
||||||
var plain = chatsModel.plainText(deparse)
|
const index = message.data.lastIndexOf(':', message.cursor);
|
||||||
var TheText = Emoji.parse(plain, '26x26');
|
|
||||||
|
|
||||||
var text = extraPolatePosition(TheText, txtData.cursorPosition);
|
|
||||||
var cursorPosition = countEmojis(text) + txtData.cursorPosition;
|
|
||||||
var msg = chatsModel.plainText(deparseFromParse(text));
|
|
||||||
|
|
||||||
console.log("MESSAGE: [", msg, "]", "[", msg.length, "]", txtData.cursorPosition);
|
|
||||||
|
|
||||||
// check if user has placed cursor near valid emoji colon token
|
|
||||||
var index = msg.lastIndexOf(':', cursorPosition);
|
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
var substr = msg.substr(index, cursorPosition - index);
|
emojiEvent = validSubstr(message.data.substr(index, message.cursor - index));
|
||||||
console.log("MESSAGE: [", msg, "]", "[", msg.length, "]", txtData.cursorPosition, index, substr, validSubstr(substr));
|
|
||||||
emojiEvent = validSubstr(substr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("EVENT: ", event.key, Qt.Key_Colon, event.key === Qt.Key_Colon, emojiEvent);
|
|
||||||
|
|
||||||
// state machine to handle different forms of the emoji event state
|
|
||||||
if (emojiEvent === false && event.key === Qt.Key_Colon) {
|
|
||||||
if (msg.length <= 1 || isSpace(msg.charAt(cursorPosition - 1)) === true) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} else if (emojiEvent === true && event.key === Qt.Key_Colon) {
|
|
||||||
var index = msg.lastIndexOf(':', cursorPosition - 1);
|
|
||||||
console.log("BEGIN SENTENCE: ", index, cursorPosition, txtData.cursorPosition);
|
|
||||||
if (index >= 0 && cursorPosition > 0) {
|
|
||||||
var shortname = msg.substr(index, cursorPosition);
|
|
||||||
var codePoint = getEmojiUnicodeFromShortname(shortname);
|
|
||||||
var newText = (codePoint !== undefined) ? Emoji.fromCodePoint(codePoint) : shortname;
|
|
||||||
|
|
||||||
var newMsg = msg.replace(shortname, newText)
|
|
||||||
console.log("INDEX AND CURSOR: ", index, cursorPosition, "[",shortname,"]", "[",msg,"]", "[",newMsg,"]");
|
|
||||||
txtData.remove(0, cursorPosition);
|
|
||||||
txtData.insert(0, Emoji.parse(newMsg, '26x26'));
|
|
||||||
|
|
||||||
if (event) event.accepted = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else if (emojiEvent === true && isKeyValid(event.key) === true) {
|
|
||||||
console.log('popup');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (emojiEvent === true && isKeyValid(event.key) === false) {
|
|
||||||
console.log('emoji event stopped');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function validSubstr(substr) {
|
function validSubstr(substr) {
|
||||||
for(var i = 0; i < substr.length; i++) {
|
for(var i = 0; i < substr.length; i++) {
|
||||||
var c = substr.charAt(i);
|
var c = substr.charAt(i);
|
||||||
console.log("isSpace: ", isSpace(c), "isPunct: ", isPunct(c))
|
|
||||||
if (isSpace(c) === true || isPunct(c) === true)
|
if (isSpace(c) === true || isPunct(c) === true)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -192,8 +208,8 @@ Rectangle {
|
|||||||
|
|
||||||
function isSpace(c) {
|
function isSpace(c) {
|
||||||
if (/( |\t|\n|\r)/.test(c))
|
if (/( |\t|\n|\r)/.test(c))
|
||||||
return true
|
return true;
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isPunct(c) {
|
function isPunct(c) {
|
||||||
@ -202,31 +218,6 @@ Rectangle {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isKeyAlpha(key) {
|
|
||||||
if (key >= Qt.Key_A && key <= Qt.Key_Z)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isKeyDigit(key) {
|
|
||||||
if (key >= Qt.Key_0 && key <= Qt.Key_9)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// search for shortname
|
|
||||||
function getEmojiUnicodeFromShortname(shortname) {
|
|
||||||
var _emoji;
|
|
||||||
EmojiJSON.emoji_json.forEach(function(emoji) {
|
|
||||||
if (emoji.shortname === shortname)
|
|
||||||
_emoji = emoji;
|
|
||||||
})
|
|
||||||
|
|
||||||
if (_emoji !== undefined)
|
|
||||||
return _emoji.unicode;
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileDialog {
|
FileDialog {
|
||||||
id: imageDialog
|
id: imageDialog
|
||||||
//% "Please choose an image"
|
//% "Please choose an image"
|
||||||
|
@ -2,6 +2,7 @@ pragma Singleton
|
|||||||
|
|
||||||
import QtQuick 2.13
|
import QtQuick 2.13
|
||||||
import "./twemoji/twemoji.js" as Twemoji
|
import "./twemoji/twemoji.js" as Twemoji
|
||||||
|
import "../app/AppLayouts/Chat/components/emojiList.js" as EmojiJSON
|
||||||
|
|
||||||
QtObject {
|
QtObject {
|
||||||
property string base: Qt.resolvedUrl("twemoji/")
|
property string base: Qt.resolvedUrl("twemoji/")
|
||||||
@ -17,8 +18,25 @@ QtObject {
|
|||||||
function deparse(value){
|
function deparse(value){
|
||||||
return value.replace(/<img src=\"qrc:\/imports\/twemoji\/.+?" alt=\"(.+?)\" \/>/g, "$1");
|
return value.replace(/<img src=\"qrc:\/imports\/twemoji\/.+?" alt=\"(.+?)\" \/>/g, "$1");
|
||||||
}
|
}
|
||||||
|
function deparseFromParse(value) {
|
||||||
|
return value.replace(/<img class=\"emoji\" draggable=\"false\" alt=\"(.+?)\" src=\"qrc:\/imports\/twemoji\/.+?"\/>/g, "$1");
|
||||||
|
}
|
||||||
function hasEmoji(value) {
|
function hasEmoji(value) {
|
||||||
let match = value.match(/<img src=\"qrc:\/imports\/twemoji\/.+?" alt=\"(.+?)\" \/>/g)
|
let match = value.match(/<img src=\"qrc:\/imports\/twemoji\/.+?" alt=\"(.+?)\" \/>/g)
|
||||||
return match && match.length > 0
|
return match && match.length > 0
|
||||||
}
|
}
|
||||||
|
function getEmojis(value) {
|
||||||
|
return value.match(/<img class=\"emoji\" draggable=\"false\" alt=\"(.+?)\" src=\"qrc:\/imports\/twemoji\/.+?"\/>/g, "$1");
|
||||||
|
}
|
||||||
|
function getEmojiUnicode(shortname) {
|
||||||
|
var _emoji;
|
||||||
|
EmojiJSON.emoji_json.forEach(function(emoji) {
|
||||||
|
if (emoji.shortname === shortname)
|
||||||
|
_emoji = emoji;
|
||||||
|
})
|
||||||
|
|
||||||
|
if (_emoji !== undefined)
|
||||||
|
return _emoji.unicode;
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user