feat: Keyboard shortcuts
Add keyboard shortcuts according to https://notes.status.im/02cfVf1KQLeQU2SqrIi9tw fix: update chat message bubbles - Align emojis to middle of text - Add line-height as per design - Properly support RTL languages (right-aligned) and LTR languages (left-aligned) - Remove unneeded non-breaking space at the beginning of current user messages - Properly support markdown for bold, strikethrough, and italic - Fix text being removed when in between strikethrough markdown (~~) fix: emoji resolution update for high resolution monitors - Emojis now use the 72x72 original set, but are down-scaled to 20x20 (in chat bubbles) or 22x22 in other places, effectively tripling their pixel density feat: handle new lines in blockquote Handle new lines in blockquote so that messages display correctly. Also, add functionality when a new line is entered in to the chat input, if it's inside a blockquote, a new ">" will be added automatically. This is also handled when backspace is entered. feat: update xss to support full qt html4 table and table-cell attributes
This commit is contained in:
parent
e2ec5fa84e
commit
417194e7b4
|
@ -1,4 +1,6 @@
|
|||
import sequtils
|
||||
import sequtils, re
|
||||
|
||||
let NEW_LINE = re"\n|\r"
|
||||
|
||||
proc sectionIdentifier(message: Message): string =
|
||||
result = message.fromAuthor
|
||||
|
@ -15,15 +17,16 @@ proc mention(self: ChatMessageList, pubKey: string): string =
|
|||
|
||||
# See render-inline in status-react/src/status_im/ui/screens/chat/message/message.cljs
|
||||
proc renderInline(self: ChatMessageList, elem: TextItem): string =
|
||||
let value = escape_html(elem.literal.strip)
|
||||
let value = escape_html(elem.literal)
|
||||
case elem.textType:
|
||||
of "": result = value
|
||||
of "code": result = fmt(" <code>{value}</code> ")
|
||||
of "emph": result = fmt(" <em>{value}</em> ")
|
||||
of "strong": result = fmt(" <strong>{value}</strong> ")
|
||||
of "link": result = fmt(" {elem.destination} ")
|
||||
of "mention": result = fmt(" <a href=\"//{value}\" class=\"mention\">{self.mention(value)}</a> ")
|
||||
of "status-tag": result = fmt(" <a href=\"#{value}\" class=\"status-tag\">#{value}</a> ")
|
||||
of "code": result = fmt("<code>{value}</code>")
|
||||
of "emph": result = fmt("<em>{value}</em>")
|
||||
of "strong": result = fmt("<strong>{value}</strong>")
|
||||
of "link": result = fmt("{elem.destination}")
|
||||
of "mention": result = fmt("<a href=\"//{value}\" class=\"mention\">{self.mention(value)}</a>")
|
||||
of "status-tag": result = fmt("<a href=\"#{value}\" class=\"status-tag\">#{value}</a>")
|
||||
of "del": result = fmt("<del>{value}</del>")
|
||||
|
||||
# See render-block in status-react/src/status_im/ui/screens/chat/message/message.cljs
|
||||
proc renderBlock(self: ChatMessageList, message: Message): string =
|
||||
|
@ -31,14 +34,26 @@ proc renderBlock(self: ChatMessageList, message: Message): string =
|
|||
case pMsg.textType:
|
||||
of "paragraph":
|
||||
result = result & "<p>"
|
||||
if message.isCurrentUser:
|
||||
result = result & " "
|
||||
for children in pMsg.children:
|
||||
result = result & self.renderInline(children)
|
||||
result = result & "</p>"
|
||||
of "blockquote":
|
||||
result = result & pMsg.literal.strip.split("\n").mapIt("<span>▍ " & escape_html(it) & "</span>").join("<br />")
|
||||
var
|
||||
blockquote = escape_html(pMsg.literal)
|
||||
lines = toSeq(blockquote.split(NEW_LINE))
|
||||
for i in 0..(lines.len - 1):
|
||||
if i + 1 >= lines.len:
|
||||
continue
|
||||
if lines[i + 1] != "":
|
||||
lines[i] = lines[i] & "<br/>"
|
||||
blockquote = lines.join("")
|
||||
result = result & fmt(
|
||||
"<table class=\"blockquote\">" &
|
||||
"<tr>" &
|
||||
"<td class=\"quoteline\" valign=\"middle\"></td>" &
|
||||
"<td>{blockquote}</td>" &
|
||||
"</tr>" &
|
||||
"</table>")
|
||||
of "codeblock":
|
||||
result = result & "<code>" & escape_html(pMsg.literal.strip) & "</code>"
|
||||
result = result & "<code>" & escape_html(pMsg.literal) & "</code>"
|
||||
result = result.strip()
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ Loader {
|
|||
visible: repliedMessageType != Constants.imageType
|
||||
anchors.top: lblReplyAuthor.bottom
|
||||
anchors.topMargin: 5
|
||||
text: Emoji.parse(Utils.linkifyAndXSS(repliedMessageContent), "26x26");
|
||||
text: Emoji.parse(Utils.linkifyAndXSS(repliedMessageContent));
|
||||
textFormat: Text.RichText
|
||||
color: root.elementsColor
|
||||
readOnly: true
|
||||
|
|
|
@ -40,7 +40,6 @@ Item {
|
|||
StyledTextEdit {
|
||||
id: chatText
|
||||
textFormat: Text.RichText
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
wrapMode: Text.Wrap
|
||||
font.pixelSize: Style.current.primaryTextFontSize
|
||||
readOnly: true
|
||||
|
@ -66,35 +65,41 @@ Item {
|
|||
if(contentType === Constants.stickerType) return "";
|
||||
let msg = Utils.linkifyAndXSS(message);
|
||||
if(isEmoji) {
|
||||
return Emoji.parse(msg, "72x72");
|
||||
return Emoji.parse(msg, Emoji.size.big);
|
||||
} else {
|
||||
return `<html>`+
|
||||
`<head>`+
|
||||
`<style type="text/css">`+
|
||||
`code {`+
|
||||
`background-color: #1a356b;`+
|
||||
`color: #FFFFFF;`+
|
||||
`white-space: pre;`+
|
||||
`}`+
|
||||
`p {`+
|
||||
`white-space: pre-wrap;`+
|
||||
`}`+
|
||||
`a {`+
|
||||
`color: ${isCurrentUser && !appSettings.compactMode ? Style.current.white : Style.current.textColor};`+
|
||||
`}`+
|
||||
`a.mention {`+
|
||||
`color: ${isCurrentUser ? Style.current.cyan : Style.current.turquoise};`+
|
||||
`}`+
|
||||
`blockquote {`+
|
||||
`margin: 0;`+
|
||||
`padding: 0;`+
|
||||
`}`+
|
||||
`</style>`+
|
||||
`</head>`+
|
||||
`<body>`+
|
||||
`${Emoji.parse(msg, "26x26")}`+
|
||||
`</body>`+
|
||||
`</html>`;
|
||||
return `<style type="text/css">` +
|
||||
`p, img, a, del, code, blockquote { margin: 0; padding: 0; }` +
|
||||
`code {` +
|
||||
`background-color: ${Style.current.codeBackground};` +
|
||||
`color: ${Style.current.white};` +
|
||||
`white-space: pre;` +
|
||||
`}` +
|
||||
`p {` +
|
||||
`line-height: 22px;` +
|
||||
`}` +
|
||||
`a {` +
|
||||
`color: ${isCurrentUser && !appSettings.compactMode ? Style.current.white : Style.current.textColor};` +
|
||||
`}` +
|
||||
`a.mention {` +
|
||||
`color: ${isCurrentUser ? Style.current.cyan : Style.current.turquoise};` +
|
||||
`}` +
|
||||
`del {` +
|
||||
`text-decoration: line-through;` +
|
||||
`}` +
|
||||
`table.blockquote td {` +
|
||||
`padding-left: 10px;` +
|
||||
`color: ${isCurrentUser ? Style.current.chatReplyCurrentUser : Style.current.secondaryText};` +
|
||||
`}` +
|
||||
`table.blockquote td.quoteline {` +
|
||||
`background-color: ${isCurrentUser ? Style.current.chatReplyCurrentUser : Style.current.secondaryText};` +
|
||||
`height: 100%;` +
|
||||
`padding-left: 0;` +
|
||||
`}` +
|
||||
`.emoji {` +
|
||||
`vertical-align: bottom;` +
|
||||
`}` +
|
||||
`</style>` +
|
||||
`${Emoji.parse(msg)}`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ Item {
|
|||
readonly property int defaultMaxMessageChars: 54
|
||||
readonly property int messageWidth: Math.max(defaultMessageWidth, parent.width / 2)
|
||||
readonly property int maxMessageChars: (defaultMaxMessageChars * messageWidth) / defaultMessageWidth
|
||||
property int chatVerticalPadding: isImage ? 4 : 7
|
||||
property int chatVerticalPadding: isImage ? 4 : 6
|
||||
property int chatHorizontalPadding: isImage ? 0 : 12
|
||||
property bool longReply: chatReply.visible && repliedMessageContent.length > maxMessageChars
|
||||
property bool longChatText: chatsModel.plainText(message).split('\n').some(function (messagePart) {
|
||||
|
@ -125,7 +125,6 @@ Item {
|
|||
anchors.leftMargin: chatBox.chatHorizontalPadding
|
||||
anchors.right: chatBox.longChatText ? parent.right : undefined
|
||||
anchors.rightMargin: chatBox.longChatText ? chatBox.chatHorizontalPadding : 0
|
||||
textField.horizontalAlignment: !isCurrentUser ? Text.AlignLeft : Text.AlignRight
|
||||
textField.color: !isCurrentUser ? Style.current.textColor : Style.current.currentUserTextColor
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ Rectangle {
|
|||
StyledText {
|
||||
id: contactInfo
|
||||
text: wrapper.chatType !== Constants.chatTypePublic ?
|
||||
Emoji.parse(Utils.removeStatusEns(Utils.filterXSS(wrapper.name)), "26x26") :
|
||||
Emoji.parse(Utils.removeStatusEns(Utils.filterXSS(wrapper.name))) :
|
||||
"#" + Utils.filterXSS(wrapper.name)
|
||||
anchors.right: contactTime.left
|
||||
anchors.rightMargin: Style.current.smallPadding
|
||||
|
@ -89,7 +89,7 @@ Rectangle {
|
|||
//% "Sticker"
|
||||
case Constants.stickerType: return qsTrId("sticker");
|
||||
//% "No messages"
|
||||
default: return lastMessage ? Emoji.parse(Utils.filterXSS(lastMessage), "26x26").replace(/\n|\r/g, ' ') : qsTrId("no-messages")
|
||||
default: return lastMessage ? Emoji.parse(Utils.filterXSS(lastMessage)).replace(/\n|\r/g, ' ') : qsTrId("no-messages")
|
||||
}
|
||||
}
|
||||
textFormat: Text.RichText
|
||||
|
|
|
@ -39,6 +39,23 @@ RowLayout {
|
|||
}
|
||||
}
|
||||
|
||||
Action {
|
||||
shortcut: "Ctrl+1"
|
||||
onTriggered: changeAppSection(Constants.chat)
|
||||
}
|
||||
Action {
|
||||
shortcut: "Ctrl+2"
|
||||
onTriggered: changeAppSection(Constants.browser)
|
||||
}
|
||||
Action {
|
||||
shortcut: "Ctrl+3"
|
||||
onTriggered: changeAppSection(Constants.wallet)
|
||||
}
|
||||
Action {
|
||||
shortcut: "Ctrl+4, Ctrl+,"
|
||||
onTriggered: changeAppSection(Constants.profile)
|
||||
}
|
||||
|
||||
function changeAppSection(section) {
|
||||
let sectionId = -1
|
||||
switch (section) {
|
||||
|
|
|
@ -5,28 +5,38 @@ import "./twemoji/twemoji.js" as Twemoji
|
|||
import "../shared/status/emojiList.js" as EmojiJSON
|
||||
|
||||
QtObject {
|
||||
readonly property var size: {
|
||||
"big": "72x72",
|
||||
"small": "20x20"
|
||||
}
|
||||
property string base: Qt.resolvedUrl("twemoji/")
|
||||
function parse(text, size) {
|
||||
function parse(text, renderSize = size.small) {
|
||||
const renderSizes = renderSize.split("x");
|
||||
if (!renderSize.includes("x") || renderSizes.length !== 2) {
|
||||
throw new Error("Invalid value for 'renderSize' parameter: ", renderSize);
|
||||
}
|
||||
Twemoji.twemoji.base = base
|
||||
Twemoji.twemoji.ext = ".png"
|
||||
Twemoji.twemoji.size = size
|
||||
return Twemoji.twemoji.parse(text)
|
||||
Twemoji.twemoji.size = size.big // source size in filesystem - get 72x72 and downscale for increased pixel density
|
||||
return Twemoji.twemoji.parse(text, {
|
||||
attributes: function() { return { width: renderSizes[0], height: renderSizes[1] }}
|
||||
})
|
||||
}
|
||||
function fromCodePoint(value) {
|
||||
return Twemoji.twemoji.convert.fromCodePoint(value)
|
||||
}
|
||||
function deparse(value){
|
||||
return value.replace(/<img src=\"qrc:\/imports\/twemoji\/.+?" alt=\"(.+?)\" \/>/g, "$1");
|
||||
return value.replace(/<img src=\"qrc:\/imports\/twemoji\/.+?" alt=\"(.+?)\" width=\"[0-9]*\" height=\"[0-9]*\" \/>/g, "$1");
|
||||
}
|
||||
function deparseFromParse(value) {
|
||||
return value.replace(/<img class=\"emoji\" draggable=\"false\" alt=\"(.+?)\" src=\"qrc:\/imports\/twemoji\/.+?"\/>/g, "$1");
|
||||
return value.replace(/<img class=\"emoji\" draggable=\"false\" alt=\"(.+?)\" src=\"qrc:\/imports\/twemoji\/.+?" width=\"[0-9]*\" height=\"[0-9]*\"\/>/g, "$1");
|
||||
}
|
||||
function hasEmoji(value) {
|
||||
let match = value.match(/<img src=\"qrc:\/imports\/twemoji\/.+?" alt=\"(.+?)\" \/>/g)
|
||||
let match = value.match(/<img src=\"qrc:\/imports\/twemoji\/.+?" alt=\"(.+?)\" width=\"[0-9]*\" height=\"[0-9]*\"\ \/>/g)
|
||||
return match && match.length > 0
|
||||
}
|
||||
function getEmojis(value) {
|
||||
return value.match(/<img class=\"emoji\" draggable=\"false\" alt=\"(.+?)\" src=\"qrc:\/imports\/twemoji\/.+?"\/>/g, "$1");
|
||||
return value.match(/<img class=\"emoji\" draggable=\"false\" alt=\"(.+?)\" src=\"qrc:\/imports\/twemoji\/.+?" width=\"[0-9]*\" height=\"[0-9]*\"\/>/g, "$1");
|
||||
}
|
||||
function getEmojiUnicode(shortname) {
|
||||
var _emoji;
|
||||
|
|
|
@ -49,6 +49,7 @@ Theme {
|
|||
property color pillButtonTextColor: almostBlack
|
||||
property color chatReplyCurrentUser: evenDarkerGrey
|
||||
property color topBarChatInfoColor: evenDarkerGrey
|
||||
property color codeBackground: "#2E386B"
|
||||
|
||||
property color buttonForegroundColor: blue
|
||||
property color buttonBackgroundColor: secondaryBackground
|
||||
|
|
|
@ -48,6 +48,7 @@ Theme {
|
|||
property color pillButtonTextColor: white
|
||||
property color chatReplyCurrentUser: lighterDarkGrey
|
||||
property color topBarChatInfoColor: grey
|
||||
property color codeBackground: "#2E386B"
|
||||
|
||||
property color buttonForegroundColor: blue
|
||||
property color buttonBackgroundColor: secondaryBackground
|
||||
|
|
|
@ -35,6 +35,7 @@ QtObject {
|
|||
property color currentUserTextColor
|
||||
property color secondaryBackground
|
||||
property color modalBackground
|
||||
property color codeBackground
|
||||
|
||||
property color buttonForegroundColor
|
||||
property color buttonBackgroundColor
|
||||
|
|
22
ui/main.qml
22
ui/main.qml
|
@ -37,6 +37,28 @@ ApplicationWindow {
|
|||
}
|
||||
visible: true
|
||||
|
||||
Action {
|
||||
shortcut: StandardKey.FullScreen
|
||||
onTriggered: {
|
||||
if (visibility === Window.FullScreen) {
|
||||
showNormal()
|
||||
} else {
|
||||
showFullScreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Action {
|
||||
shortcut: "Ctrl+M"
|
||||
onTriggered: {
|
||||
if (visibility === Window.Minimized) {
|
||||
showNormal()
|
||||
} else {
|
||||
showMinimized()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
// Change the theme to the system theme (dark/light) until we get the
|
||||
// user's saved setting from status-go (after login)
|
||||
|
|
|
@ -79,6 +79,10 @@ Rectangle {
|
|||
return msg
|
||||
}
|
||||
|
||||
function isUploadFilePressed(event) {
|
||||
return (event.key === Qt.Key_U) && (event.modifiers & Qt.ControlModifier) && imageBtn.visible && !imageDialog.visible
|
||||
}
|
||||
|
||||
function onKeyPress(event){
|
||||
if (event.modifiers === Qt.NoModifier && (event.key === Qt.Key_Enter || event.key === Qt.Key_Return)) {
|
||||
if (emojiSuggestions.visible) {
|
||||
|
@ -99,10 +103,42 @@ Rectangle {
|
|||
messageTooLongDialog.open()
|
||||
}
|
||||
|
||||
// handle new line in blockquote
|
||||
if ((event.key === Qt.Key_Enter || event.key === Qt.Key_Return) && (event.modifiers & Qt.ShiftModifier)) {
|
||||
const message = control.extrapolateCursorPosition();
|
||||
if(message.data.startsWith(">") && !message.data.endsWith("\n\n")) {
|
||||
let newMessage = ""
|
||||
if (message.data.endsWith("\n> ")) {
|
||||
newMessage = message.data.substr(0, message.data.lastIndexOf("> ")) + "\n\n"
|
||||
} else {
|
||||
newMessage = message.data + "\n> ";
|
||||
}
|
||||
messageInputField.remove(0, messageInputField.cursorPosition);
|
||||
insertInTextInput(0, Emoji.parse(newMessage));
|
||||
}
|
||||
event.accepted = true
|
||||
}
|
||||
// handle backspace when entering an existing blockquote
|
||||
if ((event.key === Qt.Key_Backspace || event.key === Qt.Key_Delete)) {
|
||||
const message = control.extrapolateCursorPosition();
|
||||
if(message.data.startsWith(">") && message.data.endsWith("\n\n")) {
|
||||
const newMessage = message.data.substr(0, message.data.lastIndexOf("\n")) + "> ";
|
||||
messageInputField.remove(0, messageInputField.cursorPosition);
|
||||
insertInTextInput(0, Emoji.parse(newMessage));
|
||||
event.accepted = true
|
||||
}
|
||||
}
|
||||
|
||||
if ((event.key === Qt.Key_V) && (event.modifiers & Qt.ControlModifier)) {
|
||||
paste = true;
|
||||
}
|
||||
|
||||
// ⌘⇧U
|
||||
if (isUploadFilePressed(event)) {
|
||||
imageBtn.clicked()
|
||||
event.accepted = true
|
||||
}
|
||||
|
||||
if (event.key === Qt.Key_Down) {
|
||||
suggestionsBox.listView.incrementCurrentIndex()
|
||||
return emojiSuggestions.listView.incrementCurrentIndex()
|
||||
|
@ -118,6 +154,12 @@ Rectangle {
|
|||
isColonPressed = (event.key === Qt.Key_Colon) && (event.modifiers & Qt.ShiftModifier);
|
||||
}
|
||||
|
||||
function wrapSelection(wrapWith) {
|
||||
if (messageInputField.selectionStart - messageInputField.selectionEnd === 0) return
|
||||
insertInTextInput(messageInputField.selectionStart, wrapWith);
|
||||
insertInTextInput(messageInputField.selectionEnd, wrapWith);
|
||||
messageInputField.deselect()
|
||||
}
|
||||
|
||||
function onRelease(event) {
|
||||
// the text doesn't get registered to the textarea fast enough
|
||||
|
@ -160,7 +202,7 @@ Rectangle {
|
|||
|
||||
if (madeChanges) {
|
||||
messageInputField.remove(0, messageInputField.length);
|
||||
insertInTextInput(0, Emoji.parse(words.join(' '), '26x26'));
|
||||
insertInTextInput(0, Emoji.parse(words.join(' ')));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,7 +211,7 @@ Rectangle {
|
|||
function extrapolateCursorPosition() {
|
||||
// we need only the message part to be html
|
||||
const text = chatsModel.plainText(Emoji.deparse(messageInputField.text));
|
||||
const plainText = Emoji.parse(text, '26x26');
|
||||
const plainText = Emoji.parse(text);
|
||||
|
||||
var bracketEvent = false;
|
||||
var length = 0;
|
||||
|
@ -258,7 +300,7 @@ Rectangle {
|
|||
.replace(shortname, encodedCodePoint)
|
||||
.replace(/ /g, " ");
|
||||
messageInputField.remove(0, messageInputField.cursorPosition);
|
||||
insertInTextInput(0, Emoji.parse(newMessage, '26x26'));
|
||||
insertInTextInput(0, Emoji.parse(newMessage));
|
||||
emojiSuggestions.close()
|
||||
emojiEvent = false
|
||||
}
|
||||
|
@ -391,7 +433,7 @@ Rectangle {
|
|||
text = `${left} @${aliasName} ${right}`
|
||||
}
|
||||
|
||||
messageInputField.text = hasEmoji ? Emoji.parse(text, "26x26") : text
|
||||
messageInputField.text = hasEmoji ? Emoji.parse(text) : text
|
||||
messageInputField.cursorPosition = lastAtPosition + aliasName.length + 2
|
||||
suggestionsBox.suggestionsModel.clear()
|
||||
}
|
||||
|
@ -592,11 +634,40 @@ Rectangle {
|
|||
bottomPadding: 12
|
||||
Keys.onPressed: onKeyPress(event)
|
||||
Keys.onReleased: onRelease(event) // gives much more up to date cursorPosition
|
||||
Keys.onShortcutOverride: event.accepted = isUploadFilePressed(event)
|
||||
leftPadding: 0
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
}
|
||||
}
|
||||
Action {
|
||||
shortcut: StandardKey.Bold
|
||||
onTriggered: wrapSelection("**")
|
||||
}
|
||||
Action {
|
||||
shortcut: StandardKey.Italic
|
||||
onTriggered: wrapSelection("*")
|
||||
}
|
||||
Action {
|
||||
shortcut: "Ctrl+Shift+Alt+C"
|
||||
onTriggered: wrapSelection("```")
|
||||
}
|
||||
Action {
|
||||
shortcut: "Ctrl+Shift+C"
|
||||
onTriggered: wrapSelection("`")
|
||||
}
|
||||
Action {
|
||||
shortcut: "Ctrl+Alt+-"
|
||||
onTriggered: wrapSelection("~~")
|
||||
}
|
||||
Action {
|
||||
shortcut: "Ctrl+Shift+X"
|
||||
onTriggered: wrapSelection("~~")
|
||||
}
|
||||
Action {
|
||||
shortcut: "Ctrl+Meta+Space"
|
||||
onTriggered: emojiBtn.clicked()
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
|
|
|
@ -40,7 +40,7 @@ Rectangle {
|
|||
|
||||
StyledText {
|
||||
id: replyText
|
||||
text: Emoji.parse(message, "26x26")
|
||||
text: Emoji.parse(message)
|
||||
anchors.left: replyToUsername.left
|
||||
anchors.top: replyToUsername.bottom
|
||||
anchors.topMargin: 2
|
||||
|
|
|
@ -63,7 +63,7 @@ Popup {
|
|||
emojiSectionsRepeater.itemAt(0).allEmojis = recentEmojis
|
||||
appSettings.recentEmojis = recentEmojis
|
||||
|
||||
popup.emojiSelected(Emoji.parse(encodedIcon, "26x26") + ' ', true) // Adding a space because otherwise, some emojis would fuse since emoji is just a string
|
||||
popup.emojiSelected(Emoji.parse(encodedIcon) + ' ', true) // Adding a space because otherwise, some emojis would fuse since emoji is just a string
|
||||
popup.close()
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,7 @@ Popup {
|
|||
anchors.verticalCenter: searchBox.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: emojiHeader.headerMargin
|
||||
source: "../../../../imports/twemoji/26x26/1f590.png"
|
||||
source: "../../../../imports/twemoji/72x72/1f590.png"
|
||||
|
||||
MouseArea {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
|
|
@ -90,7 +90,7 @@ Item {
|
|||
SVGImage {
|
||||
width: emojiSection.imageWidth
|
||||
height: emojiSection.imageWidth
|
||||
source: "../../imports/twemoji/26x26/" + modelData.filename
|
||||
source: "../../imports/twemoji/72x72/" + modelData.filename
|
||||
|
||||
MouseArea {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
|
|
|
@ -10,7 +10,7 @@ StatusInputListPopup {
|
|||
|
||||
id: emojiSuggestions
|
||||
getImageSource: function (modelData) {
|
||||
return `../../imports/twemoji/26x26/${modelData.unicode}.png`
|
||||
return `../../imports/twemoji/72x72/${modelData.unicode}.png`
|
||||
}
|
||||
getText: function (modelData) {
|
||||
return modelData.shortname
|
||||
|
|
|
@ -11,6 +11,8 @@ Popup {
|
|||
property var getImageSource: function () {}
|
||||
property var getText: function () {}
|
||||
property var onClicked: function () {}
|
||||
property int imageWidth: 22
|
||||
property int imageHeight: 22
|
||||
|
||||
function openPopup(listParam) {
|
||||
modelList = listParam
|
||||
|
@ -62,6 +64,8 @@ Popup {
|
|||
SVGImage {
|
||||
id: image
|
||||
source: popup.getImageSource(modelData)
|
||||
width: popup.imageWidth
|
||||
height: popup.imageHeight
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: Style.current.smallPadding
|
||||
|
|
|
@ -297,9 +297,9 @@ function getDefaultWhiteList() {
|
|||
sub: [],
|
||||
sup: [],
|
||||
strong: [],
|
||||
table: ["width", "border", "align", "valign"],
|
||||
table: ["width", "height", "border", "bgcolor", "cellspacing", "cellpadding", "class"],
|
||||
tbody: ["align", "valign"],
|
||||
td: ["width", "rowspan", "colspan", "align", "valign"],
|
||||
td: ["width", "bgcolor", "rowspan", "colspan", "align", "valign", "class"],
|
||||
tfoot: ["align", "valign"],
|
||||
th: ["width", "rowspan", "colspan", "align", "valign"],
|
||||
thead: ["align", "valign"],
|
||||
|
|
Loading…
Reference in New Issue