From 83039abc1b4ed9cdd7d9fbdbc6e6f9be187ba8da Mon Sep 17 00:00:00 2001 From: lcoursodon Date: Thu, 6 Jul 2023 14:48:03 -0400 Subject: [PATCH] TextEditor: General upgrade Implement new design Add multiline button Use correct color and implement dark theme GitLab: #1096 Change-Id: I5699c81fbc41e50300ca8b32b93ee47cd17ceee1 --- resources/icons/Preview_Black_24dp.svg | 14 + resources/icons/Shift-Enter_Black_24dp.svg | 7 + resources/icons/more_Menu_Black_24dp.svg | 13 + src/app/appsettingsmanager.h | 1 + src/app/commoncomponents/MarkdownPopup.qml | 2 +- src/app/commoncomponents/SharePopup.qml | 134 ++ src/app/constant/JamiStrings.qml | 7 +- src/app/constant/JamiTheme.qml | 18 +- src/app/mainview/components/ChatView.qml | 5 + .../mainview/components/ChatViewFooter.qml | 11 +- .../mainview/components/ChatViewHeader.qml | 3 - .../mainview/components/JamiPushButton.qml | 2 +- src/app/mainview/components/MessageBar.qml | 1640 +++++++++-------- .../components/MessageBarTextArea.qml | 12 +- .../mainview/components/MessageListView.qml | 6 +- src/app/mainview/components/Searchbar.qml | 14 +- src/app/messagesadapter.h | 1 + 17 files changed, 1133 insertions(+), 757 deletions(-) create mode 100644 resources/icons/Preview_Black_24dp.svg create mode 100644 resources/icons/Shift-Enter_Black_24dp.svg create mode 100644 resources/icons/more_Menu_Black_24dp.svg create mode 100644 src/app/commoncomponents/SharePopup.qml diff --git a/resources/icons/Preview_Black_24dp.svg b/resources/icons/Preview_Black_24dp.svg new file mode 100644 index 00000000..6f674ba2 --- /dev/null +++ b/resources/icons/Preview_Black_24dp.svg @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/resources/icons/Shift-Enter_Black_24dp.svg b/resources/icons/Shift-Enter_Black_24dp.svg new file mode 100644 index 00000000..4c54a845 --- /dev/null +++ b/resources/icons/Shift-Enter_Black_24dp.svg @@ -0,0 +1,7 @@ + + + + + diff --git a/resources/icons/more_Menu_Black_24dp.svg b/resources/icons/more_Menu_Black_24dp.svg new file mode 100644 index 00000000..02a4b156 --- /dev/null +++ b/resources/icons/more_Menu_Black_24dp.svg @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/src/app/appsettingsmanager.h b/src/app/appsettingsmanager.h index eba192e3..7397df79 100644 --- a/src/app/appsettingsmanager.h +++ b/src/app/appsettingsmanager.h @@ -60,6 +60,7 @@ extern const QString defaultDownloadPath; X(PositionShareLimit, true) \ X(FlipSelf, true) \ X(ShowMardownOption, false) \ + X(ChatViewEnterIsNewLine, false) \ X(ShowSendOption, false) /* diff --git a/src/app/commoncomponents/MarkdownPopup.qml b/src/app/commoncomponents/MarkdownPopup.qml index 67c72737..2411fc1b 100644 --- a/src/app/commoncomponents/MarkdownPopup.qml +++ b/src/app/commoncomponents/MarkdownPopup.qml @@ -67,7 +67,7 @@ Popup { focusPolicy: Qt.TabFocus normalColor: JamiTheme.chatViewFooterListColor - imageColor: JamiTheme.chatViewFooterImgColor + imageColor: JamiTheme.chatViewFooterImgHoverColor hoveredColor: JamiTheme.showMoreButtonOpenColor pressedColor: hoveredColor diff --git a/src/app/commoncomponents/SharePopup.qml b/src/app/commoncomponents/SharePopup.qml new file mode 100644 index 00000000..b2dfe05f --- /dev/null +++ b/src/app/commoncomponents/SharePopup.qml @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2023 Savoir-faire Linux Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import Qt.labs.platform +import Qt5Compat.GraphicalEffects +import net.jami.Models 1.1 +import net.jami.Adapters 1.1 +import net.jami.Constants 1.1 +import "../mainview/components" + +Popup { + id: root + padding: 0 + property list menuMoreButton + + height: childrenRect.height + width: childrenRect.width + + focus: true + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside + + Rectangle { + id: rect + + color: JamiTheme.primaryBackgroundColor + border.color: JamiTheme.chatViewFooterRectangleBorderColor + border.width: 2 + radius: 5 + height: listViewMoreButton.childrenRect.height + 16 + width: listViewMoreButton.childrenRect.width + 16 + + ListView { + id: listViewMoreButton + + anchors.centerIn: parent + orientation: ListView.Vertical + + spacing: 5 + + width: contentItem.childrenRect.width + height: contentHeight + + model: menuMoreButton + + Rectangle { + z: -1 + anchors.fill: parent + color: "transparent" + } + + 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" + } + } + background: Rectangle { + color: control.hovered ? JamiTheme.showMoreButtonOpenColor : JamiTheme.transparentColor + } + + action: modelData + + onClicked: { + root.close(); + } + } + } + } + } + + background: Rectangle { + anchors.fill: parent + color: JamiTheme.transparentColor + radius: 5 + z: -1 + } + + enter: Transition { + NumberAnimation { + properties: "opacity" + from: 0.0 + to: 1.0 + duration: JamiTheme.shortFadeDuration + } + } + exit: Transition { + NumberAnimation { + properties: "opacity" + from: 1.0 + to: 0.0 + duration: JamiTheme.shortFadeDuration + } + } +} diff --git a/src/app/constant/JamiStrings.qml b/src/app/constant/JamiStrings.qml index 251adc7b..5ca12f22 100644 --- a/src/app/constant/JamiStrings.qml +++ b/src/app/constant/JamiStrings.qml @@ -790,8 +790,8 @@ Item { property string addEmoji: qsTr("Add emoji") property string moreEmojis: qsTr("more emojis") property string sendFile: qsTr("Send file") - property string leaveAudioMessage: qsTr("Leave audio message") - property string leaveVideoMessage: qsTr("Leave video message") + property string leaveAudioMessage: qsTr("Audio message") + property string leaveVideoMessage: qsTr("Video message") property string showMore: qsTr("Show more") property string showLess: qsTr("Show less") @@ -806,7 +806,8 @@ Item { property string orderedList: qsTr("Ordered list") property string showFormating: qsTr("Show Formating") property string hideFormating: qsTr("Hide Formating") - + property string shiftEnterNewLine: qsTr("Press Shift+Enter to insert a new line") + property string enterNewLine: qsTr("Press Enter to insert a new line") property string send: qsTr("Send") property string remove: qsTr("Remove") property string replyTo: qsTr("Reply to") diff --git a/src/app/constant/JamiTheme.qml b/src/app/constant/JamiTheme.qml index 2974c991..d0b082eb 100644 --- a/src/app/constant/JamiTheme.qml +++ b/src/app/constant/JamiTheme.qml @@ -219,6 +219,7 @@ Item { property color fileInTimestampColor: darkTheme ? "#999" : "#555" property color chatviewBgColor: darkTheme ? bgDarkMode_ : whiteColor property color bgInvitationRectColor: darkTheme ? "#222222" : whiteColor + property color messageBarPlaceholderTextColor: darkTheme ? "#909090" : "#7e7e7e" property color placeholderTextColor: darkTheme ? "#7a7a7a" : "black" //Qt.rgba(0, 0, 0, 0.2) property color placeholderTextColorWhite: "#cccccc" property color inviteHoverColor: darkTheme ? blackColor : whiteColor @@ -233,11 +234,14 @@ Item { // ChatView Footer property color chatViewFooterListColor: darkTheme ? blackColor : "#E5E5E5" - property color chatViewFooterImgColor: darkTheme ? whiteColor : blackColor - property color showMoreButtonOpenColor: darkTheme ? "#123F4A" : "#CCCCCC" + property color chatViewFooterImgHoverColor: darkTheme ? whiteColor : blackColor + property color chatViewFooterImgColor: darkTheme ? "#909090" : "#7e7e7e" + property color chatViewFooterImgDisableColor: darkTheme ? "#4d4d4d" : "#cbcbcb" + property color showMoreButtonOpenColor: darkTheme ? "#4d4d4d" : "#e5e5e5" property color chatViewFooterSeparateLineColor: darkTheme ? "#5c5c5c" : "#929292" property color chatViewFooterSendButtonColor: darkTheme ? "#03B9E9" : "#005699" property color chatViewFooterSendButtonImgColor: darkTheme ? blackColor : whiteColor + property color chatViewFooterRectangleBorderColor: darkTheme ? "#4d4d4d" : "#e5e5e5" // ChatView Header property real chatViewHeaderButtonRadius: 5 @@ -299,7 +303,7 @@ Item { // Sizes property real mainViewLeftPaneMinWidth: 300 - property real mainViewPaneMinWidth: 430 + property real mainViewPaneMinWidth: 490 property real qrCodeImageSize: 256 property real splitViewHandlePreferredWidth: 4 property real indicatorFontSize: calcSize(6) @@ -433,14 +437,14 @@ Item { property real chatViewHairLineSize: 1 property real chatViewMaximumWidth: 900 property real chatViewHeaderPreferredHeight: 64 - property real chatViewFooterPreferredHeight: 50 - property real chatViewFooterMaximumHeight: 280 + property real chatViewFooterPreferredHeight: 35 + property real chatViewFooterMaximumHeight: 315 property real chatViewFooterRowSpacing: 4 property real chatViewFooterButtonSize: 36 property real chatViewFooterRealButtonSize: 26 property real chatViewFooterButtonIconSize: 48 property real chatViewFooterButtonRadius: 5 - property real chatViewFooterTextAreaMaximumHeight: 130 + property real chatViewFooterTextAreaMaximumHeight: 260 property real chatViewScrollToBottomButtonBottomMargin: 8 property real usernameBlockFontSize: calcSize(12) @@ -581,7 +585,7 @@ Item { property int keyboardShortcutDelegateSize: 50 // Main application spec - property real mainViewMinWidth: 430 + property real mainViewMinWidth: 490 property real mainViewMinHeight: 500 property real wizardViewMinWidth: 500 diff --git a/src/app/mainview/components/ChatView.qml b/src/app/mainview/components/ChatView.qml index 3005fca0..57422b0c 100644 --- a/src/app/mainview/components/ChatView.qml +++ b/src/app/mainview/components/ChatView.qml @@ -263,6 +263,7 @@ Rectangle { currentIndex: CurrentConversation.isRequest || CurrentConversation.needsSyncing Loader { + id: loader active: CurrentConversation.id !== "" sourceComponent: MessageListView { DropArea { @@ -302,6 +303,10 @@ Rectangle { return CurrentConversation.isSwarm || CurrentConversation.isTemporary; } + onHeightChanged: { + Qt.callLater(loader.item.scrollToBottom); + } + Layout.alignment: Qt.AlignHCenter Layout.fillWidth: true Layout.preferredHeight: implicitHeight diff --git a/src/app/mainview/components/ChatViewFooter.qml b/src/app/mainview/components/ChatViewFooter.qml index f388fd6f..8fe83bd3 100644 --- a/src/app/mainview/components/ChatViewFooter.qml +++ b/src/app/mainview/components/ChatViewFooter.qml @@ -25,10 +25,10 @@ import "../../commoncomponents" Rectangle { id: root - property alias textInput: messageBar.textAreaObj property string previousConvId property string previousAccountId + property bool showTypo: messageBar.showTypo function setFilePathsToSend(filePaths) { for (var index = 0; index < filePaths.length; ++index) { @@ -96,7 +96,6 @@ Rectangle { ColumnLayout { id: footerColumnLayout - anchors.centerIn: root width: root.width @@ -130,6 +129,8 @@ Rectangle { Layout.alignment: Qt.AlignHCenter Layout.preferredWidth: footerColumnLayout.width + Layout.preferredHeight: height + property var emojiPicker Connections { @@ -156,11 +157,7 @@ Rectangle { } function setXposition() { - if (UtilsAdapter.isRTL) { - return messageBar.width - JamiTheme.emojiPickerWidth; - } else { - return 0; - } + return messageBar.width - JamiTheme.emojiPickerWidth; } function setYposition() { diff --git a/src/app/mainview/components/ChatViewHeader.qml b/src/app/mainview/components/ChatViewHeader.qml index 79b6bc7d..dbf46c8c 100644 --- a/src/app/mainview/components/ChatViewHeader.qml +++ b/src/app/mainview/components/ChatViewHeader.qml @@ -93,9 +93,6 @@ Rectangle { source: JamiResources.back_24dp_svg toolTipText: CurrentConversation.inCall ? JamiStrings.backCall : JamiStrings.hideChat - normalColor: JamiTheme.chatviewBgColor - imageColor: JamiTheme.chatviewButtonColor - onClicked: root.backClicked() } diff --git a/src/app/mainview/components/JamiPushButton.qml b/src/app/mainview/components/JamiPushButton.qml index 9cb2929f..80e11131 100644 --- a/src/app/mainview/components/JamiPushButton.qml +++ b/src/app/mainview/components/JamiPushButton.qml @@ -24,5 +24,5 @@ PushButton { radius: JamiTheme.chatViewHeaderButtonRadius normalColor: JamiTheme.chatviewBgColor - imageColor: JamiTheme.chatviewButtonColor + imageColor: hovered ? JamiTheme.chatviewButtonColor : JamiTheme.chatViewFooterImgColor } diff --git a/src/app/mainview/components/MessageBar.qml b/src/app/mainview/components/MessageBar.qml index 117f6552..5ca657a2 100644 --- a/src/app/mainview/components/MessageBar.qml +++ b/src/app/mainview/components/MessageBar.qml @@ -25,9 +25,14 @@ import net.jami.Enums 1.1 import net.jami.Constants 1.1 import "../../commoncomponents" -ColumnLayout { +Rectangle { id: root + Layout.fillWidth: true + Layout.leftMargin: marginSize + Layout.rightMargin: marginSize + Layout.bottomMargin: marginSize + property alias text: textArea.text property var textAreaObj: textArea property real marginSize: JamiTheme.messageBarMarginSize @@ -35,10 +40,15 @@ ColumnLayout { property bool animate: false property bool showDefault: !UtilsAdapter.getAppValue(Settings.Key.ShowSendOption) property bool showTypo: UtilsAdapter.getAppValue(Settings.Key.ShowMardownOption) + property bool chatViewEnterIsNewLine: UtilsAdapter.getAppValue(Settings.Key.ChatViewEnterIsNewLine) property bool showTypoSecond: false + property bool showPreview: false + property bool multiLine: textArea.tooMuch property int messageBarLayoutMaximumWidth: 486 + readonly property bool isFullScreen: visibility === Window.FullScreen + signal sendMessageButtonClicked signal sendFileButtonClicked signal audioRecordMessageButtonClicked @@ -46,827 +56,997 @@ ColumnLayout { signal showMapClicked signal emojiButtonClicked - spacing: 5 + color: JamiTheme.transparentColor + height: showTypo || multiLine ? textArea.height + 25 + 3 * marginSize : textArea.height + marginSize - Rectangle { - id: messageBarHairLine + ComboBox { + id: showMoreButton + width: JamiTheme.chatViewFooterButtonSize + height: JamiTheme.chatViewFooterButtonSize - Layout.alignment: Qt.AlignTop | Qt.AlignHCenter - Layout.preferredHeight: JamiTheme.chatViewHairLineSize - Layout.fillWidth: true + anchors.leftMargin: marginSize + anchors.bottom: parent.bottom + anchors.bottomMargin: marginSize / 2 - color: JamiTheme.tabbarBorderColor - } - - MessageBarTextArea { - id: textArea - - objectName: "messageBarTextArea" - - // forward activeFocus to the actual text area object - onActiveFocusChanged: { - if (activeFocus) - textAreaObj.forceActiveFocus(); + background: Rectangle { + implicitWidth: showMoreButton.width + implicitHeight: showMoreButton.height + radius: 5 + color: JamiTheme.transparentColor } - placeholderText: JamiStrings.writeTo.arg(CurrentConversation.title) + MaterialToolTip { + id: toolTipMoreButton - Layout.alignment: Qt.AlignVCenter - Layout.fillWidth: true - Layout.leftMargin: marginSize / 2 - Layout.rightMargin: marginSize / 2 - Layout.preferredHeight: { - return JamiTheme.chatViewFooterPreferredHeight > contentHeight ? JamiTheme.chatViewFooterPreferredHeight : contentHeight; + parent: showMoreButton + visible: showMoreButton.hovered && (text.length > 0) + delay: Qt.styleHints.mousePressAndHoldInterval + text: JamiStrings.showMore } - Layout.maximumHeight: JamiTheme.chatViewFooterTextAreaMaximumHeight - marginSize / 2 - onSendMessagesRequired: root.sendMessageButtonClicked() - onTextChanged: MessagesAdapter.userIsComposing(text ? true : false) + indicator: ResponsiveImage { - property var markdownShortCut: { - "Bold": function () { - listViewTypoFirst.itemAtIndex(0).action.triggered(); - }, - "Italic": function () { - listViewTypoFirst.itemAtIndex(1).action.triggered(); - }, - "Barre": function () { - listViewTypoFirst.itemAtIndex(2).action.triggered(); - }, - "Heading": function () { - listViewTypoFirst.itemAtIndex(3).action.triggered(); - }, - "Link": function () { - listViewTypoSecond.itemAtIndex(0).action.triggered(); - }, - "Code": function () { - listViewTypoSecond.itemAtIndex(1).action.triggered(); - }, - "Quote": function () { - listViewTypoSecond.itemAtIndex(2).action.triggered(); - }, - "Unordered list": function () { - listViewTypoSecond.itemAtIndex(3).action.triggered(); - }, - "Ordered list": function () { - listViewTypoSecond.itemAtIndex(4).action.triggered(); + width: 25 + height: 25 + + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + + source: JamiResources.more_menu_black_24dp_svg + + color: JamiTheme.chatViewFooterImgColor + } + + onHoveredChanged: { + if (!sharePopup.opened) { + showMoreButton.indicator.color = hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor; + showMoreButton.background.color = hovered ? JamiTheme.hoveredButtonColor : JamiTheme.transparentColor; } } - Shortcut { - sequence: "Ctrl+B" - context: Qt.ApplicationShortcut - onActivated: textArea.markdownShortCut["Bold"]() - } + popup: SharePopup { + id: sharePopup + y: -150 + x: -20 - Shortcut { - sequence: "Ctrl+I" - context: Qt.ApplicationShortcut - onActivated: textArea.markdownShortCut["Italic"]() - } - - Shortcut { - sequence: "Shift+Alt+X" - context: Qt.ApplicationShortcut - onActivated: textArea.markdownShortCut["Barre"]() - } - - Shortcut { - sequence: "Ctrl+Alt+H" - context: Qt.ApplicationShortcut - onActivated: textArea.markdownShortCut["Heading"]() - } - - Shortcut { - sequence: "Ctrl+Alt+K" - context: Qt.ApplicationShortcut - onActivated: textArea.markdownShortCut["Link"]() - } - - Shortcut { - sequence: "Ctrl+Alt+C" - context: Qt.ApplicationShortcut - onActivated: textArea.markdownShortCut["Code"]() - } - - Shortcut { - sequence: "Shift+Alt+9" - context: Qt.ApplicationShortcut - onActivated: textArea.markdownShortCut["Quote"]() - } - - Shortcut { - sequence: "Shift+Alt+8" - context: Qt.ApplicationShortcut - onActivated: textArea.markdownShortCut["Unordered list"]() - } - - Shortcut { - sequence: "Shift+Alt+7" - context: Qt.ApplicationShortcut - onActivated: textArea.markdownShortCut["Ordered list"]() + menuMoreButton: listViewMoreButton.menuMoreButton } } - Item { - id: messageBar - Layout.fillWidth: true - Layout.preferredHeight: JamiTheme.chatViewFooterButtonSize - Layout.leftMargin: marginSize - Layout.bottomMargin: marginSize + Connections { + target: sharePopup + function onOpenedChanged() { + showMoreButton.indicator.color = (showMoreButton.parent && showMoreButton.parent.hovered) || (sharePopup != null && sharePopup.opened) ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor; + showMoreButton.background.color = (showMoreButton.parent && showMoreButton.parent.hovered) || sharePopup.opened ? JamiTheme.hoveredButtonColor : JamiTheme.transparentColor; + } + } + + Rectangle { + id: rectangle + + anchors.top: parent.top + anchors.left: showMoreButton.right + anchors.right: sendButtonRow.left + anchors.rightMargin: marginSize + anchors.leftMargin: marginSize + + radius: 5 + color: JamiTheme.transparentColor + border.color: JamiTheme.chatViewFooterRectangleBorderColor + border.width: 2 onWidthChanged: { - if (width < messageBarRowLayout.width + sendButtonRow.width + 2 * JamiTheme.preferredMarginSize) { + height = Qt.binding(() => root.height); + if (width < 468) { showTypoSecond = false; } else { - if (width > 2 * messageBarRowLayout.width) { + if (width >= 468) { showTypoSecond = true; } } } - RowLayout { - id: messageBarRowLayout + GridLayout { + id: rowLayout - spacing: JamiTheme.chatViewFooterRowSpacing - anchors.left: parent.left + columns: 2 + rows: 2 + columnSpacing: 0 + rowSpacing: 0 - Row { + anchors.fill: parent - PushButton { - id: typoButton + MessageBarTextArea { + id: textArea - preferredSize: JamiTheme.chatViewFooterButtonSize - imageContainerWidth: 24 - imageContainerHeight: 24 + objectName: "messageBarTextArea" + maxWidth: rectangle.width - messageBarRowLayout.width - 31 - radius: JamiTheme.chatViewFooterButtonRadius + enabled: !showPreview - toolTipText: showTypo ? JamiStrings.hideFormating : JamiStrings.showFormating - source: JamiResources.text_edit_black_24dp_svg + Layout.row: showTypo || multiLine ? 0 : 1 + Layout.column: showTypo || multiLine ? 0 : 0 + Layout.columnSpan: showTypo || multiLine ? 2 : 1 - normalColor: !showTypo ? JamiTheme.chatViewFooterListColor : JamiTheme.showMoreButtonOpenColor - imageColor: JamiTheme.chatViewFooterImgColor - pressedColor: JamiTheme.showMoreButtonOpenColor - hoveredColor: JamiTheme.showMoreButtonOpenColor + // forward activeFocus to the actual text area object + onActiveFocusChanged: { + if (activeFocus) + textAreaObj.forceActiveFocus(); + } - onClicked: { - showTypo = !showTypo; - if (messageBar.width < messageBarLayoutMaximumWidth + sendButtonRow.width + 2 * JamiTheme.preferredMarginSize) - showTypoSecond = false; - if (!showDefault) - showDefault = true; - UtilsAdapter.setAppValue(Settings.Key.ShowMardownOption, showTypo); - UtilsAdapter.setAppValue(Settings.Key.ShowSendOption, !showDefault); - } + placeholderText: JamiStrings.writeTo.arg(CurrentConversation.title) - Rectangle { - visible: showTypo + Layout.alignment: showTypo ? Qt.AlignLeft | Qt.AlignBottom : Qt.AlignBottom + Layout.fillWidth: true + Layout.leftMargin: marginSize / 2 + Layout.topMargin: marginSize / 2 + Layout.bottomMargin: marginSize / 2 + Layout.rightMargin: marginSize / 2 + Layout.preferredHeight: { + JamiTheme.chatViewFooterPreferredHeight > contentHeight ? JamiTheme.chatViewFooterPreferredHeight : contentHeight; + } + Layout.maximumHeight: JamiTheme.chatViewFooterTextAreaMaximumHeight - marginSize / 2 - anchors.fill: parent - anchors.leftMargin: 3 - anchors.rightMargin: -5 - color: JamiTheme.showMoreButtonOpenColor - z: -2 + onSendMessagesRequired: sendMessageButtonClicked() + onTextChanged: MessagesAdapter.userIsComposing(text ? true : false) + + property var markdownShortCut: { + "Bold": function () { + listViewTypoFirst.itemAtIndex(0).action.triggered(); + }, + "Italic": function () { + listViewTypoFirst.itemAtIndex(1).action.triggered(); + }, + "Barre": function () { + listViewTypoFirst.itemAtIndex(2).action.triggered(); + }, + "Heading": function () { + listViewTypoFirst.itemAtIndex(3).action.triggered(); + }, + "Link": function () { + listViewTypoSecond.itemAtIndex(0).action.triggered(); + }, + "Code": function () { + listViewTypoSecond.itemAtIndex(1).action.triggered(); + }, + "Quote": function () { + listViewTypoSecond.itemAtIndex(2).action.triggered(); + }, + "Unordered list": function () { + listViewTypoSecond.itemAtIndex(3).action.triggered(); + }, + "Ordered list": function () { + listViewTypoSecond.itemAtIndex(4).action.triggered(); + }, + "Enter is new line": function () { + listViewTypoSecond.itemAtIndex(5).action.triggered(); } } - Row { - id: listViewTypo - height: JamiTheme.chatViewFooterButtonSize + Shortcut { + sequence: "Ctrl+B" + context: Qt.ApplicationShortcut + onActivated: textArea.markdownShortCut["Bold"]() + } - function addStyle(text, start, end, char1, char2) { - // 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 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); - textArea.selectText(start - char1.length, end - char1.length); - } else { - // Otherwise, add the formatting characters to the selected text - root.text = text.substring(0, start) + char1 + text.substring(start, end) + char2 + text.substring(end); - textArea.selectText(start + char1.length, end + char1.length); - } - } + Shortcut { + sequence: "Ctrl+I" + context: Qt.ApplicationShortcut + onActivated: textArea.markdownShortCut["Italic"]() + } - function addPrefixStyle(message, selectionStart, selectionEnd, delimiter, isOrderedList) { + Shortcut { + sequence: "Shift+Alt+X" + context: Qt.ApplicationShortcut + onActivated: textArea.markdownShortCut["Barre"]() + } - //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); - } + Shortcut { + sequence: "Ctrl+Alt+H" + context: Qt.ApplicationShortcut + onActivated: textArea.markdownShortCut["Heading"]() + } - //get the previous index of the multilineSelection text - if (message[selectionStart] === "\n") - newStartPos = message.lastIndexOf('\n', selectionStart - 1); - else - newStartPos = message.lastIndexOf('\n', selectionStart); + Shortcut { + sequence: "Ctrl+Alt+K" + context: Qt.ApplicationShortcut + onActivated: textArea.markdownShortCut["Link"]() + } - //get the next index of the multilineSelection text - if (message[selectionEnd] === "\n" || message[selectionEnd] === undefined) - newEndPos = selectionEnd; - else - newEndPos = nextIndexOf(message, "\n", selectionEnd); + Shortcut { + sequence: "Ctrl+Alt+C" + context: Qt.ApplicationShortcut + onActivated: textArea.markdownShortCut["Code"]() + } - //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) { - if (getHasCurrentMarkdown()) { + Shortcut { + sequence: "Shift+Alt+9" + context: Qt.ApplicationShortcut + onActivated: textArea.markdownShortCut["Quote"]() + } - // clear first line from delimiter - if (isFirstLineSelected) - multilineSelection = multilineSelection.slice(delimiter.length); - newValue = newPrefix + multilineSelection.replace(new RegExp(`\n${delimiter}`, 'g'), '\n') + newSuffix; - count = 0; - if (isFirstLineSelected) - count++; - count += (multilineSelection.match(/\n/g) || []).length; - newStart = Math.max(selectionStart - delimiter.length, 0); - newEnd = Math.max(selectionEnd - (delimiter.length * count), 0); - } else { - newValue = newPrefix + multilineSelection.replace(/\n/g, `\n${delimiter}`) + newSuffix; - count = 0; - if (isFirstLineSelected) { - newValue = delimiter + newValue; - count++; - } - count += (multilineSelection.match(new RegExp('\\n', 'g')) || []).length; - newStart = selectionStart + delimiter.length; - newEnd = selectionEnd + (delimiter.length * count); - } - } else if (getHasCurrentMarkdownBullet()) { - if (message[selectionStart] === "\n") - startPos = message.lastIndexOf('\n', selectionStart - 1) + 1; - else - startPos = message.lastIndexOf('\n', selectionStart) + 1; - newStart = startPos; - multilineSelection = multilineSelection.replace(/^\d+\.\s/gm, ''); - newValue = newPrefix + multilineSelection + newSuffix; - multilineSelectionLength = multilineSelection.length; + Shortcut { + sequence: "Shift+Alt+8" + context: Qt.ApplicationShortcut + onActivated: textArea.markdownShortCut["Unordered list"]() + } - //if the first line is not selected, we need to remove the first "\n" of multilineSelection - if (newStart) - multilineSelectionLength = multilineSelection.length - 1; - newEnd = Math.max(newStart + multilineSelectionLength, 0); - } else { - if (message[selectionStart] === "\n") - startPos = message.lastIndexOf('\n', selectionStart - 1) + 1; - else - startPos = message.lastIndexOf('\n', selectionStart) + 1; - newStart = startPos; - - // if no text is selected - if (selectionStart === selectionEnd) - newStart = newStart + 3; - if (isFirstLineSelected) - multilineSelection = getDelimiter() + multilineSelection; - const selectionArr = Array.from(multilineSelection); - for (var i = 0; i < selectionArr.length; i++) { - if (selectionArr[i] === '\n') - selectionArr[i] = `\n${getDelimiter()}`; - } - multilineSelection = selectionArr.join(''); - newValue = newPrefix + multilineSelection + newSuffix; - multilineSelectionLength = multilineSelection.length; - - //if the first line is not selected, we meed to remove the first "\n" of multilineSelection - if (startPos) - multilineSelectionLength = multilineSelection.length - 1; - newEnd = Math.max(startPos + multilineSelectionLength, 0); - } - root.text = newValue; - textArea.selectText(newStart, newEnd); - } - - ListView { - id: listViewTypoFirst - - objectName: "listViewTypoFirst" - - visible: width > 0 - width: showTypo ? contentWidth + 2 * leftMargin : 0 - - Behavior on width { - NumberAnimation { - duration: JamiTheme.longFadeDuration / 2 - } - } - - height: JamiTheme.chatViewFooterButtonSize - orientation: ListView.Horizontal - interactive: false - leftMargin: 10 - rightMargin: 10 - spacing: 10 - - Rectangle { - anchors.fill: parent - color: JamiTheme.chatViewFooterListColor - z: -1 - } - - property list menuTypoActionsFirst: [ - Action { - id: boldAction - property var iconSrc: JamiResources.bold_black_24dp_svg - property var shortcutText: JamiStrings.bold - property string shortcutKey: "Ctrl+B" - - onTriggered: function clickAction() { - listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "**", "**"); - } - }, - Action { - id: italicAction - property var iconSrc: JamiResources.italic_black_24dp_svg - property var shortcutText: JamiStrings.italic - property string shortcutKey: "Ctrl+I" - onTriggered: function clickAction() { - listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "*", "*"); - } - }, - Action { - id: strikethroughAction - property var iconSrc: JamiResources.s_barre_black_24dp_svg - property var shortcutText: JamiStrings.strikethrough - property string shortcutKey: "Shift+Alt+X" - onTriggered: function clickAction() { - listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "~~", "~~"); - } - }, - Action { - id: titleAction - property var iconSrc: JamiResources.title_black_24dp_svg - property var shortcutText: JamiStrings.title - property string shortcutKey: "Ctrl+Alt+H" - onTriggered: function clickAction() { - listViewTypo.addPrefixStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "### ", false); - } - } - ] - - model: menuTypoActionsFirst - - delegate: PushButton { - anchors.verticalCenter: parent.verticalCenter - - preferredSize: JamiTheme.chatViewFooterRealButtonSize - imageContainerWidth: 15 - imageContainerHeight: 15 - radius: 5 - - toolTipText: modelData.shortcutText - shortcutKey: modelData.shortcutKey - hasShortcut: true - - source: modelData.iconSrc - focusPolicy: Qt.TabFocus - - normalColor: JamiTheme.chatViewFooterListColor - imageColor: JamiTheme.chatViewFooterImgColor - hoveredColor: JamiTheme.showMoreButtonOpenColor - pressedColor: hoveredColor - - action: modelData - } - } - - Rectangle { - - height: JamiTheme.chatViewFooterButtonSize - color: JamiTheme.chatViewFooterListColor - visible: width > 0 - width: showTypo && showTypoSecond ? 2 : 0 - - Behavior on width { - NumberAnimation { - duration: JamiTheme.longFadeDuration / 2 - } - } - - Rectangle { - anchors.verticalCenter: parent.verticalCenter - width: 2 - height: JamiTheme.chatViewFooterButtonSize / 2 - color: JamiTheme.chatViewFooterSeparateLineColor - } - } - - Rectangle { - z: -1 - radius: 0 - color: JamiTheme.chatViewFooterListColor - width: JamiTheme.chatViewFooterButtonSize - height: JamiTheme.chatViewFooterButtonSize - - visible: showTypo && !showTypoSecond - - ComboBox { - id: showMoreTypoButton - width: JamiTheme.chatViewFooterRealButtonSize - height: width - anchors.verticalCenter: parent.verticalCenter - - MaterialToolTip { - id: toolTip - - parent: showMoreTypoButton - visible: showMoreTypoButton.hovered && (text.length > 0) - delay: Qt.styleHints.mousePressAndHoldInterval - text: JamiStrings.showMore - } - - background: Rectangle { - implicitWidth: showMoreTypoButton.width - implicitHeight: showMoreTypoButton.height - radius: 5 - color: showMoreTypoButton.popup.opened || showMoreTypoButton.hovered ? JamiTheme.showMoreButtonOpenColor : JamiTheme.chatViewFooterListColor - } - - indicator: ResponsiveImage { - containerHeight: 20 - containerWidth: 20 - width: 18 - height: 18 - - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - - source: JamiResources.more_vert_24dp_svg - - color: JamiTheme.chatViewFooterImgColor - } - - popup: MarkdownPopup { - y: 1.5 * parent.height - x: -parent.width * 3 - width: 190 - height: JamiTheme.chatViewFooterButtonSize - - menuTypoActionsSecond: listViewTypoSecond.menuTypoActionsSecond - } - } - } - - ListView { - id: listViewTypoSecond - visible: width > 0 - width: showTypo && showTypoSecond ? contentWidth + 2 * leftMargin : 0 - - Behavior on width { - NumberAnimation { - duration: JamiTheme.longFadeDuration / 2 - } - } - - height: JamiTheme.chatViewFooterButtonSize - orientation: ListView.Horizontal - interactive: false - leftMargin: 10 - rightMargin: 10 - spacing: 10 - - Rectangle { - anchors.fill: parent - color: JamiTheme.chatViewFooterListColor - z: -1 - } - - property list menuTypoActionsSecond: [ - Action { - id: linkAction - property var iconSrc: JamiResources.link_web_black_24dp_svg - property var shortcutText: JamiStrings.link - property string shortcutKey: "Ctrl+Alt+K" - onTriggered: function clickAction() { - listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "[", "](url)"); - } - }, - Action { - id: codeAction - property var iconSrc: JamiResources.code_black_24dp_svg - property var shortcutText: JamiStrings.code - property string shortcutKey: "Ctrl+Alt+C" - onTriggered: function clickAction() { - listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "```", "```"); - } - }, - Action { - id: quoteAction - property var iconSrc: JamiResources.quote_black_24dp_svg - property var shortcutText: JamiStrings.quote - property string shortcutKey: "Shift+Alt+9" - onTriggered: function clickAction() { - listViewTypo.addPrefixStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "> ", false); - } - }, - Action { - id: unorderedListAction - property var iconSrc: JamiResources.bullet_point_black_24dp_svg - property var shortcutText: JamiStrings.unorderedList - property string shortcutKey: "Shift+Alt+8" - onTriggered: function clickAction() { - listViewTypo.addPrefixStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "- ", false); - } - }, - Action { - id: orderedListAction - property var iconSrc: JamiResources.bullet_number_black_24dp_svg - property var shortcutText: JamiStrings.orderedList - property string shortcutKey: "Shift+Alt+7" - onTriggered: function clickAction() { - listViewTypo.addPrefixStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "", true); - } - } - ] - - model: menuTypoActionsSecond - - delegate: PushButton { - anchors.verticalCenter: parent.verticalCenter - - preferredSize: JamiTheme.chatViewFooterRealButtonSize - imageContainerWidth: 20 - imageContainerHeight: 20 - radius: 5 - - toolTipText: modelData.shortcutText - shortcutKey: modelData.shortcutKey - hasShortcut: true - source: modelData.iconSrc - focusPolicy: Qt.TabFocus - - normalColor: JamiTheme.chatViewFooterListColor - imageColor: JamiTheme.chatViewFooterImgColor - hoveredColor: JamiTheme.showMoreButtonOpenColor - pressedColor: hoveredColor - - action: modelData - } - } + Shortcut { + sequence: "Shift+Alt+7" + context: Qt.ApplicationShortcut + onActivated: textArea.markdownShortCut["Ordered list"]() } } Row { + id: messageBarRowLayout - ListView { - id: listViewAction + Layout.row: showTypo || multiLine ? 1 : 1 + Layout.column: showTypo || multiLine ? 0 : 1 + Layout.alignment: showTypo || multiLine ? Qt.AlignRight : Qt.AlignBottom + Layout.columnSpan: showTypo || multiLine ? 2 : 1 + Layout.topMargin: marginSize / 2 + Layout.rightMargin: marginSize / 2 - width: contentWidth + 2 * leftMargin + Row { - Behavior on width { - NumberAnimation { - duration: JamiTheme.longFadeDuration / 2 - } - } + anchors.bottom: parent.bottom + anchors.bottomMargin: marginSize / 2 - height: JamiTheme.chatViewFooterButtonSize - orientation: ListView.Horizontal - interactive: false + Row { + id: listViewTypo + height: JamiTheme.chatViewFooterButtonSize - leftMargin: 10 - rightMargin: 10 - spacing: 10 - - Rectangle { - anchors.fill: parent - color: JamiTheme.chatViewFooterListColor - z: -1 - } - - property list menuActions: [ - Action { - id: sendFile - property var iconSrc: JamiResources.link_black_24dp_svg - property var toolTip: JamiStrings.sendFile - property bool show: true - property bool needWebEngine: false - property bool needVideoDevice: false - property bool noSip: false - onTriggered: function clickAction() { - sendFileButtonClicked(); - } - }, - Action { - id: addEmoji - property var iconSrc: JamiResources.emoji_black_24dp_svg - property var toolTip: JamiStrings.addEmoji - property bool show: true - property bool needWebEngine: true - property bool needVideoDevice: false - property bool noSip: true - onTriggered: function clickAction() { - emojiButtonClicked(); - } - }, - Action { - id: leaveAudioMessage - property var iconSrc: JamiResources.message_audio_black_24dp_svg - property var toolTip: JamiStrings.leaveAudioMessage - property bool show: false - property bool needWebEngine: false - property bool needVideoDevice: false - property bool noSip: false - onTriggered: function clickAction() { - audioRecordMessageButtonClicked(); - } - }, - Action { - id: leaveVideoMessage - property var iconSrc: JamiResources.message_video_black_24dp_svg - property var toolTip: JamiStrings.leaveVideoMessage - property bool show: false - property bool needWebEngine: false - property bool needVideoDevice: true - property bool noSip: false - onTriggered: function clickAction() { - videoRecordMessageButtonClicked(); - } - }, - Action { - id: shareLocation - property var iconSrc: JamiResources.localisation_sharing_send_pin_svg - property var toolTip: JamiStrings.shareLocation - property bool show: false - property bool needWebEngine: true - property bool needVideoDevice: false - property bool noSip: false - onTriggered: function clickAction() { - showMapClicked(); + function addStyle(text, start, end, char1, char2) { + // 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 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); + textArea.selectText(start - char1.length, end - char1.length); + } else { + // Otherwise, add the formatting characters to the selected text + root.text = text.substring(0, start) + char1 + text.substring(start, end) + char2 + text.substring(end); + textArea.selectText(start + char1.length, end + char1.length); } } - ] - ListModel { - id: listActions - Component.onCompleted: { - for (var i = 0; i < listViewAction.menuActions.length; i++) { - append({ - "menuAction": listViewAction.menuActions[i] - }); + function addPrefixStyle(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) { + if (getHasCurrentMarkdown()) { + + // clear first line from delimiter + if (isFirstLineSelected) + multilineSelection = multilineSelection.slice(delimiter.length); + newValue = newPrefix + multilineSelection.replace(new RegExp(`\n${delimiter}`, 'g'), '\n') + newSuffix; + count = 0; + if (isFirstLineSelected) + count++; + count += (multilineSelection.match(/\n/g) || []).length; + newStart = Math.max(selectionStart - delimiter.length, 0); + newEnd = Math.max(selectionEnd - (delimiter.length * count), 0); + } else { + newValue = newPrefix + multilineSelection.replace(/\n/g, `\n${delimiter}`) + newSuffix; + count = 0; + if (isFirstLineSelected) { + newValue = delimiter + newValue; + count++; + } + count += (multilineSelection.match(new RegExp('\\n', 'g')) || []).length; + newStart = selectionStart + delimiter.length; + newEnd = selectionEnd + (delimiter.length * count); + } + } else if (getHasCurrentMarkdownBullet()) { + if (message[selectionStart] === "\n") + startPos = message.lastIndexOf('\n', selectionStart - 1) + 1; + else + startPos = message.lastIndexOf('\n', selectionStart) + 1; + newStart = startPos; + multilineSelection = multilineSelection.replace(/^\d+\.\s/gm, ''); + newValue = newPrefix + multilineSelection + newSuffix; + multilineSelectionLength = multilineSelection.length; + + //if the first line is not selected, we need to remove the first "\n" of multilineSelection + if (newStart) + multilineSelectionLength = multilineSelection.length - 1; + newEnd = Math.max(newStart + multilineSelectionLength, 0); + } else { + if (message[selectionStart] === "\n") + startPos = message.lastIndexOf('\n', selectionStart - 1) + 1; + else + startPos = message.lastIndexOf('\n', selectionStart) + 1; + newStart = startPos; + + // if no text is selected + if (selectionStart === selectionEnd) + newStart = newStart + 3; + if (isFirstLineSelected) + multilineSelection = getDelimiter() + multilineSelection; + const selectionArr = Array.from(multilineSelection); + for (var i = 0; i < selectionArr.length; i++) { + if (selectionArr[i] === '\n') + selectionArr[i] = `\n${getDelimiter()}`; + } + multilineSelection = selectionArr.join(''); + newValue = newPrefix + multilineSelection + newSuffix; + multilineSelectionLength = multilineSelection.length; + + //if the first line is not selected, we meed to remove the first "\n" of multilineSelection + if (startPos) + multilineSelectionLength = multilineSelection.length - 1; + newEnd = Math.max(startPos + multilineSelectionLength, 0); + } + root.text = newValue; + textArea.selectText(newStart, newEnd); + } + + ListView { + id: listViewTypoFirst + + objectName: "listViewTypoFirst" + + visible: width > 0 + width: showTypo ? contentWidth + 2 * leftMargin : 0 + + Behavior on width { + NumberAnimation { + duration: JamiTheme.longFadeDuration / 2 + } + } + + height: JamiTheme.chatViewFooterButtonSize + orientation: ListView.Horizontal + interactive: false + leftMargin: 5 + rightMargin: 5 + spacing: 5 + + property list menuTypoActionsFirst: [ + Action { + id: boldAction + property var iconSrc: JamiResources.bold_black_24dp_svg + property var shortcutText: JamiStrings.bold + property string shortcutKey: "Ctrl+B" + onTriggered: function clickAction() { + listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "**", "**"); + } + }, + Action { + id: italicAction + property var iconSrc: JamiResources.italic_black_24dp_svg + property var shortcutText: JamiStrings.italic + property string shortcutKey: "Ctrl+I" + onTriggered: function clickAction() { + listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "*", "*"); + } + }, + Action { + id: strikethroughAction + property var iconSrc: JamiResources.s_barre_black_24dp_svg + property var shortcutText: JamiStrings.strikethrough + property string shortcutKey: "Shift+Alt+X" + onTriggered: function clickAction() { + listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "~~", "~~"); + } + }, + Action { + id: titleAction + property var iconSrc: JamiResources.title_black_24dp_svg + property var shortcutText: JamiStrings.title + property string shortcutKey: "Ctrl+Alt+H" + onTriggered: function clickAction() { + listViewTypo.addPrefixStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "### ", false); + } + }, + Action { + id: linkAction + property var iconSrc: JamiResources.link_web_black_24dp_svg + property var shortcutText: JamiStrings.link + property string shortcutKey: "Ctrl+Alt+K" + onTriggered: function clickAction() { + listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "[", "](url)"); + } + }, + Action { + id: codeAction + property var iconSrc: JamiResources.code_black_24dp_svg + property var shortcutText: JamiStrings.code + property string shortcutKey: "Ctrl+Alt+C" + onTriggered: function clickAction() { + listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "```", "```"); + } + } + ] + + model: menuTypoActionsFirst + + delegate: PushButton { + anchors.verticalCenter: parent.verticalCenter + + preferredSize: JamiTheme.chatViewFooterRealButtonSize + imageContainerWidth: 15 + imageContainerHeight: 15 + radius: 5 + + hoverEnabled: !showPreview + enabled: !showPreview + + toolTipText: modelData.shortcutText + shortcutKey: modelData.shortcutKey + hasShortcut: true + + source: modelData.iconSrc + focusPolicy: Qt.TabFocus + + normalColor: JamiTheme.transparentColor + imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor) + hoveredColor: JamiTheme.hoveredButtonColor + pressedColor: hoveredColor + + action: modelData + } + } + + Rectangle { + + height: JamiTheme.chatViewFooterButtonSize + color: JamiTheme.transparentColor + visible: width > 0 + width: showTypo && showTypoSecond ? 2 : 0 + + /*Behavior on width { + NumberAnimation { + duration: JamiTheme.longFadeDuration / 2 + } + }*/ + Rectangle { + anchors.verticalCenter: parent.verticalCenter + width: 2 + height: JamiTheme.chatViewFooterButtonSize / 2 + color: showPreview ? JamiTheme.chatViewFooterImgDisableColor : JamiTheme.chatViewFooterSeparateLineColor + } + } + + Rectangle { + z: -1 + radius: 0 + color: JamiTheme.transparentColor + width: JamiTheme.chatViewFooterButtonSize + height: JamiTheme.chatViewFooterButtonSize + + visible: showTypo && !showTypoSecond + + ComboBox { + id: showMoreTypoButton + width: JamiTheme.chatViewFooterRealButtonSize + height: width + anchors.verticalCenter: parent.verticalCenter + + enabled: !showPreview + hoverEnabled: !showPreview + + MaterialToolTip { + id: toolTip + + parent: showMoreTypoButton + visible: showMoreTypoButton.hovered && (text.length > 0) + delay: Qt.styleHints.mousePressAndHoldInterval + text: JamiStrings.showMore + } + + background: Rectangle { + implicitWidth: showMoreTypoButton.width + implicitHeight: showMoreTypoButton.height + radius: 5 + color: showPreview ? JamiTheme.transparentColor : (parent && parent.hovered ? JamiTheme.hoveredButtonColor : JamiTheme.transparentColor) + } + + indicator: ResponsiveImage { + containerHeight: 20 + containerWidth: 20 + width: 18 + height: 18 + + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + + source: JamiResources.more_vert_24dp_svg + + color: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (parent && parent.hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor) + } + + popup: MarkdownPopup { + y: 1.5 * parent.height + x: -parent.width * 2 + width: 155 + height: JamiTheme.chatViewFooterButtonSize + + menuTypoActionsSecond: listViewTypoSecond.menuTypoActionsSecond + } + } + } + + ListView { + id: listViewTypoSecond + visible: width > 0 + width: showTypo && showTypoSecond ? contentWidth + 2 * leftMargin : 0 + + height: JamiTheme.chatViewFooterButtonSize + orientation: ListView.Horizontal + interactive: false + leftMargin: 10 + rightMargin: 10 + spacing: 10 + + Rectangle { + anchors.fill: parent + color: JamiTheme.transparentColor + z: -1 + } + + property list menuTypoActionsSecond: [ + Action { + id: quoteAction + property var iconSrc: JamiResources.quote_black_24dp_svg + property var shortcutText: JamiStrings.quote + property string shortcutKey: "Shift+Alt+9" + onTriggered: function clickAction() { + listViewTypo.addPrefixStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "> ", false); + } + }, + Action { + id: unorderedListAction + property var iconSrc: JamiResources.bullet_point_black_24dp_svg + property var shortcutText: JamiStrings.unorderedList + property string shortcutKey: "Shift+Alt+8" + onTriggered: function clickAction() { + listViewTypo.addPrefixStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "- ", false); + } + }, + Action { + id: orderedListAction + property var iconSrc: JamiResources.bullet_number_black_24dp_svg + property var shortcutText: JamiStrings.orderedList + property string shortcutKey: "Shift+Alt+7" + onTriggered: function clickAction() { + listViewTypo.addPrefixStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "", true); + } + }, + Action { + id: shiftEnterActiom + property var iconSrc: JamiResources.shift_enter_black_24dp_svg + property var shortcutText: chatViewEnterIsNewLine ? JamiStrings.enterNewLine : JamiStrings.shiftEnterNewLine + property var imageColor: chatViewEnterIsNewLine ? JamiTheme.chatViewFooterImgHoverColor : "#7f7f7f" + property var normalColor: chatViewEnterIsNewLine ? JamiTheme.hoveredButtonColor : JamiTheme.transparentColor + property var hasShortcut: false + property var shortcutKey: null + onTriggered: function clickAction() { + root.chatViewEnterIsNewLine = !root.chatViewEnterIsNewLine; + UtilsAdapter.setAppValue(Settings.Key.ChatViewEnterIsNewLine, chatViewEnterIsNewLine); + } + } + ] + + model: menuTypoActionsSecond + + delegate: PushButton { + anchors.verticalCenter: parent.verticalCenter + + preferredSize: JamiTheme.chatViewFooterRealButtonSize + imageContainerWidth: 20 + imageContainerHeight: 20 + radius: 5 + + hoverEnabled: !showPreview + enabled: !showPreview + + toolTipText: modelData.shortcutText + shortcutKey: modelData.shortcutKey + hasShortcut: modelData.hasShortcut != null ? modelData.hasShortcut : true + 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)) + hoveredColor: JamiTheme.hoveredButtonColor + pressedColor: hoveredColor + + action: modelData } } } - model: SortFilterProxyModel { - sourceModel: listActions - filters: [ - ExpressionFilter { - expression: menuAction.show === true - enabled: root.showDefault - }, - ExpressionFilter { - expression: menuAction.needWebEngine === false - enabled: !WITH_WEBENGINE - }, - ExpressionFilter { - expression: menuAction.noSip === true - enabled: CurrentConversation.isSip - }, - ExpressionFilter { - expression: menuAction.needVideoDevice === false - enabled: VideoDevices.listSize === 0 - } - ] - } - - delegate: PushButton { - id: buttonDelegate - anchors.verticalCenter: parent ? parent.verticalCenter : undefined - preferredSize: JamiTheme.chatViewFooterRealButtonSize - imageContainerWidth: 20 - imageContainerHeight: 20 - radius: 5 - - toolTipText: modelData.toolTip - source: modelData.iconSrc - - normalColor: JamiTheme.chatViewFooterListColor - imageColor: JamiTheme.chatViewFooterImgColor - hoveredColor: JamiTheme.showMoreButtonOpenColor - pressedColor: hoveredColor - - action: modelData - } - } - - Rectangle { - z: -1 - radius: 0 - color: showMoreButton.normalColor - width: JamiTheme.chatViewFooterButtonSize / 2 - height: JamiTheme.chatViewFooterButtonSize - PushButton { - id: showMoreButton - anchors.left: parent.left + id: typoButton preferredSize: JamiTheme.chatViewFooterButtonSize - imageContainerWidth: 20 - imageContainerHeight: 20 + imageContainerWidth: 24 + imageContainerHeight: 24 radius: JamiTheme.chatViewFooterButtonRadius - toolTipText: showDefault ? JamiStrings.showMore : JamiStrings.showLess + hoverEnabled: !showPreview + enabled: !showPreview - source: JamiResources.more_vert_24dp_svg + toolTipText: showTypo ? JamiStrings.hideFormating : JamiStrings.showFormating + source: JamiResources.text_edit_black_24dp_svg - normalColor: showDefault ? JamiTheme.chatViewFooterListColor : JamiTheme.showMoreButtonOpenColor - imageColor: JamiTheme.chatViewFooterImgColor - pressedColor: JamiTheme.showMoreButtonOpenColor - hoveredColor: JamiTheme.showMoreButtonOpenColor + normalColor: showPreview ? JamiTheme.transparentColor : (showTypo ? JamiTheme.hoveredButtonColor : JamiTheme.transparentColor) + imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered || showTypo ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor) + hoveredColor: JamiTheme.hoveredButtonColor + pressedColor: hoveredColor onClicked: { - showDefault = !showDefault; - if (showTypo) - showTypo = false; + showTypo = !showTypo; + if (messageBar.width < messageBarLayoutMaximumWidth + sendButtonRow.width + 2 * JamiTheme.preferredMarginSize) + showTypoSecond = false; + if (!showDefault) + showDefault = true; + if (showTypo) { + root.chatViewEnterIsNewLine = true; + UtilsAdapter.setAppValue(Settings.Key.ChatViewEnterIsNewLine, true); + } else { + root.chatViewEnterIsNewLine = false; + UtilsAdapter.setAppValue(Settings.Key.ChatViewEnterIsNewLine, false); + } UtilsAdapter.setAppValue(Settings.Key.ShowMardownOption, showTypo); UtilsAdapter.setAppValue(Settings.Key.ShowSendOption, !showDefault); } } } - } - } - Row { - id: sendButtonRow - spacing: JamiTheme.chatViewFooterRowSpacing - anchors.right: parent.right - anchors.rightMargin: sendMessageButton.visible ? marginSize : 0 + Row { - PushButton { - id: sendMessageButton + anchors.bottom: parent.bottom + anchors.bottomMargin: marginSize / 2 - objectName: "sendMessageButton" + ListView { + id: listViewAction - width: scale * JamiTheme.chatViewFooterButtonSize - height: JamiTheme.chatViewFooterButtonSize + width: contentWidth + 2 * leftMargin - radius: JamiTheme.chatViewFooterButtonRadius - preferredSize: JamiTheme.chatViewFooterButtonIconSize - 6 - imageContainerWidth: 25 - imageContainerHeight: 25 + Behavior on width { + NumberAnimation { + duration: JamiTheme.longFadeDuration / 2 + } + } - toolTipText: JamiStrings.send + height: JamiTheme.chatViewFooterButtonSize + orientation: ListView.Horizontal + interactive: false - mirror: UtilsAdapter.isRTL + leftMargin: 5 + rightMargin: 5 + spacing: 5 - source: JamiResources.send_black_24dp_svg + property list menuActions: [ + Action { + id: sendFile + property var iconSrc: JamiResources.link_black_24dp_svg + property var toolTip: JamiStrings.sendFile + property bool show: true + property bool needWebEngine: false + property bool needVideoDevice: false + property bool noSip: false + onTriggered: function clickAction() { + sendFileButtonClicked(); + } + }, + Action { + id: addEmoji + property var iconSrc: JamiResources.emoji_black_24dp_svg + property var toolTip: JamiStrings.addEmoji + property bool show: true + property bool needWebEngine: true + property bool needVideoDevice: false + property bool noSip: true + onTriggered: function clickAction() { + emojiButtonClicked(); + } + } + ] - normalColor: JamiTheme.chatViewFooterSendButtonColor - imageColor: JamiTheme.chatViewFooterSendButtonImgColor - hoveredColor: JamiTheme.buttonTintedBlueHovered - pressedColor: hoveredColor + ListModel { + id: listActions + Component.onCompleted: { + for (var i = 0; i < listViewAction.menuActions.length; i++) { + append({ + "menuAction": listViewAction.menuActions[i] + }); + } + } + } - opacity: sendButtonVisibility ? 1 : 0 - visible: opacity - scale: opacity + model: SortFilterProxyModel { + sourceModel: listActions + filters: [ + ExpressionFilter { + expression: menuAction.show === true + enabled: root.showDefault + }, + ExpressionFilter { + expression: menuAction.needWebEngine === false + enabled: !WITH_WEBENGINE + }, + ExpressionFilter { + expression: menuAction.noSip === true + enabled: CurrentConversation.isSip + }, + ExpressionFilter { + expression: menuAction.needVideoDevice === false + enabled: VideoDevices.listSize === 0 + } + ] + } - Behavior on opacity { - enabled: animate - NumberAnimation { - duration: JamiTheme.shortFadeDuration - easing.type: Easing.InOutQuad + delegate: PushButton { + id: buttonDelegate + anchors.verticalCenter: parent ? parent.verticalCenter : undefined + preferredSize: JamiTheme.chatViewFooterButtonSize + imageContainerWidth: 25 + imageContainerHeight: 25 + radius: 5 + + hoverEnabled: !showPreview + enabled: !showPreview + + toolTipText: modelData.toolTip + source: modelData.iconSrc + + normalColor: JamiTheme.transparentColor + imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor) + hoveredColor: JamiTheme.hoveredButtonColor + pressedColor: hoveredColor + + action: modelData + } + } + + ListView { + id: listViewMoreButton + + width: 0 + Behavior on width { + NumberAnimation { + duration: JamiTheme.longFadeDuration / 2 + } + } + + height: JamiTheme.chatViewFooterButtonSize + orientation: ListView.Horizontal + interactive: false + + leftMargin: 10 + rightMargin: 10 + spacing: 10 + + property list menuMoreButton: [ + Action { + id: leaveAudioMessage + property var iconSrc: JamiResources.message_audio_black_24dp_svg + property var toolTip: JamiStrings.leaveAudioMessage + property bool show: false + property bool needWebEngine: false + property bool needVideoDevice: false + property bool noSip: false + onTriggered: function clickAction() { + audioRecordMessageButtonClicked(); + } + }, + Action { + id: leaveVideoMessage + property var iconSrc: JamiResources.message_video_black_24dp_svg + property var toolTip: JamiStrings.leaveVideoMessage + property bool show: false + property bool needWebEngine: false + property bool needVideoDevice: true + property bool noSip: false + onTriggered: function clickAction() { + videoRecordMessageButtonClicked(); + } + }, + Action { + id: shareLocation + property var iconSrc: JamiResources.localisation_sharing_send_pin_svg + property var toolTip: JamiStrings.shareLocation + property bool show: false + property bool needWebEngine: true + property bool needVideoDevice: false + property bool noSip: false + onTriggered: function clickAction() { + showMapClicked(); + } + } + ] + + ListModel { + id: listMoreButton + Component.onCompleted: { + for (var i = 0; i < listViewMoreButton.menuMoreButton.length; i++) { + append({ + "menuAction": listViewMoreButton.menuMoreButton[i] + }); + } + } + } + + model: SortFilterProxyModel { + sourceModel: listMoreButton + filters: [ + ExpressionFilter { + expression: menuAction.show === true + enabled: showDefault + }, + ExpressionFilter { + expression: menuAction.needWebEngine === false + enabled: !WITH_WEBENGINE + }, + ExpressionFilter { + expression: menuAction.noSip === true + enabled: CurrentConversation.isSip + }, + ExpressionFilter { + expression: menuAction.needVideoDevice === false + enabled: VideoDevices.listSize === 0 + } + ] + } + + delegate: PushButton { + id: buttonDelegateMoreButton + anchors.verticalCenter: parent ? parent.verticalCenter : undefined + preferredSize: JamiTheme.chatViewFooterRealButtonSize + imageContainerWidth: 20 + imageContainerHeight: 20 + radius: 5 + + toolTipText: modelData.toolTip + source: modelData.iconSrc + + normalColor: JamiTheme.chatViewFooterListColor + imageColor: JamiTheme.chatViewFooterImgHoverColor + hoveredColor: JamiTheme.hoveredButtonColor + pressedColor: hoveredColor + + action: modelData + } } } + } - onClicked: root.sendMessageButtonClicked() + Rectangle { + color: JamiTheme.transparentColor + visible: false //showTypo + height: 50 + width: previewButton.width + marginSize + Layout.row: showTypo ? 0 : 0 + Layout.column: showTypo ? 1 : 1 + + PushButton { + id: previewButton + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: marginSize + preferredSize: JamiTheme.chatViewFooterButtonSize + imageContainerWidth: 25 + imageContainerHeight: 25 + radius: 5 + source: JamiResources.preview_black_24dp_svg + normalColor: showPreview ? hoveredColor : JamiTheme.transparentColor + imageColor: (hovered || showPreview) ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor + hoveredColor: JamiTheme.hoveredButtonColor + pressedColor: hoveredColor + + onClicked: { + showPreview = !showPreview; + } + } } } } + + Row { + id: sendButtonRow + + spacing: JamiTheme.chatViewFooterRowSpacing + + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.rightMargin: sendMessageButton.visible ? marginSize : 0 + anchors.bottomMargin: marginSize / 2 + + PushButton { + id: sendMessageButton + + objectName: "sendMessageButton" + + width: scale * JamiTheme.chatViewFooterButtonSize + height: JamiTheme.chatViewFooterButtonSize + + radius: JamiTheme.chatViewFooterButtonRadius + preferredSize: JamiTheme.chatViewFooterButtonIconSize - 6 + imageContainerWidth: 25 + imageContainerHeight: 25 + + toolTipText: JamiStrings.send + + mirror: UtilsAdapter.isRTL + + source: JamiResources.send_black_24dp_svg + + normalColor: JamiTheme.chatViewFooterSendButtonColor + imageColor: JamiTheme.chatViewFooterSendButtonImgColor + hoveredColor: JamiTheme.buttonTintedBlueHovered + pressedColor: hoveredColor + + opacity: sendButtonVisibility ? 1 : 0 + visible: opacity + scale: opacity + + Behavior on opacity { + enabled: animate + NumberAnimation { + duration: JamiTheme.shortFadeDuration + easing.type: Easing.InOutQuad + } + } + + onClicked: sendMessageButtonClicked() + } + } } diff --git a/src/app/mainview/components/MessageBarTextArea.qml b/src/app/mainview/components/MessageBarTextArea.qml index 75702f96..46e290f8 100644 --- a/src/app/mainview/components/MessageBarTextArea.qml +++ b/src/app/mainview/components/MessageBarTextArea.qml @@ -19,11 +19,17 @@ import QtQuick import QtQuick.Controls import net.jami.Adapters 1.1 import net.jami.Constants 1.1 +import net.jami.Enums 1.1 +import net.jami.Models 1.1 import "../../commoncomponents" JamiFlickable { id: root + property int maxWidth: 330 + property bool tooMuch: { + return textArea.contentWidth > maxWidth; + } property alias text: textArea.text property var textAreaObj: textArea property alias placeholderText: textArea.placeholderText @@ -86,7 +92,7 @@ JamiFlickable { wrapMode: TextEdit.Wrap selectByMouse: true textFormat: TextEdit.PlainText - placeholderTextColor: JamiTheme.placeholderTextColor + placeholderTextColor: JamiTheme.messageBarPlaceholderTextColor horizontalAlignment: Text.AlignLeft background: Rectangle { @@ -121,7 +127,9 @@ JamiFlickable { MessagesAdapter.editId = CurrentConversation.lastSelfMessageId; keyEvent.accepted = true; } else if (keyEvent.key === Qt.Key_Enter || keyEvent.key === Qt.Key_Return) { - if (!(keyEvent.modifiers & Qt.ShiftModifier)) { + const isEnterNewLine = UtilsAdapter.getAppValue(Settings.Key.ChatViewEnterIsNewLine); + const isShiftPressed = (keyEvent.modifiers & Qt.ShiftModifier); + if ((isEnterNewLine && isShiftPressed) || (!isEnterNewLine && !isShiftPressed)) { root.sendMessagesRequired(); keyEvent.accepted = true; } diff --git a/src/app/mainview/components/MessageListView.qml b/src/app/mainview/components/MessageListView.qml index 8da11323..442685cd 100644 --- a/src/app/mainview/components/MessageListView.qml +++ b/src/app/mainview/components/MessageListView.qml @@ -54,6 +54,10 @@ JamiListView { return false } + function scrollToBottom() { + verticalScrollBar.position = 1 - verticalScrollBar.size; + } + function computeChatview(item, itemIndex) { if (!root) return var rootItem = root.itemAtIndex(0) @@ -277,7 +281,7 @@ JamiListView { anchors.horizontalCenter: root.horizontalCenter visible: 1 - verticalScrollBar.position >= verticalScrollBar.size * 2 - onClicked: verticalScrollBar.position = 1 - verticalScrollBar.size + onClicked: scrollToBottom() } header: Control { diff --git a/src/app/mainview/components/Searchbar.qml b/src/app/mainview/components/Searchbar.qml index 7f575a33..5f68fad6 100644 --- a/src/app/mainview/components/Searchbar.qml +++ b/src/app/mainview/components/Searchbar.qml @@ -76,7 +76,17 @@ Rectangle { hoveredColor: JamiTheme.hoveredButtonColor source: JamiResources.ic_baseline_search_24dp_svg normalColor: "transparent" - imageColor: JamiTheme.chatviewButtonColor + imageColor: { + if (reductionEnabled) { + if (hovered) { + JamiTheme.chatviewButtonColor; + } else { + JamiTheme.chatViewFooterImgColor; + } + } else { + JamiTheme.chatviewButtonColor; + } + } onClicked: root.searchClicked() } @@ -99,7 +109,7 @@ Rectangle { } width: isOpen ? JamiTheme.searchbarSize : 0 - Behavior on width { + Behavior on width { NumberAnimation { duration: 150 } diff --git a/src/app/messagesadapter.h b/src/app/messagesadapter.h index 4a1fc7e1..a70c66d6 100644 --- a/src/app/messagesadapter.h +++ b/src/app/messagesadapter.h @@ -78,6 +78,7 @@ Q_SIGNALS: void moreMessagesLoaded(qint32 loadingRequestId); void timestampUpdated(); void fileCopied(const QString& dest); + void messageParsed(const QString& msgId, const QString& msg); protected: Q_INVOKABLE bool isDocument(const interaction::Type& type);