diff --git a/src/app/commoncomponents/SharePopup.qml b/src/app/commoncomponents/SharePopup.qml index b2dfe05f80531e6e37a89d0cd0666189bdb6ffca..4c48bcc1d80f4a7fa7337a40c964d83423c01c0b 100644 --- a/src/app/commoncomponents/SharePopup.qml +++ b/src/app/commoncomponents/SharePopup.qml @@ -51,7 +51,7 @@ Popup { anchors.centerIn: parent orientation: ListView.Vertical - spacing: 5 + spacing: 0 width: contentItem.childrenRect.width height: contentHeight @@ -64,45 +64,45 @@ Popup { color: "transparent" } + onCountChanged: { + for (var i = 0; i < count; i++) { + var item = listViewMoreButton.itemAtIndex(i); + item.width = listViewMoreButton.width; + } + } + delegate: ItemDelegate { - width: control.width - height: control.height - - AbstractButton { - id: control - - anchors.centerIn: parent - height: JamiTheme.chatViewFooterRealButtonSize + 10 - - text: modelData.toolTip - - contentItem: RowLayout { - Rectangle { - id: image - width: 26 - height: 26 - radius: 5 - color: JamiTheme.transparentColor - ResponsiveImage { - anchors.fill: parent - source: modelData.iconSrc - color: control.hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor - } - } - Text { - text: control.text - color: control.hovered ? JamiTheme.chatViewFooterImgHoverColor : "#7f7f7f" + id: control + + text: modelData.toolTip + + contentItem: RowLayout { + Rectangle { + id: image + width: 26 + height: 26 + radius: 5 + color: JamiTheme.transparentColor + ResponsiveImage { + anchors.fill: parent + source: modelData.iconSrc + color: control.hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor } } - background: Rectangle { - color: control.hovered ? JamiTheme.showMoreButtonOpenColor : JamiTheme.transparentColor + Text { + Layout.alignment: Qt.AlignLeft + text: control.text + color: control.hovered ? JamiTheme.chatViewFooterImgHoverColor : "#7f7f7f" } + } + background: Rectangle { + color: control.hovered ? JamiTheme.showMoreButtonOpenColor : JamiTheme.transparentColor + } - action: modelData + action: modelData - onClicked: { - root.close(); - } + onClicked: { + root.close(); } } } diff --git a/src/app/constant/JamiTheme.qml b/src/app/constant/JamiTheme.qml index 7e459c6d836d637115e5d7f81cfb890f2db04b77..3d39ed34afe96cd94799ecf7517f77c2003e62d8 100644 --- a/src/app/constant/JamiTheme.qml +++ b/src/app/constant/JamiTheme.qml @@ -242,7 +242,9 @@ Item { property color showMoreButtonOpenColor: darkTheme ? "#4d4d4d" : "#e5e5e5" property color chatViewFooterSeparateLineColor: darkTheme ? "#5c5c5c" : "#929292" property color chatViewFooterSendButtonColor: darkTheme ? "#03B9E9" : "#005699" + property color chatViewFooterSendButtonDisableColor: darkTheme ? "#191a1c" : "#f0f0f1" property color chatViewFooterSendButtonImgColor: darkTheme ? blackColor : whiteColor + property color chatViewFooterSendButtonImgColorDisable: darkTheme ? "#4d4d4d" : "#cbcbcb" property color chatViewFooterRectangleBorderColor: darkTheme ? "#4d4d4d" : "#e5e5e5" // ChatView Header diff --git a/src/app/mainview/components/ChatView.qml b/src/app/mainview/components/ChatView.qml index 57422b0c345d3ab708518b66dca8f8d1a20b98b2..5e42d6e806a4c374be70ef81342de367ea601c45 100644 --- a/src/app/mainview/components/ChatView.qml +++ b/src/app/mainview/components/ChatView.qml @@ -304,7 +304,9 @@ Rectangle { } onHeightChanged: { - Qt.callLater(loader.item.scrollToBottom); + if (loader.item != null) { + Qt.callLater(loader.item.scrollToBottom); + } } Layout.alignment: Qt.AlignHCenter diff --git a/src/app/mainview/components/KeyboardShortcutTable.qml b/src/app/mainview/components/KeyboardShortcutTable.qml index d5288c44dae7320d2db631033a174ee0ff2a7fc0..b8dbf51306f5920b136688a639c97c1a7f65f2bf 100644 --- a/src/app/mainview/components/KeyboardShortcutTable.qml +++ b/src/app/mainview/components/KeyboardShortcutTable.qml @@ -255,6 +255,16 @@ Window { shortcut2: "" description: qsTr("Ordered list") } + ListElement { + shortcut: "Shift + Alt + T" + shortcut2: "" + description: qsTr("Show Formatting") + } + ListElement { + shortcut: "Shift + Alt + P" + shortcut2: "" + description: qsTr("Show Preview") + } } Rectangle { diff --git a/src/app/mainview/components/MessageBar.qml b/src/app/mainview/components/MessageBar.qml index 6ac36c8d91c64faf8e0b4880cde2fb46aa8ccd0b..0bbeb60d20c22e9d5dd06bf91eeb55462ad00644 100644 --- a/src/app/mainview/components/MessageBar.qml +++ b/src/app/mainview/components/MessageBar.qml @@ -36,7 +36,7 @@ Rectangle { property alias text: textArea.text property var textAreaObj: textArea property real marginSize: JamiTheme.messageBarMarginSize - property bool sendButtonVisibility: false + property bool sendButtonVisibility: true property bool animate: false property bool showDefault: !UtilsAdapter.getAppValue(Settings.Key.ShowSendOption) property bool showTypo: UtilsAdapter.getAppValue(Settings.Key.ShowMardownOption) @@ -57,12 +57,12 @@ Rectangle { signal emojiButtonClicked color: JamiTheme.transparentColor - height: showTypo || multiLine ? textArea.height + 25 + 3 * marginSize : textArea.height + marginSize + height: showTypo || multiLine ? textArea.height + 25 + 3 * marginSize + 1 : textArea.height + marginSize + 1 ComboBox { id: showMoreButton visible: !CurrentConversation.isSip - width: CurrentConversation.isSip? 0 : JamiTheme.chatViewFooterButtonSize + width: CurrentConversation.isSip ? 0 : JamiTheme.chatViewFooterButtonSize height: JamiTheme.chatViewFooterButtonSize anchors.leftMargin: marginSize @@ -107,7 +107,7 @@ Rectangle { popup: SharePopup { id: sharePopup - y: -150 + y: -180 x: -20 menuMoreButton: listViewMoreButton.menuMoreButton @@ -161,13 +161,9 @@ Rectangle { id: textArea objectName: "messageBarTextArea" - maxWidth: rectangle.width - messageBarRowLayout.width - 31 - - enabled: !showPreview - + maxWidth: rectangle.width - messageBarRowLayout.width - 35 Layout.row: showTypo || multiLine ? 0 : 1 - Layout.column: showTypo || multiLine ? 0 : 0 - Layout.columnSpan: showTypo || multiLine ? 2 : 1 + Layout.column: 0 // forward activeFocus to the actual text area object onActiveFocusChanged: { @@ -188,39 +184,62 @@ Rectangle { } Layout.maximumHeight: JamiTheme.chatViewFooterTextAreaMaximumHeight - marginSize / 2 - onSendMessagesRequired: sendMessageButtonClicked() + onSendMessagesRequired: { + sendMessageButtonClicked(); + textArea.heightBinding(); + } onTextChanged: MessagesAdapter.userIsComposing(text ? true : false) property var markdownShortCut: { "Bold": function () { - listViewTypoFirst.itemAtIndex(0).action.triggered(); + if (!showPreview) { + listViewTypoFirst.itemAtIndex(0).action.triggered(); + } }, "Italic": function () { - listViewTypoFirst.itemAtIndex(1).action.triggered(); + if (!showPreview) { + listViewTypoFirst.itemAtIndex(1).action.triggered(); + } }, "Barre": function () { - listViewTypoFirst.itemAtIndex(2).action.triggered(); + if (!showPreview) { + listViewTypoFirst.itemAtIndex(2).action.triggered(); + } }, "Heading": function () { - listViewTypoFirst.itemAtIndex(3).action.triggered(); + if (!showPreview) { + listViewTypoFirst.itemAtIndex(3).action.triggered(); + } }, "Link": function () { - listViewTypoSecond.itemAtIndex(0).action.triggered(); + if (!showPreview) { + listViewTypoSecond.itemAtIndex(0).action.triggered(); + } }, "Code": function () { - listViewTypoSecond.itemAtIndex(1).action.triggered(); + if (!showPreview) { + listViewTypoSecond.itemAtIndex(1).action.triggered(); + } }, "Quote": function () { - listViewTypoSecond.itemAtIndex(2).action.triggered(); + if (!showPreview) { + listViewTypoSecond.itemAtIndex(2).action.triggered(); + } }, "Unordered list": function () { - listViewTypoSecond.itemAtIndex(3).action.triggered(); + if (!showPreview) { + listViewTypoSecond.itemAtIndex(3).action.triggered(); + } }, "Ordered list": function () { - listViewTypoSecond.itemAtIndex(4).action.triggered(); + if (!showPreview) { + listViewTypoSecond.itemAtIndex(4).action.triggered(); + } }, "Enter is new line": function () { - listViewTypoSecond.itemAtIndex(5).action.triggered(); + if (!showPreview) { + listViewTypoSecond.itemAtIndex(5).action.triggered(); + } } } @@ -277,6 +296,23 @@ Rectangle { context: Qt.ApplicationShortcut onActivated: textArea.markdownShortCut["Ordered list"]() } + + Shortcut { + sequence: "Shift+Alt+T" + context: Qt.ApplicationShortcut + onActivated: { + showTypo = !showTypo; + } + } + + Shortcut { + sequence: "Shift+Alt+P" + context: Qt.ApplicationShortcut + onActivated: { + showPreview = !showPreview; + textArea.showPreview = showPreview; + } + } } Row { @@ -287,7 +323,7 @@ Rectangle { Layout.alignment: showTypo || multiLine ? Qt.AlignRight : Qt.AlignBottom Layout.columnSpan: showTypo || multiLine ? 2 : 1 Layout.topMargin: marginSize / 2 - Layout.rightMargin: marginSize / 2 + Layout.rightMargin: 0 Row { @@ -298,10 +334,39 @@ Rectangle { id: listViewTypo height: JamiTheme.chatViewFooterButtonSize - function addStyle(text, start, end, char1, char2) { + function isStyle(text, start, end, char1, char2, regex) { + if (char1 === "**") { + return isStarStyle(text, start, end, "bold"); + } + if (char1 === "*") { + return isStarStyle(text, start, end, "italic"); + } + var selectedText = text.substring(start - char1.length, end + char2.length); + return (selectedText.startsWith(char1) && selectedText.endsWith(char2)); + var res = regex.test(text.substring(start - char1.length, end + char2.length)); + return res && start - char1.length >= 0 && end + char2.length <= text.length; + } + + function isStarStyle(text, selectionStart, selectionEnd, type) { + let start = selectionStart; + while (start > 0 && text[start - 1] === "*") { + start--; + } + let end = selectionEnd; + while (end < text.length && text[end] === "*") { + end++; + } + const starCount = Math.min(selectionStart - start, end - selectionEnd); + if (type === "italic") { + return starCount === 1 || starCount === 3; + } + return starCount === 2 || starCount === 3; + } + + function addStyle(text, start, end, char1, char2, regex) { // get the selected text with markdown effect var selectedText = text.substring(start - char1.length, end + char2.length); - if (selectedText.startsWith(char1) && selectedText.endsWith(char2)) { + if (isStyle(text, start, end, char1, char2, regex)) { // If the selected text is already formatted with the given characters, remove them selectedText = text.substring(start, end); root.text = text.substring(0, start - char1.length) + selectedText + text.substring(end + char2.length); @@ -313,8 +378,68 @@ Rectangle { } } - function addPrefixStyle(message, selectionStart, selectionEnd, delimiter, isOrderedList) { + function isPrefixSyle(message, selectionStart, selectionEnd, delimiter, isOrderedList) { + //represents all the selected lines + var multilineSelection; + var newPrefix; + var newSuffix; + var newStartPos; + var newEndPos; + function nextIndexOf(text, char1, startPos) { + return text.indexOf(char1, startPos + 1); + } + + //get the previous index of the multilineSelection text + if (message[selectionStart] === "\n") + newStartPos = message.lastIndexOf('\n', selectionStart - 1); + else + newStartPos = message.lastIndexOf('\n', selectionStart); + + //get the next index of the multilineSelection text + if (message[selectionEnd] === "\n" || message[selectionEnd] === undefined) + newEndPos = selectionEnd; + else + newEndPos = nextIndexOf(message, "\n", selectionEnd); + + //if the text is empty + if (newStartPos === -1) + newStartPos = 0; + newPrefix = message.slice(0, newStartPos); + multilineSelection = message.slice(newStartPos, newEndPos); + newSuffix = message.slice(newEndPos); + var isFirstLineSelected = !multilineSelection.startsWith('\n') || newPrefix === ""; + var getDelimiter_counter = 1; + function getDelimiter() { + return `${getDelimiter_counter++}. `; + } + function getHasCurrentMarkdown() { + const linesQuantity = (multilineSelection.match(/\n/g) || []).length; + const newLinesWithDelimitersQuantity = (multilineSelection.match(new RegExp(`\n${delimiter}`, 'g')) || []).length; + if (newLinesWithDelimitersQuantity === linesQuantity && !isFirstLineSelected) + return true; + return linesQuantity === newLinesWithDelimitersQuantity && multilineSelection.startsWith(delimiter); + } + function getHasCurrentMarkdownBullet() { + const linesQuantity = (multilineSelection.match(/\n/g) || []).length; + const newLinesWithDelimitersQuantity = (multilineSelection.match(/\n\d+\. /g) || []).length; + if (newLinesWithDelimitersQuantity === linesQuantity && !isFirstLineSelected) + return true; + return linesQuantity === newLinesWithDelimitersQuantity && (/^\d\. /).test(multilineSelection); + } + var newValue; + var newStart; + var newEnd; + var count; + var startPos; + var multilineSelectionLength; + if (!isOrderedList) { + return getHasCurrentMarkdown(); + } else { + return getHasCurrentMarkdownBullet(); + } + } + function addPrefixStyle(message, selectionStart, selectionEnd, delimiter, isOrderedList) { //represents all the selected lines var multilineSelection; var newPrefix; @@ -463,8 +588,9 @@ Rectangle { property var iconSrc: JamiResources.bold_black_24dp_svg property var shortcutText: JamiStrings.bold property string shortcutKey: "Ctrl+B" + property bool isStyle: listViewTypo.isStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "**", "**", /\\*\*.+\\*\*/) onTriggered: function clickAction() { - listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "**", "**"); + listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "**", "**", /\\*\*.+\\*\*/); } }, Action { @@ -472,8 +598,9 @@ Rectangle { property var iconSrc: JamiResources.italic_black_24dp_svg property var shortcutText: JamiStrings.italic property string shortcutKey: "Ctrl+I" + property bool isStyle: listViewTypo.isStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "*", "*", /(?:\*.+\*|\*\*\*.+\*\*\*)/) onTriggered: function clickAction() { - listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "*", "*"); + listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "*", "*", /(?:\*.+\*|\*\*\*.+\*\*\*)/); } }, Action { @@ -481,8 +608,9 @@ Rectangle { property var iconSrc: JamiResources.s_barre_black_24dp_svg property var shortcutText: JamiStrings.strikethrough property string shortcutKey: "Shift+Alt+X" + property bool isStyle: listViewTypo.isStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "~~", "~~", /\~\~.+\~\~/) onTriggered: function clickAction() { - listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "~~", "~~"); + listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "~~", "~~", /\~\~.+\~\~/); } }, Action { @@ -490,6 +618,7 @@ Rectangle { property var iconSrc: JamiResources.title_black_24dp_svg property var shortcutText: JamiStrings.title property string shortcutKey: "Ctrl+Alt+H" + property bool isStyle: listViewTypo.isPrefixSyle(root.text, textArea.selectionStart, textArea.selectionEnd, "### ", false) onTriggered: function clickAction() { listViewTypo.addPrefixStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "### ", false); } @@ -499,8 +628,9 @@ Rectangle { property var iconSrc: JamiResources.link_web_black_24dp_svg property var shortcutText: JamiStrings.link property string shortcutKey: "Ctrl+Alt+K" + property bool isStyle: listViewTypo.isStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "[", "](url)", /\[.+\]\(.+\)/) onTriggered: function clickAction() { - listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "[", "](url)"); + listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "[", "](url)", /\[.+\]\(.+\)/); } }, Action { @@ -508,8 +638,9 @@ Rectangle { property var iconSrc: JamiResources.code_black_24dp_svg property var shortcutText: JamiStrings.code property string shortcutKey: "Ctrl+Alt+C" + property bool isStyle: listViewTypo.isStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "```", "```", /\`\`\`.+\`\`\`/) onTriggered: function clickAction() { - listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "```", "```"); + listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "```", "```", /\`\`\`.+\`\`\`/); } } ] @@ -534,8 +665,26 @@ Rectangle { source: modelData.iconSrc focusPolicy: Qt.TabFocus - normalColor: JamiTheme.transparentColor - imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor) + normalColor: { + if (showPreview) { + return JamiTheme.transparentColor; + } else if (modelData.isStyle) { + return JamiTheme.hoveredButtonColor; + } else { + return JamiTheme.transparentColor; + } + } + imageColor: { + if (showPreview) { + return JamiTheme.chatViewFooterImgDisableColor; + } else if (hovered) { + return JamiTheme.chatViewFooterImgHoverColor; + } else if (modelData.isStyle) { + return JamiTheme.chatViewFooterImgHoverColor; + } else { + return JamiTheme.chatViewFooterImgColor; + } + } hoveredColor: JamiTheme.hoveredButtonColor pressedColor: hoveredColor @@ -550,11 +699,6 @@ Rectangle { visible: width > 0 width: showTypo && showTypoSecond ? 2 : 0 - /*Behavior on width { - NumberAnimation { - duration: JamiTheme.longFadeDuration / 2 - } - }*/ Rectangle { anchors.verticalCenter: parent.verticalCenter width: 2 @@ -646,6 +790,7 @@ Rectangle { property var iconSrc: JamiResources.quote_black_24dp_svg property var shortcutText: JamiStrings.quote property string shortcutKey: "Shift+Alt+9" + property bool isStyle: listViewTypo.isPrefixSyle(root.text, textArea.selectionStart, textArea.selectionEnd, "> ", false) onTriggered: function clickAction() { listViewTypo.addPrefixStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "> ", false); } @@ -655,6 +800,7 @@ Rectangle { property var iconSrc: JamiResources.bullet_point_black_24dp_svg property var shortcutText: JamiStrings.unorderedList property string shortcutKey: "Shift+Alt+8" + property bool isStyle: listViewTypo.isPrefixSyle(root.text, textArea.selectionStart, textArea.selectionEnd, "- ", false) onTriggered: function clickAction() { listViewTypo.addPrefixStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "- ", false); } @@ -664,6 +810,7 @@ Rectangle { property var iconSrc: JamiResources.bullet_number_black_24dp_svg property var shortcutText: JamiStrings.orderedList property string shortcutKey: "Shift+Alt+7" + property bool isStyle: listViewTypo.isPrefixSyle(root.text, textArea.selectionStart, textArea.selectionEnd, "", true) onTriggered: function clickAction() { listViewTypo.addPrefixStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "", true); } @@ -676,6 +823,7 @@ Rectangle { property var normalColor: chatViewEnterIsNewLine ? JamiTheme.hoveredButtonColor : JamiTheme.transparentColor property var hasShortcut: false property var shortcutKey: null + property bool isStyle: false onTriggered: function clickAction() { root.chatViewEnterIsNewLine = !root.chatViewEnterIsNewLine; UtilsAdapter.setAppValue(Settings.Key.ChatViewEnterIsNewLine, chatViewEnterIsNewLine); @@ -702,8 +850,30 @@ Rectangle { source: modelData.iconSrc focusPolicy: Qt.TabFocus - normalColor: showPreview ? JamiTheme.transparentColor : (modelData.normalColor != null ? modelData.normalColor : JamiTheme.transparentColor) - imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered ? JamiTheme.chatViewFooterImgHoverColor : (modelData.imageColor != null ? modelData.imageColor : JamiTheme.chatViewFooterImgColor)) + normalColor: { + if (showPreview) { + return JamiTheme.transparentColor; + } else if (modelData.normalColor != null) { + return modelData.normalColor; + } else if (modelData.isStyle) { + return JamiTheme.hoveredButtonColor; + } else { + return JamiTheme.transparentColor; + } + } + imageColor: { + if (showPreview) { + return JamiTheme.chatViewFooterImgDisableColor; + } else if (hovered) { + return JamiTheme.chatViewFooterImgHoverColor; + } else if (modelData.imageColor != null) { + return modelData.imageColor; + } else if (modelData.isStyle) { + return JamiTheme.chatViewFooterImgHoverColor; + } else { + return JamiTheme.chatViewFooterImgColor; + } + } hoveredColor: JamiTheme.hoveredButtonColor pressedColor: hoveredColor @@ -972,7 +1142,7 @@ Rectangle { Rectangle { color: JamiTheme.transparentColor - visible: false //showTypo + visible: showTypo height: 50 width: previewButton.width + marginSize Layout.row: showTypo ? 0 : 0 @@ -995,6 +1165,7 @@ Rectangle { onClicked: { showPreview = !showPreview; + textArea.showPreview = showPreview; } } } @@ -1008,7 +1179,7 @@ Rectangle { anchors.bottom: parent.bottom anchors.right: parent.right - anchors.rightMargin: sendMessageButton.visible ? marginSize : 0 + anchors.rightMargin: sendMessageButton.visible ? marginSize / 2 : 0 anchors.bottomMargin: marginSize / 2 PushButton { @@ -1016,6 +1187,9 @@ Rectangle { objectName: "sendMessageButton" + enabled: sendButtonVisibility + hoverEnabled: enabled + width: scale * JamiTheme.chatViewFooterButtonSize height: JamiTheme.chatViewFooterButtonSize @@ -1030,12 +1204,12 @@ Rectangle { source: JamiResources.send_black_24dp_svg - normalColor: JamiTheme.chatViewFooterSendButtonColor - imageColor: JamiTheme.chatViewFooterSendButtonImgColor + normalColor: enabled ? JamiTheme.chatViewFooterSendButtonColor : JamiTheme.chatViewFooterSendButtonDisableColor + imageColor: enabled ? JamiTheme.chatViewFooterSendButtonImgColor : JamiTheme.chatViewFooterSendButtonImgColorDisable hoveredColor: JamiTheme.buttonTintedBlueHovered pressedColor: hoveredColor - opacity: sendButtonVisibility ? 1 : 0 + opacity: 1 visible: opacity scale: opacity @@ -1047,7 +1221,10 @@ Rectangle { } } - onClicked: sendMessageButtonClicked() + onClicked: { + root.showPreview = false; + sendMessageButtonClicked(); + } } } } diff --git a/src/app/mainview/components/MessageBarTextArea.qml b/src/app/mainview/components/MessageBarTextArea.qml index 46e290f8da393b21b1a4eae3e36d7e327125ef12..c924a4f1abf834106156ec6242225d858033a2ff 100644 --- a/src/app/mainview/components/MessageBarTextArea.qml +++ b/src/app/mainview/components/MessageBarTextArea.qml @@ -22,6 +22,8 @@ import net.jami.Constants 1.1 import net.jami.Enums 1.1 import net.jami.Models 1.1 import "../../commoncomponents" +import QtQuick.Layouts +import SortFilterProxyModel 0.2 JamiFlickable { id: root @@ -36,12 +38,17 @@ JamiFlickable { property alias selectedText: textArea.selectedText property alias selectionStart: textArea.selectionStart property alias selectionEnd: textArea.selectionEnd + property bool showPreview: false ScrollBar.vertical.visible: textArea.text ScrollBar.horizontal.visible: textArea.text signal sendMessagesRequired + function heightBinding() { + textArea.height = Qt.binding(() => textArea.paintedHeight); + } + function selectText(start, end) { textArea.select(start, end); } @@ -71,11 +78,72 @@ JamiFlickable { } interactive: true - attachedFlickableMoving: contentHeight > height || root.moving + attachedFlickableMoving: textAreaPreview.height > height || textArea.height > height || root.moving + + contentHeight: showPreview ? textAreaPreview.height : textArea.height + + onShowPreviewChanged: { + if (showPreview) { + textAreaPreview.height = textArea.lineCount === 1 ? textArea.height : textAreaPreview.paintedHeight; + } + heightBinding(); + } + + TextArea { + id: textAreaPreview + + onWidthChanged: root.height = this.height + + overwriteMode: false + readOnly: true + + height: textArea.lineCount === 1 ? textArea.height : this.paintedHeight + width: textArea.width + + visible: showPreview + leftPadding: JamiTheme.scrollBarHandleSize + rightPadding: JamiTheme.scrollBarHandleSize + topPadding: 0 + bottomPadding: 0 + + Connections { + target: textArea + function onTextChanged() { + MessagesAdapter.parseMessage("", textArea.text, false, "", ""); + } + } + + Connections { + target: MessagesAdapter + function onMessageParsed(messageId, messageText) { + if (messageId === "") { + textAreaPreview.text = messageText; + } + } + } + + verticalAlignment: TextEdit.AlignVCenter + + font.pointSize: JamiTheme.textFontSize + 2 + font.hintingPreference: Font.PreferNoHinting + + color: JamiTheme.textColor + wrapMode: TextEdit.Wrap + textFormat: TextEdit.RichText + placeholderTextColor: JamiTheme.messageBarPlaceholderTextColor + horizontalAlignment: Text.AlignLeft + + background: Rectangle { + border.width: 0 + color: "transparent" + } + } TextArea.flickable: TextArea { id: textArea + visible: !showPreview + leftPadding: JamiTheme.scrollBarHandleSize rightPadding: JamiTheme.scrollBarHandleSize topPadding: 0 @@ -83,6 +151,8 @@ JamiFlickable { persistentSelection: true + height: this.paintedHeight + verticalAlignment: TextEdit.AlignVCenter font.pointSize: JamiTheme.textFontSize + 2 @@ -97,7 +167,7 @@ JamiFlickable { background: Rectangle { border.width: 0 - color: JamiTheme.transparentColor + color: "transparent" } onReleased: function (event) { @@ -129,7 +199,8 @@ JamiFlickable { } else if (keyEvent.key === Qt.Key_Enter || keyEvent.key === Qt.Key_Return) { const isEnterNewLine = UtilsAdapter.getAppValue(Settings.Key.ChatViewEnterIsNewLine); const isShiftPressed = (keyEvent.modifiers & Qt.ShiftModifier); - if ((isEnterNewLine && isShiftPressed) || (!isEnterNewLine && !isShiftPressed)) { + const isCtrlPressed = (keyEvent.modifiers & Qt.ControlModifier); + if (!isEnterNewLine && !isShiftPressed || isCtrlPressed) { root.sendMessagesRequired(); keyEvent.accepted = true; } diff --git a/src/app/messagesadapter.cpp b/src/app/messagesadapter.cpp index 8e3fb83bbe9447e1524e7f6c409cb45db4033f63..0b77e51b6e7793a93d258f26ae5bf238804b9a1d 100644 --- a/src/app/messagesadapter.cpp +++ b/src/app/messagesadapter.cpp @@ -449,6 +449,10 @@ MessagesAdapter::onNewInteraction(const QString& convUid, void MessagesAdapter::onMessageParsed(const QString& messageId, const QString& parsed) { + if (messageId.isEmpty()) { + Q_EMIT messageParsed(messageId, parsed); + return; + } const QString& convId = lrcInstance_->get_selectedConvUid(); const QString& accId = lrcInstance_->get_currentAccountId(); auto& conversation = lrcInstance_->getConversationFromConvUid(convId, accId);