diff --git a/resources/icons/Preview_Black_24dp.svg b/resources/icons/Preview_Black_24dp.svg new file mode 100644 index 0000000000000000000000000000000000000000..6f674ba26ca8a3884c8ded67041920e74280cfa5 --- /dev/null +++ b/resources/icons/Preview_Black_24dp.svg @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve"> +<g id="noun-overview-4287788" transform="translate(-112.49 -112.51)"> + <path id="Path_272" d="M134.5,133.4l-3.5-3.5c3.3-3.9,2.8-9.8-1.1-13.2c-3.9-3.3-9.8-2.8-13.2,1.1c-3.3,3.9-2.8,9.8,1.1,13.2 + c3.5,2.9,8.6,2.9,12.1,0l3.5,3.5L134.5,133.4z M123.8,131.6c-4.3,0-7.8-3.5-7.8-7.8s3.5-7.8,7.8-7.8c4.3,0,7.8,3.5,7.8,7.8l0,0 + C131.6,128.2,128.1,131.6,123.8,131.6L123.8,131.6z"/> + <path id="Path_273" d="M123.8,119.7c-3.5,0-6.2,1.8-6.2,4.1s2.7,4.1,6.2,4.1c3.5,0,6.2-1.8,6.2-4.1S127.3,119.7,123.8,119.7z + M123.8,126.6c-2.6,0-4.8-1.3-4.8-2.8s2.2-2.8,4.8-2.8c2.6,0,4.8,1.3,4.8,2.8S126.5,126.6,123.8,126.6z"/> + <path id="Path_274" d="M126.1,123.9c0,1.3-1,2.3-2.3,2.3c-1.3,0-2.3-1-2.3-2.3c0-1.3,1-2.3,2.3-2.3 + C125.1,121.6,126.1,122.6,126.1,123.9L126.1,123.9"/> +</g> +</svg> diff --git a/resources/icons/Shift-Enter_Black_24dp.svg b/resources/icons/Shift-Enter_Black_24dp.svg new file mode 100644 index 0000000000000000000000000000000000000000..4c54a845d7e1cf71007f58489c42ae131a1f5b85 --- /dev/null +++ b/resources/icons/Shift-Enter_Black_24dp.svg @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve"> +<path d="M5.8,4.7h12.5c0.7,0,1.2,0.6,1.2,1.2v7.5c0,0.7-0.6,1.2-1.2,1.2h-12l2.9-2.9l-1.8-1.8l-5,5c-0.1,0.1-0.2,0.3-0.3,0.4 + c-0.2,0.5-0.1,1,0.3,1.4l5,5L9.1,20l-2.9-2.9h12c2.1,0,3.7-1.7,3.7-3.7V5.9c0-2.1-1.7-3.7-3.7-3.7H5.8V4.7z"/> +</svg> diff --git a/resources/icons/more_Menu_Black_24dp.svg b/resources/icons/more_Menu_Black_24dp.svg new file mode 100644 index 0000000000000000000000000000000000000000..02a4b156eadc18afd7a0c496c9c8f58643e7916f --- /dev/null +++ b/resources/icons/more_Menu_Black_24dp.svg @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" + viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve"> +<g id="noun-add-929469" transform="translate(-102.6 -102.6)"> + <path id="Path_270" d="M107.5,107.5c-3.9,3.9-3.9,10.2,0,14.1c3.9,3.9,10.2,3.9,14.1,0c3.9-3.9,3.9-10.2,0-14.1 + C117.8,103.6,111.4,103.6,107.5,107.5C107.5,107.5,107.5,107.5,107.5,107.5z M120.5,120.5c-3.3,3.3-8.5,3.3-11.8,0 + c-3.3-3.3-3.3-8.5,0-11.8c3.3-3.3,8.5-3.3,11.8,0C123.7,112,123.7,117.2,120.5,120.5z"/> + <path id="Path_271" d="M114.6,109.8c-0.4,0-0.8,0.4-0.8,0.8c0,0,0,0,0,0v3.1h-3.1c-0.5,0-0.8,0.4-0.8,0.8c0,0.5,0.4,0.8,0.8,0.8 + h3.1v3.1c0,0.4,0.4,0.8,0.8,0.8c0,0,0,0,0,0c0.5,0,0.8-0.4,0.8-0.8v-3.1h3.1c0.5,0,0.8-0.4,0.8-0.8c0-0.4-0.4-0.8-0.8-0.8 + c0,0,0,0,0,0h-3.1v-3.1C115.4,110.2,115.1,109.8,114.6,109.8C114.6,109.8,114.6,109.8,114.6,109.8z"/> +</g> +</svg> diff --git a/src/app/appsettingsmanager.h b/src/app/appsettingsmanager.h index eba192e38f3cbc9426647e3364019ccc876abc07..7397df79451f73495a7ffbdc7dfa4b89e11e9a47 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 67c7273717bb6bda55d1cc310d24f52fe88350b5..2411fc1b383f6ab24e6d01533ba1e71420911bbf 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 0000000000000000000000000000000000000000..b2dfe05f80531e6e37a89d0cd0666189bdb6ffca --- /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 <https://www.gnu.org/licenses/>. + */ +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<Action> 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 251adc7b02dfe806dcd940a5f0d80b5a7bacb18e..5ca12f223d6c761bfb61e48651f2c8c2eb7a39a7 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 2974c9918539fb295ecabd23411e2b85d4a2b566..d0b082eb2546f4d0241a6512c75d6a2a6d651386 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 3005fca04d2206f388c38dcd9288905146947069..57422b0c345d3ab708518b66dca8f8d1a20b98b2 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 f388fd6fd0142bdb3cb039fdd4ac1b2a80be9ad0..8fe83bd33e20b6f7b5ba39e751ee93fc615b6368 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 79b6bc7db87c48e704451acdcc419dd8ebd56c02..dbf46c8c09f8f745b6fb62525e935a0e059cef13 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 9cb2929f6621b3fd32fe52ef3fa5409d5ee2b1d7..80e111310f303e49b5b9d5e82395140592236ac9 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 117f6552259c36c46783effecc3811620117d17c..5ca657a2ada42ccb2bbea9c1a9ab252a376b1f51 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,509 +56,812 @@ 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 - - color: JamiTheme.tabbarBorderColor - } + anchors.leftMargin: marginSize + anchors.bottom: parent.bottom + anchors.bottomMargin: marginSize / 2 - 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; - } - Layout.maximumHeight: JamiTheme.chatViewFooterTextAreaMaximumHeight - marginSize / 2 - - onSendMessagesRequired: root.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(); - } + parent: showMoreButton + visible: showMoreButton.hovered && (text.length > 0) + delay: Qt.styleHints.mousePressAndHoldInterval + text: JamiStrings.showMore } - Shortcut { - sequence: "Ctrl+B" - context: Qt.ApplicationShortcut - onActivated: textArea.markdownShortCut["Bold"]() - } + indicator: ResponsiveImage { - Shortcut { - sequence: "Ctrl+I" - context: Qt.ApplicationShortcut - onActivated: textArea.markdownShortCut["Italic"]() - } + width: 25 + height: 25 - Shortcut { - sequence: "Shift+Alt+X" - context: Qt.ApplicationShortcut - onActivated: textArea.markdownShortCut["Barre"]() - } + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter - Shortcut { - sequence: "Ctrl+Alt+H" - context: Qt.ApplicationShortcut - onActivated: textArea.markdownShortCut["Heading"]() - } + source: JamiResources.more_menu_black_24dp_svg - Shortcut { - sequence: "Ctrl+Alt+K" - context: Qt.ApplicationShortcut - onActivated: textArea.markdownShortCut["Link"]() + color: JamiTheme.chatViewFooterImgColor } - Shortcut { - sequence: "Ctrl+Alt+C" - context: Qt.ApplicationShortcut - onActivated: textArea.markdownShortCut["Code"]() + onHoveredChanged: { + if (!sharePopup.opened) { + showMoreButton.indicator.color = hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor; + showMoreButton.background.color = hovered ? JamiTheme.hoveredButtonColor : JamiTheme.transparentColor; + } } - Shortcut { - sequence: "Shift+Alt+9" - context: Qt.ApplicationShortcut - onActivated: textArea.markdownShortCut["Quote"]() - } + popup: SharePopup { + id: sharePopup + y: -150 + x: -20 - Shortcut { - sequence: "Shift+Alt+8" - context: Qt.ApplicationShortcut - onActivated: textArea.markdownShortCut["Unordered list"]() + menuMoreButton: listViewMoreButton.menuMoreButton } + } - Shortcut { - sequence: "Shift+Alt+7" - context: Qt.ApplicationShortcut - onActivated: textArea.markdownShortCut["Ordered list"]() + 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; } } - Item { - id: messageBar - Layout.fillWidth: true - Layout.preferredHeight: JamiTheme.chatViewFooterButtonSize - Layout.leftMargin: marginSize - Layout.bottomMargin: marginSize + 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) + + 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 + + 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(); } + } - Rectangle { - visible: showTypo + Shortcut { + sequence: "Ctrl+B" + context: Qt.ApplicationShortcut + onActivated: textArea.markdownShortCut["Bold"]() + } - anchors.fill: parent - anchors.leftMargin: 3 - anchors.rightMargin: -5 - color: JamiTheme.showMoreButtonOpenColor - z: -2 - } + 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"]() + } + } + + Row { + id: messageBarRowLayout + + 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 + Row { - id: listViewTypo - height: JamiTheme.chatViewFooterButtonSize - - 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); - } - } - function addPrefixStyle(message, selectionStart, selectionEnd, delimiter, isOrderedList) { + anchors.bottom: parent.bottom + anchors.bottomMargin: marginSize / 2 - //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); - } + Row { + id: listViewTypo + height: JamiTheme.chatViewFooterButtonSize - //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); + 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 { - 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); + // 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); } - } else if (getHasCurrentMarkdownBullet()) { + } + + 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") - startPos = message.lastIndexOf('\n', selectionStart - 1) + 1; + newStartPos = message.lastIndexOf('\n', selectionStart - 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; + newStartPos = message.lastIndexOf('\n', selectionStart); + + //get the next index of the multilineSelection text + if (message[selectionEnd] === "\n" || message[selectionEnd] === undefined) + newEndPos = selectionEnd; 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()}`; + 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++}. `; } - 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); + 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); } - root.text = newValue; - textArea.selectText(newStart, newEnd); - } - ListView { - id: listViewTypoFirst + ListView { + id: listViewTypoFirst - objectName: "listViewTypoFirst" + objectName: "listViewTypoFirst" - visible: width > 0 - width: showTypo ? contentWidth + 2 * leftMargin : 0 + visible: width > 0 + width: showTypo ? contentWidth + 2 * leftMargin : 0 - Behavior on width { - NumberAnimation { - duration: JamiTheme.longFadeDuration / 2 + Behavior on width { + NumberAnimation { + duration: JamiTheme.longFadeDuration / 2 + } + } + + height: JamiTheme.chatViewFooterButtonSize + orientation: ListView.Horizontal + interactive: false + leftMargin: 5 + rightMargin: 5 + spacing: 5 + + property list<Action> 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 } } - height: JamiTheme.chatViewFooterButtonSize - orientation: ListView.Horizontal - interactive: false - leftMargin: 10 - rightMargin: 10 - spacing: 10 + 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 { - anchors.fill: parent - color: JamiTheme.chatViewFooterListColor z: -1 - } + radius: 0 + color: JamiTheme.transparentColor + width: JamiTheme.chatViewFooterButtonSize + height: JamiTheme.chatViewFooterButtonSize - property list<Action> menuTypoActionsFirst: [ - Action { - id: boldAction - property var iconSrc: JamiResources.bold_black_24dp_svg - property var shortcutText: JamiStrings.bold - property string shortcutKey: "Ctrl+B" + visible: showTypo && !showTypoSecond - onTriggered: function clickAction() { - listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "**", "**"); + 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 } - }, - 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, "*", "*"); + + background: Rectangle { + implicitWidth: showMoreTypoButton.width + implicitHeight: showMoreTypoButton.height + radius: 5 + color: showPreview ? JamiTheme.transparentColor : (parent && parent.hovered ? JamiTheme.hoveredButtonColor : JamiTheme.transparentColor) } - }, - 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, "~~", "~~"); + + 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) } - }, - 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); + + popup: MarkdownPopup { + y: 1.5 * parent.height + x: -parent.width * 2 + width: 155 + height: JamiTheme.chatViewFooterButtonSize + + menuTypoActionsSecond: listViewTypoSecond.menuTypoActionsSecond } } - ] + } - model: menuTypoActionsFirst + 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 + } - delegate: PushButton { - anchors.verticalCenter: parent.verticalCenter + property list<Action> 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); + } + } + ] - preferredSize: JamiTheme.chatViewFooterRealButtonSize - imageContainerWidth: 15 - imageContainerHeight: 15 - radius: 5 + model: menuTypoActionsSecond - toolTipText: modelData.shortcutText - shortcutKey: modelData.shortcutKey - hasShortcut: true + delegate: PushButton { + anchors.verticalCenter: parent.verticalCenter - source: modelData.iconSrc - focusPolicy: Qt.TabFocus + preferredSize: JamiTheme.chatViewFooterRealButtonSize + imageContainerWidth: 20 + imageContainerHeight: 20 + radius: 5 - normalColor: JamiTheme.chatViewFooterListColor - imageColor: JamiTheme.chatViewFooterImgColor - hoveredColor: JamiTheme.showMoreButtonOpenColor - pressedColor: hoveredColor + hoverEnabled: !showPreview + enabled: !showPreview - action: modelData + 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 + } } } - Rectangle { + PushButton { + id: typoButton - height: JamiTheme.chatViewFooterButtonSize - color: JamiTheme.chatViewFooterListColor - visible: width > 0 - width: showTypo && showTypoSecond ? 2 : 0 + preferredSize: JamiTheme.chatViewFooterButtonSize + imageContainerWidth: 24 + imageContainerHeight: 24 - Behavior on width { - NumberAnimation { - duration: JamiTheme.longFadeDuration / 2 - } - } + radius: JamiTheme.chatViewFooterButtonRadius - Rectangle { - anchors.verticalCenter: parent.verticalCenter - width: 2 - height: JamiTheme.chatViewFooterButtonSize / 2 - color: JamiTheme.chatViewFooterSeparateLineColor + hoverEnabled: !showPreview + enabled: !showPreview + + toolTipText: showTypo ? JamiStrings.hideFormating : JamiStrings.showFormating + source: JamiResources.text_edit_black_24dp_svg + + 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: { + 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); } } + } - Rectangle { - z: -1 - radius: 0 - color: JamiTheme.chatViewFooterListColor - width: JamiTheme.chatViewFooterButtonSize - height: JamiTheme.chatViewFooterButtonSize + Row { - visible: showTypo && !showTypoSecond + anchors.bottom: parent.bottom + anchors.bottomMargin: marginSize / 2 - ComboBox { - id: showMoreTypoButton - width: JamiTheme.chatViewFooterRealButtonSize - height: width - anchors.verticalCenter: parent.verticalCenter + ListView { + id: listViewAction - MaterialToolTip { - id: toolTip + width: contentWidth + 2 * leftMargin - parent: showMoreTypoButton - visible: showMoreTypoButton.hovered && (text.length > 0) - delay: Qt.styleHints.mousePressAndHoldInterval - text: JamiStrings.showMore + Behavior on width { + NumberAnimation { + duration: JamiTheme.longFadeDuration / 2 } + } - background: Rectangle { - implicitWidth: showMoreTypoButton.width - implicitHeight: showMoreTypoButton.height - radius: 5 - color: showMoreTypoButton.popup.opened || showMoreTypoButton.hovered ? JamiTheme.showMoreButtonOpenColor : JamiTheme.chatViewFooterListColor + height: JamiTheme.chatViewFooterButtonSize + orientation: ListView.Horizontal + interactive: false + + leftMargin: 5 + rightMargin: 5 + spacing: 5 + + property list<Action> 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(); + } } + ] - indicator: ResponsiveImage { - containerHeight: 20 - containerWidth: 20 - width: 18 - height: 18 + ListModel { + id: listActions + Component.onCompleted: { + for (var i = 0; i < listViewAction.menuActions.length; i++) { + append({ + "menuAction": listViewAction.menuActions[i] + }); + } + } + } - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter + 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 + } + ] + } - source: JamiResources.more_vert_24dp_svg + delegate: PushButton { + id: buttonDelegate + anchors.verticalCenter: parent ? parent.verticalCenter : undefined + preferredSize: JamiTheme.chatViewFooterButtonSize + imageContainerWidth: 25 + imageContainerHeight: 25 + radius: 5 - color: JamiTheme.chatViewFooterImgColor - } + hoverEnabled: !showPreview + enabled: !showPreview - popup: MarkdownPopup { - y: 1.5 * parent.height - x: -parent.width * 3 - width: 190 - height: JamiTheme.chatViewFooterButtonSize + toolTipText: modelData.toolTip + source: modelData.iconSrc - menuTypoActionsSecond: listViewTypoSecond.menuTypoActionsSecond - } + normalColor: JamiTheme.transparentColor + imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor) + hoveredColor: JamiTheme.hoveredButtonColor + pressedColor: hoveredColor + + action: modelData } } ListView { - id: listViewTypoSecond - visible: width > 0 - width: showTypo && showTypoSecond ? contentWidth + 2 * leftMargin : 0 + id: listViewMoreButton - Behavior on width { + width: 0 + Behavior on width { NumberAnimation { duration: JamiTheme.longFadeDuration / 2 } @@ -557,83 +870,97 @@ ColumnLayout { 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<Action> 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)"); - } - }, + property list<Action> menuMoreButton: [ Action { - id: codeAction - property var iconSrc: JamiResources.code_black_24dp_svg - property var shortcutText: JamiStrings.code - property string shortcutKey: "Ctrl+Alt+C" + 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() { - listViewTypo.addStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "```", "```"); + audioRecordMessageButtonClicked(); } }, Action { - id: quoteAction - property var iconSrc: JamiResources.quote_black_24dp_svg - property var shortcutText: JamiStrings.quote - property string shortcutKey: "Shift+Alt+9" + 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() { - listViewTypo.addPrefixStyle(root.text, textArea.selectionStart, textArea.selectionEnd, "> ", false); + videoRecordMessageButtonClicked(); } }, Action { - id: unorderedListAction - property var iconSrc: JamiResources.bullet_point_black_24dp_svg - property var shortcutText: JamiStrings.unorderedList - property string shortcutKey: "Shift+Alt+8" + 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() { - 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); + showMapClicked(); } } ] - model: menuTypoActionsSecond + ListModel { + id: listMoreButton + Component.onCompleted: { + for (var i = 0; i < listViewMoreButton.menuMoreButton.length; i++) { + append({ + "menuAction": listViewMoreButton.menuMoreButton[i] + }); + } + } + } - delegate: PushButton { - anchors.verticalCenter: parent.verticalCenter + 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.shortcutText - shortcutKey: modelData.shortcutKey - hasShortcut: true + toolTipText: modelData.toolTip source: modelData.iconSrc - focusPolicy: Qt.TabFocus normalColor: JamiTheme.chatViewFooterListColor - imageColor: JamiTheme.chatViewFooterImgColor - hoveredColor: JamiTheme.showMoreButtonOpenColor + imageColor: JamiTheme.chatViewFooterImgHoverColor + hoveredColor: JamiTheme.hoveredButtonColor pressedColor: hoveredColor action: modelData @@ -642,231 +969,84 @@ ColumnLayout { } } - Row { - - ListView { - id: listViewAction - - width: contentWidth + 2 * leftMargin - - Behavior on width { - NumberAnimation { - duration: JamiTheme.longFadeDuration / 2 - } - } - - height: JamiTheme.chatViewFooterButtonSize - orientation: ListView.Horizontal - interactive: false - - leftMargin: 10 - rightMargin: 10 - spacing: 10 + Rectangle { + color: JamiTheme.transparentColor + visible: false //showTypo + height: 50 + width: previewButton.width + marginSize + Layout.row: showTypo ? 0 : 0 + Layout.column: showTypo ? 1 : 1 - Rectangle { - anchors.fill: parent - color: JamiTheme.chatViewFooterListColor - z: -1 - } - - property list<Action> 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(); - } - } - ] - - ListModel { - id: listActions - Component.onCompleted: { - for (var i = 0; i < listViewAction.menuActions.length; i++) { - append({ - "menuAction": listViewAction.menuActions[i] - }); - } - } - } - - 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 - - preferredSize: JamiTheme.chatViewFooterButtonSize - imageContainerWidth: 20 - imageContainerHeight: 20 - - radius: JamiTheme.chatViewFooterButtonRadius - - toolTipText: showDefault ? JamiStrings.showMore : JamiStrings.showLess - - source: JamiResources.more_vert_24dp_svg - - normalColor: showDefault ? JamiTheme.chatViewFooterListColor : JamiTheme.showMoreButtonOpenColor - imageColor: JamiTheme.chatViewFooterImgColor - pressedColor: JamiTheme.showMoreButtonOpenColor - hoveredColor: JamiTheme.showMoreButtonOpenColor + 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: { - showDefault = !showDefault; - if (showTypo) - showTypo = false; - UtilsAdapter.setAppValue(Settings.Key.ShowMardownOption, showTypo); - UtilsAdapter.setAppValue(Settings.Key.ShowSendOption, !showDefault); - } + onClicked: { + showPreview = !showPreview; } } } } + } - Row { - id: sendButtonRow - spacing: JamiTheme.chatViewFooterRowSpacing - anchors.right: parent.right - anchors.rightMargin: sendMessageButton.visible ? marginSize : 0 + Row { + id: sendButtonRow - PushButton { - id: sendMessageButton + spacing: JamiTheme.chatViewFooterRowSpacing - objectName: "sendMessageButton" + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.rightMargin: sendMessageButton.visible ? marginSize : 0 + anchors.bottomMargin: marginSize / 2 - width: scale * JamiTheme.chatViewFooterButtonSize - height: JamiTheme.chatViewFooterButtonSize + PushButton { + id: sendMessageButton - radius: JamiTheme.chatViewFooterButtonRadius - preferredSize: JamiTheme.chatViewFooterButtonIconSize - 6 - imageContainerWidth: 25 - imageContainerHeight: 25 + objectName: "sendMessageButton" - toolTipText: JamiStrings.send + width: scale * JamiTheme.chatViewFooterButtonSize + height: JamiTheme.chatViewFooterButtonSize - mirror: UtilsAdapter.isRTL + radius: JamiTheme.chatViewFooterButtonRadius + preferredSize: JamiTheme.chatViewFooterButtonIconSize - 6 + imageContainerWidth: 25 + imageContainerHeight: 25 - source: JamiResources.send_black_24dp_svg + toolTipText: JamiStrings.send - normalColor: JamiTheme.chatViewFooterSendButtonColor - imageColor: JamiTheme.chatViewFooterSendButtonImgColor - hoveredColor: JamiTheme.buttonTintedBlueHovered - pressedColor: hoveredColor + mirror: UtilsAdapter.isRTL - opacity: sendButtonVisibility ? 1 : 0 - visible: opacity - scale: opacity + source: JamiResources.send_black_24dp_svg - Behavior on opacity { - enabled: animate - NumberAnimation { - duration: JamiTheme.shortFadeDuration - easing.type: Easing.InOutQuad - } - } + normalColor: JamiTheme.chatViewFooterSendButtonColor + imageColor: JamiTheme.chatViewFooterSendButtonImgColor + hoveredColor: JamiTheme.buttonTintedBlueHovered + pressedColor: hoveredColor + + opacity: sendButtonVisibility ? 1 : 0 + visible: opacity + scale: opacity - onClicked: root.sendMessageButtonClicked() + 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 75702f969f063ea41f0b76090cc85ffa4b4833c8..46e290f8da393b21b1a4eae3e36d7e327125ef12 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 8da113236cf146f812d9ba21d8d8ee35177fc17f..442685cd7c9611609b221772b0c5aa98600ea3e1 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 7f575a3330883474ee7daac8c3dc9db0f036f867..5f68fad6e4f0f85bc63f547d05e35cf4ea06b147 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 4a1fc7e1a3f14afcfa3d36d282f0584a7703a2f8..a70c66d6765db6c28dd0f9e1319f64c12c0393a8 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);