From a29d5f791f3c373ebfc2372d381a3ceae10fb623 Mon Sep 17 00:00:00 2001 From: Andreas Hatziiliou <andreas.hatziiliou@savoirfairelinux.com> Date: Thu, 3 Oct 2024 15:12:29 -0400 Subject: [PATCH] message_bar: unify layout to be more coherent The goal of this patch is to make the messagebar (and more broadly the chatViewFooter) more coherent in its behavior and look/feel. GitLab: #1846 GitLab: #1848 GitLab: #1639 GitLab: #1420 Change-Id: I0d0ed207df9eba50f724c69fa49f956dc8aaa573 --- .../mainview/components/ChatViewFooter.qml | 2 +- .../mainview/components/ChatViewHeader.qml | 54 +- .../components/FilesToSendContainer.qml | 3 +- src/app/mainview/components/MessageBar.qml | 861 ++---------------- .../components/MessageBarTextArea.qml | 127 +-- .../mainview/components/MessageFormatBar.qml | 693 ++++++++++++++ .../mainview/components/MessageListView.qml | 200 ++-- .../components/MessagesResearchPanel.qml | 1 - src/app/net/jami/Constants/JamiTheme.qml | 3 + tests/qml/src/tst_ChatViewFooter.qml | 8 +- 10 files changed, 968 insertions(+), 984 deletions(-) create mode 100644 src/app/mainview/components/MessageFormatBar.qml diff --git a/src/app/mainview/components/ChatViewFooter.qml b/src/app/mainview/components/ChatViewFooter.qml index 70dc63c50..baa3a13e8 100644 --- a/src/app/mainview/components/ChatViewFooter.qml +++ b/src/app/mainview/components/ChatViewFooter.qml @@ -148,7 +148,7 @@ Rectangle { Layout.alignment: Qt.AlignHCenter Layout.preferredWidth: footerColumnLayout.width - Layout.leftMargin: 0 + Layout.leftMargin: marginSize Layout.rightMargin: marginSize Layout.bottomMargin: marginSize Layout.preferredHeight: height diff --git a/src/app/mainview/components/ChatViewHeader.qml b/src/app/mainview/components/ChatViewHeader.qml index a05419068..1c5c1f426 100644 --- a/src/app/mainview/components/ChatViewHeader.qml +++ b/src/app/mainview/components/ChatViewHeader.qml @@ -23,7 +23,6 @@ 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" Rectangle { @@ -61,9 +60,7 @@ Rectangle { } property bool addMemberVisibility: { - return swarmDetailsVisibility - && !CurrentConversation.isCoreDialog - && !CurrentConversation.isRequest; + return swarmDetailsVisibility && !CurrentConversation.isCoreDialog && !CurrentConversation.isRequest; } property bool swarmDetailsVisibility: { @@ -81,8 +78,10 @@ Rectangle { anchors.rightMargin: 10 + layoutManager.qwkSystemButtonSpacing.right spacing: 16 - JamiPushButton { QWKSetParentHitTestVisible {} + JamiPushButton { id: backToWelcomeViewButton + QWKSetParentHitTestVisible { + } Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft Layout.leftMargin: 8 @@ -109,8 +108,10 @@ Rectangle { color: JamiTheme.transparentColor - ColumnLayout { QWKSetParentHitTestVisible {} + ColumnLayout { id: userNameOrIdColumnLayout + QWKSetParentHitTestVisible { + } objectName: "userNameOrIdColumnLayout" height: parent.height @@ -148,31 +149,34 @@ Rectangle { } } - JamiPushButton { QWKSetParentHitTestVisible {} + JamiPushButton { id: startAudioCallButton + QWKSetParentHitTestVisible { + } - visible: interactionButtonsVisibility && - (!addMemberVisibility || UtilsAdapter.getAppValue(Settings.EnableExperimentalSwarm)) + visible: interactionButtonsVisibility && (!addMemberVisibility || UtilsAdapter.getAppValue(Settings.EnableExperimentalSwarm)) source: JamiResources.place_audiocall_24dp_svg toolTipText: JamiStrings.startAudioCall onClicked: CallAdapter.placeAudioOnlyCall() } - JamiPushButton { QWKSetParentHitTestVisible {} + JamiPushButton { id: startVideoCallButton + QWKSetParentHitTestVisible { + } - visible: interactionButtonsVisibility && - CurrentAccount.videoEnabled_Video && - (!addMemberVisibility || UtilsAdapter.getAppValue(Settings.EnableExperimentalSwarm)) + visible: interactionButtonsVisibility && CurrentAccount.videoEnabled_Video && (!addMemberVisibility || UtilsAdapter.getAppValue(Settings.EnableExperimentalSwarm)) source: JamiResources.videocam_24dp_svg toolTipText: JamiStrings.startVideoCall onClicked: CallAdapter.placeCall() } - JamiPushButton { QWKSetParentHitTestVisible {} + JamiPushButton { id: inviteMembersButton + QWKSetParentHitTestVisible { + } checkable: true checked: extrasPanel.isOpen(ChatView.AddMemberPanel) @@ -183,8 +187,10 @@ Rectangle { onClicked: extrasPanel.switchToPanel(ChatView.AddMemberPanel) } - JamiPushButton { QWKSetParentHitTestVisible {} + JamiPushButton { id: selectExtensionsButton + QWKSetParentHitTestVisible { + } visible: PluginAdapter.chatHandlersListCount && interactionButtonsVisibility source: JamiResources.plugins_24dp_svg @@ -193,27 +199,29 @@ Rectangle { onClicked: pluginSelector() } - JamiPushButton { QWKSetParentHitTestVisible {} + JamiPushButton { id: sendContactRequestButton + QWKSetParentHitTestVisible { + } objectName: "sendContactRequestButton" visible: CurrentConversation.isTemporary || CurrentConversation.isBanned source: JamiResources.add_people_24dp_svg toolTipText: JamiStrings.addToConversations - onClicked: CurrentConversation.isBanned ? - MessagesAdapter.unbanConversation(CurrentConversation.id) : - MessagesAdapter.sendConversationRequest() + onClicked: CurrentConversation.isBanned ? MessagesAdapter.unbanConversation(CurrentConversation.id) : MessagesAdapter.sendConversationRequest() } - JamiPushButton { QWKSetParentHitTestVisible {} + JamiPushButton { id: searchMessagesButton + QWKSetParentHitTestVisible { + } objectName: "searchMessagesButton" checkable: true checked: extrasPanel.isOpen(ChatView.MessagesResearchPanel) visible: root.swarmDetailsVisibility - source: JamiResources.ic_baseline_search_24dp_svg + source: JamiResources.ic_baseline_search_24dp_svg toolTipText: JamiStrings.search onClicked: extrasPanel.switchToPanel(ChatView.MessagesResearchPanel) @@ -226,8 +234,10 @@ Rectangle { } } - JamiPushButton { QWKSetParentHitTestVisible {} + JamiPushButton { id: detailsButton + QWKSetParentHitTestVisible { + } objectName: "detailsButton" checkable: true diff --git a/src/app/mainview/components/FilesToSendContainer.qml b/src/app/mainview/components/FilesToSendContainer.qml index 1cce7ad2f..9167b690e 100644 --- a/src/app/mainview/components/FilesToSendContainer.qml +++ b/src/app/mainview/components/FilesToSendContainer.qml @@ -28,7 +28,6 @@ Rectangle { property alias filesToSendListModel: repeater.model property alias filesToSendCount: repeater.count color: JamiTheme.primaryBackgroundColor - LayoutMirroring.enabled: UtilsAdapter.isRTL LayoutMirroring.childrenInherit: true @@ -51,7 +50,7 @@ Rectangle { layoutDirection: UtilsAdapter.isRTL ? Qt.RightToLeft : Qt.LeftToRight spacing: JamiTheme.filesToSendContainerSpacing - padding: JamiTheme.filesToSendContainerPadding + //padding: JamiTheme.filesToSendContainerPadding Repeater { id: repeater diff --git a/src/app/mainview/components/MessageBar.qml b/src/app/mainview/components/MessageBar.qml index a728ce50f..e9da7dc6a 100644 --- a/src/app/mainview/components/MessageBar.qml +++ b/src/app/mainview/components/MessageBar.qml @@ -24,11 +24,10 @@ import net.jami.Models 1.1 import net.jami.Enums 1.1 import net.jami.Constants 1.1 import "../../commoncomponents" - import "qrc:/js/markdownedition.js" as MDE -RowLayout { - id: root +Rectangle { + id: rectangle property alias text: messageBarTextArea.text property alias fileContainer: dataTransferSendContainer @@ -38,11 +37,10 @@ RowLayout { 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: messageBarTextArea.tooMuch + property bool maximized: (showTypo || dataTransferSendContainer.visible) property int messageBarLayoutMaximumWidth: 486 readonly property bool isFullScreen: visibility === Window.FullScreen @@ -54,126 +52,73 @@ RowLayout { signal showMapClicked signal emojiButtonClicked - property real rectHeight: (showTypo || multiLine) ? messageBarTextArea.height + 25 + 4 * marginSize + 1 : textAreaObj.height + 1 * marginSize + 1 - - height: rectHeight + (dataTransferSendContainer.visible ? dataTransferSendContainer.height + (!showTypo ? 40 : - marginSize) : 0 ) + onSendMessageButtonClicked: { + messageBarTextArea.restoreVisibilityAfterSend(); + messageBarTextArea.forceActiveFocus(); + } onShowTypoChanged: { messageBarTextArea.forceActiveFocus(); } - Rectangle { - Layout.preferredHeight: parent.height - Layout.preferredWidth: childrenRect.width - visible: !CurrentConversation.isSip - color: JamiTheme.transparentColor - ComboBox { - id: showMoreButton - focus: true - width: JamiTheme.chatViewFooterButtonSize - height: JamiTheme.chatViewFooterButtonSize - anchors.bottom: parent.bottom - anchors.bottomMargin: marginSize / 2 - - // Used to choose the correct color for the button. - readonly property bool highlight: down || hovered - - background: Rectangle { - implicitWidth: showMoreButton.width - implicitHeight: showMoreButton.height - radius: 5 - color: showMoreButton.highlight ? - JamiTheme.hoveredButtonColor : - JamiTheme.transparentColor - } - - MaterialToolTip { - id: toolTipMoreButton + Layout.fillWidth: true + Layout.alignment: Qt.AlignBottom + height: Math.min(JamiTheme.chatViewFooterTextAreaMaximumHeight + 2 * marginSize, colLayout.height + 2 * marginSize) - parent: showMoreButton - visible: showMoreButton.hovered && (text.length > 0) - delay: Qt.styleHints.mousePressAndHoldInterval - text: showMoreButton.down ? JamiStrings.showLess : JamiStrings.showMore - } - - indicator: ResponsiveImage { - - width: 25 - height: 25 - - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - - source: JamiResources.more_menu_black_24dp_svg - - color: showMoreButton.highlight ? - JamiTheme.chatViewFooterImgHoverColor : - JamiTheme.chatViewFooterImgColor; - } + radius: 5 + color: JamiTheme.transparentColor + border.color: JamiTheme.chatViewFooterRectangleBorderColor + border.width: 2 - Component { - id: sharePopupComp - ShareMenu { - id: sharePopup - onAudioRecordMessageButtonClicked: root.audioRecordMessageButtonClicked() - onVideoRecordMessageButtonClicked: root.videoRecordMessageButtonClicked() - onShowMapClicked: root.showMapClicked() - modelList: listViewMoreButton.menuMoreButton - y: showMoreButton.y + 31 - x: showMoreButton.x - 3 - } - } - - popup: ShareMenu { - id: sharePopup - onAudioRecordMessageButtonClicked: root.audioRecordMessageButtonClicked() - onVideoRecordMessageButtonClicked: root.videoRecordMessageButtonClicked() - onShowMapClicked: root.showMapClicked() - modelList: listViewMoreButton.menuMoreButton - y: showMoreButton.y + 31 - x: showMoreButton.x - 3 - } + onWidthChanged: { + if (width < JamiTheme.showTypoSecondToggleWidth) { + showTypoSecond = false; + } else { + showTypoSecond = true; } } - Rectangle { - id: rectangle + GridLayout { + id: colLayout + columns: 2 + rows: 3 - Layout.fillWidth: true - Layout.fillHeight: true - - radius: 5 - color: JamiTheme.transparentColor - border.color: JamiTheme.chatViewFooterRectangleBorderColor - border.width: 2 - - onWidthChanged: { - height = Qt.binding(() => root.height); - if (width < JamiTheme.messageBarMinimumWidth) { - showTypoSecond = false; - } else { - showTypoSecond = true; - } + anchors { + left: parent.left + right: parent.right + top: parent.top + margins: marginSize } - GridLayout { - id: rowLayout + Rectangle { + id: messageRow - columns: 2 - rows: 3 - columnSpacing: 0 - rowSpacing: 0 + property bool isExpanding: !(showTypo && dataTransferSendContainer.visible) && (textAreaObj.textWidth >= rectangle.width - formatRow.width - 8 * marginSize) - anchors.fill: parent + Layout.fillWidth: true + Layout.row: maximized || isExpanding ? 0 : 2 + Layout.column: 0 + Layout.columnSpan: maximized || isExpanding ? 2 : 1 + Layout.alignment: Qt.AlignTop + Layout.rightMargin: marginSize / 2 + Layout.leftMargin: marginSize / 2 + Layout.preferredHeight: Math.max(messageBarTextArea.contentHeight + 4, 36) + Layout.maximumHeight: JamiTheme.messageBarMaximumHeight + color: JamiTheme.transparentColor MessageBarTextArea { id: messageBarTextArea - objectName: "messageBarTextArea" - maxWidth: rectangle.width - messageBarRowLayout.width - 35 - Layout.row: 0 - Layout.column: 0 + + placeholderText: JamiStrings.writeTo.arg(CurrentConversation.title) + + anchors { + right: (showTypo) ? previewButton.left : messageRow.right + left: parent.left + verticalCenter: parent.verticalCenter + top: parent.top + } // forward activeFocus to the actual text area object onActiveFocusChanged: { @@ -181,24 +126,10 @@ RowLayout { textAreaObj.forceActiveFocus(); } - placeholderText: JamiStrings.writeTo.arg(CurrentConversation.title) - - Layout.alignment: showTypo ? Qt.AlignLeft : Qt.AlignBottom - Layout.fillWidth: true - Layout.margins: marginSize / 2 - Layout.topMargin: 0 - Layout.minimumHeight: JamiTheme.chatViewFooterPreferredHeight - Layout.preferredHeight: contentHeight - Layout.maximumHeight: JamiTheme.chatViewFooterTextAreaMaximumHeight - marginSize / 2 - onSendMessagesRequired: { sendMessageButtonClicked(); } - onTextChanged: { - if (!text) { - messageBarTextArea.heightBinding(); - } - } + property var markdownShortCut: { "Bold": function () { if (!showPreview) { @@ -326,657 +257,59 @@ RowLayout { } } - FilesToSendContainer { - id: dataTransferSendContainer - - objectName: "dataTransferSendContainer" - visible: filesToSendCount > 0 - - Layout.alignment: Qt.AlignCenter - Layout.fillWidth: true - Layout.rightMargin: marginSize / 2 - Layout.leftMargin: marginSize / 2 - Layout.row: 1 - Layout.column: 0 - Layout.columnSpan: 2 - Layout.preferredHeight: filesToSendCount ? JamiTheme.layoutWidthFileTransfer : 0 - } - - Row { - id: messageBarRowLayout - - Layout.row: dataTransferSendContainer.visible ? 3 : (showTypo || multiLine ? 2 : 0) - Layout.column: showTypo || multiLine ? 0 : 1 - Layout.alignment: showTypo || multiLine ? Qt.AlignRight : Qt.AlignBottom - Layout.columnSpan: showTypo || multiLine ? 2 : 1 - Layout.topMargin: dataTransferSendContainer.visible ? 0 : marginSize - Layout.rightMargin: 0 - - Row { - anchors.bottom: parent.bottom - anchors.bottomMargin: marginSize / 2 - - Row { - id: listViewTypo - height: JamiTheme.chatViewFooterButtonSize - - ListView { - id: listViewTypoFirst - - objectName: "listViewTypoFirst" - - visible: showTypo - width: contentWidth + 2 * leftMargin - - Behavior on width { - NumberAnimation { - duration: JamiTheme.longFadeDuration / 2 - } - } - - height: JamiTheme.chatViewFooterButtonSize - orientation: ListView.Horizontal - interactive: false - spacing: 5 - - property list<Action> menuTypoActionsFirst: [ - Action { - id: boldAction - property string iconSrc: JamiResources.bold_black_24dp_svg - property string shortcutText: JamiStrings.bold - property string shortcutKey: "Ctrl+B" - property bool isStyle: MDE.isStyle(messageBarTextArea, root.text, "**", "**") - onTriggered: MDE.addStyle(messageBarTextArea, root.text, "**", "**") - }, - Action { - id: italicAction - property string iconSrc: JamiResources.italic_black_24dp_svg - property string shortcutText: JamiStrings.italic - property string shortcutKey: "Ctrl+I" - property bool isStyle: MDE.isStyle(messageBarTextArea, root.text, "*", "*") - onTriggered: MDE.addStyle(messageBarTextArea, root.text, "*", "*") - }, - Action { - id: strikethroughAction - property string iconSrc: JamiResources.s_barre_black_24dp_svg - property string shortcutText: JamiStrings.strikethrough - property string shortcutKey: "Shift+Alt+X" - property bool isStyle: MDE.isStyle(messageBarTextArea, root.text, "~~", "~~") - onTriggered: MDE.addStyle(messageBarTextArea, root.text, "~~", "~~") - }, - Action { - id: titleAction - property string iconSrc: JamiResources.title_black_24dp_svg - property string shortcutText: JamiStrings.heading - property string shortcutKey: "Ctrl+Alt+H" - property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, root.text, "### ", false) - onTriggered: MDE.addPrefixStyle(messageBarTextArea, root.text, "### ", false) - }, - Action { - id: linkAction - property string iconSrc: JamiResources.link_web_black_24dp_svg - property string shortcutText: JamiStrings.link - property string shortcutKey: "Ctrl+Alt+K" - property bool isStyle: MDE.isStyle(messageBarTextArea, root.text, "[", "](url)") - onTriggered: MDE.addStyle(messageBarTextArea, root.text, "[", "](url)") - }, - Action { - id: codeAction - property string iconSrc: JamiResources.code_black_24dp_svg - property string shortcutText: JamiStrings.code - property string shortcutKey: "Ctrl+Alt+C" - property bool isStyle: MDE.isStyle(messageBarTextArea, root.text, "```", "```") - onTriggered: MDE.addStyle(messageBarTextArea, root.text, "```", "```") - } - ] - - model: menuTypoActionsFirst - - delegate: PushButton { - anchors.verticalCenter: parent ? parent.verticalCenter : undefined - 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: { - if (showPreview) { - return JamiTheme.primaryBackgroundColor; - } else if (modelData.isStyle) { - return JamiTheme.hoveredButtonColor; - } else { - return JamiTheme.primaryBackgroundColor; - } - } - imageColor: { - if (showPreview) { - return JamiTheme.chatViewFooterImgDisableColor; - } else if (hovered) { - return JamiTheme.chatViewFooterImgHoverColor; - } else if (modelData.isStyle) { - return JamiTheme.chatViewFooterImgHoverColor; - } else { - return JamiTheme.chatViewFooterImgColor; - } - } - hoveredColor: JamiTheme.hoveredButtonColor - pressedColor: hoveredColor - - action: modelData - } - } - - Rectangle { - height: JamiTheme.chatViewFooterButtonSize - color: JamiTheme.primaryBackgroundColor - visible: showTypo && showTypoSecond - width: 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.primaryBackgroundColor - width: JamiTheme.chatViewFooterButtonSize - height: JamiTheme.chatViewFooterButtonSize - - visible: showTypo && !showTypoSecond - - ComboBox { - id: showMoreTypoButton - width: JamiTheme.chatViewFooterRealButtonSize - height: width - anchors.verticalCenter: parent.verticalCenter - anchors.horizontalCenter: parent.horizontalCenter - - enabled: !showPreview - hoverEnabled: !showPreview - - MaterialToolTip { - id: toolTip - parent: showMoreTypoButton - visible: showMoreTypoButton.hovered && (text.length > 0) - delay: Qt.styleHints.mousePressAndHoldInterval - text: markdownPopup.visible ? JamiStrings.showLess : 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 { - id: markdownPopup - y: 1.5 * parent.height - x: -parent.width * 2 - width: 105 - height: JamiTheme.chatViewFooterButtonSize - - menuTypoActionsSecond: listViewTypoSecond.menuTypoActionsSecond - } - } - } - - ListView { - id: listViewTypoSecond - visible: showTypo && showTypoSecond - width: contentWidth + 2 * leftMargin - - height: JamiTheme.chatViewFooterButtonSize - orientation: ListView.Horizontal - interactive: false - spacing: 10 - - Rectangle { - anchors.fill: parent - color: JamiTheme.transparentColor - z: -1 - } - - property list<Action> menuTypoActionsSecond: [ - Action { - id: quoteAction - property string iconSrc: JamiResources.quote_black_24dp_svg - property string shortcutText: JamiStrings.quote - property string shortcutKey: "Shift+Alt+9" - property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, root.text, "> ", false) - onTriggered: MDE.addPrefixStyle(messageBarTextArea, root.text, "> ", false) - }, - Action { - id: unorderedListAction - property string iconSrc: JamiResources.bullet_point_black_24dp_svg - property string shortcutText: JamiStrings.unorderedList - property string shortcutKey: "Shift+Alt+8" - property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, root.text, "- ", false) - onTriggered: MDE.addPrefixStyle(messageBarTextArea, root.text, "- ", false) - }, - Action { - id: orderedListAction - property string iconSrc: JamiResources.bullet_number_black_24dp_svg - property string shortcutText: JamiStrings.orderedList - property string shortcutKey: "Shift+Alt+7" - property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, root.text, "", true) - onTriggered: MDE.addPrefixStyle(messageBarTextArea, root.text, "", true) - } - ] - - model: menuTypoActionsSecond - - delegate: PushButton { - anchors.verticalCenter: parent ? parent.verticalCenter : undefined - preferredSize: JamiTheme.chatViewFooterRealButtonSize - imageContainerWidth: 20 - imageContainerHeight: 20 - radius: 5 - - hoverEnabled: !showPreview - enabled: !showPreview - - toolTipText: modelData.shortcutText - shortcutKey: modelData.shortcutKey - hasShortcut: modelData.hasShortcut ? true : false - source: modelData.iconSrc - focusPolicy: Qt.TabFocus - - normalColor: { - if (showPreview) { - return JamiTheme.primaryBackgroundColor; - } else if (modelData.normalColor) { - return modelData.normalColor; - } else if (modelData.isStyle) { - return JamiTheme.hoveredButtonColor; - } else { - return JamiTheme.primaryBackgroundColor; - } - } - imageColor: { - if (showPreview) { - return JamiTheme.chatViewFooterImgDisableColor; - } else if (hovered) { - return JamiTheme.chatViewFooterImgHoverColor; - } else if (modelData.isStyle) { - return JamiTheme.chatViewFooterImgHoverColor; - } else { - return JamiTheme.chatViewFooterImgColor; - } - } - hoveredColor: JamiTheme.hoveredButtonColor - pressedColor: hoveredColor - - action: modelData - } - } - } - - PushButton { - id: typoButton - - preferredSize: JamiTheme.chatViewFooterButtonSize - imageContainerWidth: 24 - imageContainerHeight: 24 + PushButton { + id: previewButton - radius: JamiTheme.chatViewFooterButtonRadius - - hoverEnabled: !showPreview - enabled: !showPreview - - toolTipText: showTypo ? JamiStrings.hideFormatting : JamiStrings.showFormatting - source: JamiResources.text_edit_black_24dp_svg - - normalColor: showPreview ? JamiTheme.primaryBackgroundColor : (showTypo ? JamiTheme.hoveredButtonColor : JamiTheme.primaryBackgroundColor) - imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered || showTypo ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor) - hoveredColor: JamiTheme.hoveredButtonColor - pressedColor: hoveredColor - - onClicked: { - showTypo = !showTypo; - messageBarTextArea.isShowTypo = showTypo; - if (messageBar.width < messageBarLayoutMaximumWidth + sendMessageButton.width + 2 * JamiTheme.preferredMarginSize) - showTypoSecond = false; - if (!showDefault) - showDefault = true; - UtilsAdapter.setAppValue(Settings.Key.ShowMardownOption, showTypo); - UtilsAdapter.setAppValue(Settings.Key.ShowSendOption, !showDefault); - } - } - } - - Row { - anchors.bottom: parent.bottom - anchors.bottomMargin: marginSize / 2 - - ListView { - id: listViewAction - - width: contentWidth + 2 * leftMargin - - 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> menuActions: [ - Action { - id: sendFile - property string iconSrc: JamiResources.link_black_24dp_svg - property string toolTip: JamiStrings.sendFile - property bool show: true - property bool needWebEngine: false - property bool needVideoDevice: false - property bool noSip: false - onTriggered: function clickAction() { - sendFileButtonClicked(); - textAreaObj.forceActiveFocus(); - } - }, - Action { - id: addEmoji - property string iconSrc: JamiResources.emoji_black_24dp_svg - property string toolTip: JamiStrings.addEmoji - property bool show: true - property bool needWebEngine: true - property bool needVideoDevice: false - property bool noSip: true - onTriggered: function clickAction() { - emojiButtonClicked(); - } - } - ] - - 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.chatViewFooterButtonSize - imageContainerWidth: 25 - imageContainerHeight: 25 - radius: 5 - - hoverEnabled: !showPreview - enabled: !showPreview - - toolTipText: modelData.toolTip - source: modelData.iconSrc - - normalColor: JamiTheme.primaryBackgroundColor - 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<Action> menuMoreButton: [ - Action { - id: leaveAudioMessage - property string iconSrc: JamiResources.message_audio_black_24dp_svg - property string 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 string iconSrc: JamiResources.message_video_black_24dp_svg - property string 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 string iconSrc: JamiResources.localisation_sharing_send_pin_svg - property string 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 - } - } - } - } + visible: showTypo && messageBarTextArea.text + anchors.top: parent.top + anchors.right: parent.right + preferredSize: JamiTheme.chatViewFooterButtonSize + imageContainerWidth: 25 + imageContainerHeight: 25 + radius: 5 + source: JamiResources.preview_black_24dp_svg + normalColor: showPreview ? hoveredColor : JamiTheme.primaryBackgroundColor + imageColor: (hovered || showPreview) ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor + hoveredColor: JamiTheme.hoveredButtonColor + pressedColor: hoveredColor + toolTipText: showPreview ? JamiStrings.continueEditing : JamiStrings.showPreview + Layout.margins: marginSize / 2 - Rectangle { - color: JamiTheme.transparentColor - visible: 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.primaryBackgroundColor - imageColor: (hovered || showPreview) ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor - hoveredColor: JamiTheme.hoveredButtonColor - pressedColor: hoveredColor - toolTipText: showPreview ? JamiStrings.continueEditing : JamiStrings.showPreview - - - onClicked: { - showPreview = !showPreview; - messageBarTextArea.showPreview = showPreview; - } + onClicked: { + showPreview = !showPreview; + messageBarTextArea.showPreview = showPreview; + messageBarTextArea.forceActiveFocus(); } } } - } - - Rectangle { - Layout.preferredHeight: parent.height - Layout.preferredWidth: childrenRect.width - visible: sendButtonVisibility - color: JamiTheme.transparentColor - PushButton { - id: sendMessageButton - objectName: "sendMessageButton" - anchors.bottom: parent.bottom - anchors.bottomMargin: marginSize / 2 - - enabled: sendButtonVisibility - hoverEnabled: enabled - - 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: enabled ? JamiTheme.chatViewFooterSendButtonColor : JamiTheme.chatViewFooterSendButtonDisableColor - imageColor: enabled ? JamiTheme.chatViewFooterSendButtonImgColor : JamiTheme.chatViewFooterSendButtonImgColorDisable - hoveredColor: JamiTheme.buttonTintedBlueHovered - pressedColor: hoveredColor - - opacity: 1 - scale: opacity - - Behavior on opacity { - enabled: animate - NumberAnimation { - duration: JamiTheme.shortFadeDuration - easing.type: Easing.InOutQuad - } - } + FilesToSendContainer { + id: dataTransferSendContainer + + objectName: "dataTransferSendContainer" + visible: filesToSendCount > 0 + height: visible ? JamiTheme.layoutWidthFileTransfer : 0 + Layout.rightMargin: marginSize / 2 + Layout.leftMargin: marginSize / 2 + Layout.fillWidth: true + Layout.alignment: Qt.AlignBottom + Layout.preferredHeight: filesToSendCount ? JamiTheme.layoutWidthFileTransfer : 0 + Layout.row: 1 + Layout.column: 0 + Layout.columnSpan: 2 + } - onClicked: { - root.showPreview = false; - sendMessageButtonClicked(); - root.height = root.rectHeight; - } + MessageFormatBar { + id: formatRow + color: JamiTheme.transparentColor + Layout.alignment: Qt.AlignBottom + Layout.fillWidth: maximized ? true : false + Layout.rightMargin: marginSize / 2 + Layout.leftMargin: marginSize / 2 + Layout.preferredHeight: JamiTheme.chatViewFooterButtonSize + Layout.row: 2 + Layout.column: maximized ? 0 : 1 + Layout.columnSpan: maximized ? 2 : 1 } } } diff --git a/src/app/mainview/components/MessageBarTextArea.qml b/src/app/mainview/components/MessageBarTextArea.qml index 3c81acad8..ada46a915 100644 --- a/src/app/mainview/components/MessageBarTextArea.qml +++ b/src/app/mainview/components/MessageBarTextArea.qml @@ -17,23 +17,20 @@ */ import QtQuick import QtQuick.Controls +import QtQuick.Layouts + 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" -import QtQuick.Layouts + import SortFilterProxyModel 0.2 +import "../../commoncomponents" + JamiFlickable { id: root - property int maxWidth: 330 - property bool tooMuch: { - if (maxWidth > 0) - return textArea.contentWidth > maxWidth; - return false; - } property alias text: textArea.text property var textAreaObj: textArea property alias placeholderText: textArea.placeholderText @@ -42,16 +39,15 @@ JamiFlickable { property alias selectionEnd: textArea.selectionEnd property bool showPreview: false property bool isShowTypo: UtilsAdapter.getAppValue(Settings.Key.ShowMardownOption) + property int textWidth: textArea.contentWidth - ScrollBar.vertical.visible: textArea.text - ScrollBar.horizontal.visible: textArea.text + // Used to cache the editable text when showing the preview message + // and also to debounce the textChanged signal's effect on the composing status. + property string cachedText + property string debounceText signal sendMessagesRequired - function heightBinding() { - textArea.height = Qt.binding(() => textArea.lineCount === 1 ? 35 : textArea.paintedHeight); - } - function selectText(start, end) { textArea.select(start, end); } @@ -60,16 +56,16 @@ JamiFlickable { textArea.insert(textArea.cursorPosition, text); } + function pasteText() { + textArea.paste(); + } + function clearText() { - var multiLine = textArea.lineCount !== 1; textArea.clear(); - if (multiLine) { - heightBinding(); - } } - function pasteText() { - textArea.paste(); + function restoreVisibilityAfterSend() { + showPreview = false; } LineEditContextMenu { @@ -84,94 +80,55 @@ JamiFlickable { } } + ScrollBar.vertical.visible: text + ScrollBar.horizontal.visible: text + + boundsMovement: Flickable.StopAtBounds + boundsBehavior: Flickable.DragOverBounds interactive: true - attachedFlickableMoving: textAreaPreview.height > height || textArea.height > height || root.moving - contentHeight: showPreview ? textAreaPreview.height : textArea.height + function resetEditableText() { + textArea.text = cachedText; + textArea.update(); + } onShowPreviewChanged: { if (showPreview) { - textAreaPreview.height = textArea.lineCount === 1 ? textArea.height : textAreaPreview.paintedHeight; + cachedText = textArea.text; + MessagesAdapter.parseMessage("", textArea.text, false, "", ""); + } else { + textArea.textFormatChanged.disconnect(resetEditableText); + textArea.textFormatChanged.connect(resetEditableText); } - heightBinding(); } - TextArea { - id: textAreaPreview - - onWidthChanged: root.height = this.height - - overwriteMode: false - readOnly: true - - height: textArea.lineCount === 1 ? textArea.height : this.paintedHeight - width: textArea.width - - visible: showPreview - leftPadding: JamiTheme.scrollBarHandleSize - rightPadding: JamiTheme.scrollBarHandleSize - topPadding: 0 - bottomPadding: 0 - - Connections { - target: textArea - function onTextChanged() { - MessagesAdapter.parseMessage("", textArea.text, false, "", ""); + Connections { + target: MessagesAdapter + function onMessageParsed(messageId, messageText) { + if (messageId === "") { + textArea.text = messageText; + textArea.update(); } } - - Connections { - target: MessagesAdapter - function onMessageParsed(messageId, messageText) { - if (messageId === "") { - textAreaPreview.text = messageText; - } - } - } - - verticalAlignment: TextEdit.AlignVCenter - - font.pointSize: JamiTheme.textFontSize + 2 - font.hintingPreference: Font.PreferNoHinting - - color: JamiTheme.textColor - wrapMode: TextEdit.Wrap - textFormat: TextEdit.RichText - placeholderTextColor: JamiTheme.messageBarPlaceholderTextColor - horizontalAlignment: Text.AlignLeft - - background: Rectangle { - border.width: 0 - color: "transparent" - } } TextArea.flickable: TextArea { id: textArea - visible: !showPreview - + readOnly: showPreview leftPadding: JamiTheme.scrollBarHandleSize rightPadding: JamiTheme.scrollBarHandleSize - topPadding: 0 - bottomPadding: 0 - persistentSelection: true - - height: textArea.lineCount === 1 ? 35 : textArea.paintedHeight - verticalAlignment: TextEdit.AlignVCenter - font.pointSize: JamiTheme.textFontSize + 2 font.hintingPreference: Font.PreferNoHinting - color: JamiTheme.textColor wrapMode: TextEdit.Wrap - selectByMouse: true - textFormat: TextEdit.PlainText + selectByMouse: !showPreview + textFormat: showPreview ? TextEdit.RichText : TextEdit.PlainText + placeholderTextColor: JamiTheme.messageBarPlaceholderTextColor horizontalAlignment: Text.AlignLeft - property var cacheText: "" background: Rectangle { border.width: 0 @@ -184,8 +141,8 @@ JamiFlickable { } onTextChanged: { - if (text != cacheText) { - cacheText = text; + if (text !== debounceText && !showPreview) { + debounceText = text; MessagesAdapter.userIsComposing(text ? true : false); } } diff --git a/src/app/mainview/components/MessageFormatBar.qml b/src/app/mainview/components/MessageFormatBar.qml new file mode 100644 index 000000000..dfcdc687a --- /dev/null +++ b/src/app/mainview/components/MessageFormatBar.qml @@ -0,0 +1,693 @@ +/* + * Copyright (C) 2020-2024 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 SortFilterProxyModel 0.2 +import net.jami.Adapters 1.1 +import net.jami.Models 1.1 +import net.jami.Enums 1.1 +import net.jami.Constants 1.1 +import "../../commoncomponents" +import "qrc:/js/markdownedition.js" as MDE + +Rectangle { + id: messageBarRowLayout + Layout.preferredWidth: showTypo ? firstRow.width + secondRow.width : secondRow.width + LayoutMirroring.enabled: UtilsAdapter.isRTL + LayoutMirroring.childrenInherit: true + + Row { + id: firstRow + anchors.left: messageBarRowLayout.left + anchors.bottom: messageBarRowLayout.bottom + + Row { + id: listViewTypo + height: JamiTheme.chatViewFooterButtonSize + + ListView { + id: listViewTypoFirst + objectName: "listViewTypoFirst" + + visible: showTypo + width: visible ? contentWidth + 2 * leftMargin : 0 + + Behavior on width { + NumberAnimation { + duration: JamiTheme.longFadeDuration / 2 + } + } + + height: JamiTheme.chatViewFooterButtonSize + orientation: ListView.Horizontal + interactive: false + + property list<Action> menuTypoActionsFirst: [ + Action { + id: boldAction + property string iconSrc: JamiResources.bold_black_24dp_svg + property string shortcutText: JamiStrings.bold + property string shortcutKey: "Ctrl+B" + property bool isStyle: MDE.isStyle(messageBarTextArea, rectangle.text, "**", "**") + onTriggered: MDE.addStyle(messageBarTextArea, rectangle.text, "**", "**") + }, + Action { + id: italicAction + property string iconSrc: JamiResources.italic_black_24dp_svg + property string shortcutText: JamiStrings.italic + property string shortcutKey: "Ctrl+I" + property bool isStyle: MDE.isStyle(messageBarTextArea, rectangle.text, "*", "*") + onTriggered: MDE.addStyle(messageBarTextArea, rectangle.text, "*", "*") + }, + Action { + id: strikethroughAction + property string iconSrc: JamiResources.s_barre_black_24dp_svg + property string shortcutText: JamiStrings.strikethrough + property string shortcutKey: "Shift+Alt+X" + property bool isStyle: MDE.isStyle(messageBarTextArea, rectangle.text, "~~", "~~") + onTriggered: MDE.addStyle(messageBarTextArea, rectangle.text, "~~", "~~") + }, + Action { + id: titleAction + property string iconSrc: JamiResources.title_black_24dp_svg + property string shortcutText: JamiStrings.heading + property string shortcutKey: "Ctrl+Alt+H" + property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, rectangle.text, "### ", false) + onTriggered: MDE.addPrefixStyle(messageBarTextArea, rectangle.text, "### ", false) + }, + Action { + id: linkAction + property string iconSrc: JamiResources.link_web_black_24dp_svg + property string shortcutText: JamiStrings.link + property string shortcutKey: "Ctrl+Alt+K" + property bool isStyle: MDE.isStyle(messageBarTextArea, rectangle.text, "[", "](url)") + onTriggered: MDE.addStyle(messageBarTextArea, rectangle.text, "[", "](url)") + }, + Action { + id: codeAction + property string iconSrc: JamiResources.code_black_24dp_svg + property string shortcutText: JamiStrings.code + property string shortcutKey: "Ctrl+Alt+C" + property bool isStyle: MDE.isStyle(messageBarTextArea, rectangle.text, "```", "```") + onTriggered: MDE.addStyle(messageBarTextArea, rectangle.text, "```", "```") + } + ] + + model: menuTypoActionsFirst + + delegate: PushButton { + anchors.verticalCenter: parent ? parent.verticalCenter : undefined + preferredSize: JamiTheme.chatViewFooterButtonSize + 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: { + if (showPreview) { + return JamiTheme.primaryBackgroundColor; + } else if (modelData.isStyle) { + return JamiTheme.hoveredButtonColor; + } else { + return JamiTheme.primaryBackgroundColor; + } + } + imageColor: { + if (showPreview) { + return JamiTheme.chatViewFooterImgDisableColor; + } else if (hovered) { + return JamiTheme.chatViewFooterImgHoverColor; + } else if (modelData.isStyle) { + return JamiTheme.chatViewFooterImgHoverColor; + } else { + return JamiTheme.chatViewFooterImgColor; + } + } + hoveredColor: JamiTheme.hoveredButtonColor + pressedColor: hoveredColor + + action: modelData + } + } + + Rectangle { + height: JamiTheme.chatViewFooterButtonSize + color: JamiTheme.primaryBackgroundColor + visible: showTypo && showTypoSecond + width: 5 + + Rectangle { + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + width: 1 + height: JamiTheme.chatViewFooterButtonSize * 2 / 3 + color: showPreview ? JamiTheme.chatViewFooterImgDisableColor : JamiTheme.chatViewFooterSeparateLineColor + } + } + + Rectangle { + z: -1 + radius: 0 + color: JamiTheme.primaryBackgroundColor + width: JamiTheme.chatViewFooterButtonSize + height: JamiTheme.chatViewFooterButtonSize + + visible: showTypo && !showTypoSecond + + ComboBox { + id: showMoreTypoButton + width: JamiTheme.chatViewFooterButtonSize + height: width + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + + enabled: !showPreview + hoverEnabled: !showPreview + + MaterialToolTip { + id: toolTip + parent: showMoreTypoButton + visible: showMoreTypoButton.hovered && (text.length > 0) + delay: Qt.styleHints.mousePressAndHoldInterval + text: markdownPopup.visible ? JamiStrings.showLess : 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 { + id: markdownPopup + y: 1.5 * parent.height + x: -parent.width * 2 + width: listViewTypoSecond.width + 10 + height: JamiTheme.chatViewFooterButtonSize + + menuTypoActionsSecond: listViewTypoSecond.menuTypoActionsSecond + } + } + } + + ListView { + id: listViewTypoSecond + visible: showTypo && showTypoSecond + width: contentWidth + 2 * leftMargin + + height: JamiTheme.chatViewFooterButtonSize + orientation: ListView.Horizontal + interactive: false + + Rectangle { + anchors.fill: parent + color: JamiTheme.transparentColor + z: -1 + } + + property list<Action> menuTypoActionsSecond: [ + Action { + id: quoteAction + property string iconSrc: JamiResources.quote_black_24dp_svg + property string shortcutText: JamiStrings.quote + property string shortcutKey: "Shift+Alt+9" + property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, rectangle.text, "> ", false) + onTriggered: MDE.addPrefixStyle(messageBarTextArea, rectangle.text, "> ", false) + }, + Action { + id: unorderedListAction + property string iconSrc: JamiResources.bullet_point_black_24dp_svg + property string shortcutText: JamiStrings.unorderedList + property string shortcutKey: "Shift+Alt+8" + property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, rectangle.text, "- ", false) + onTriggered: MDE.addPrefixStyle(messageBarTextArea, rectangle.text, "- ", false) + }, + Action { + id: orderedListAction + property string iconSrc: JamiResources.bullet_number_black_24dp_svg + property string shortcutText: JamiStrings.orderedList + property string shortcutKey: "Shift+Alt+7" + property bool isStyle: MDE.isPrefixSyle(messageBarTextArea, rectangle.text, "", true) + onTriggered: MDE.addPrefixStyle(messageBarTextArea, rectangle.text, "", true) + } + ] + + model: menuTypoActionsSecond + + delegate: PushButton { + anchors.verticalCenter: parent ? parent.verticalCenter : undefined + preferredSize: JamiTheme.chatViewFooterButtonSize + imageContainerWidth: 20 + imageContainerHeight: 20 + radius: 5 + + hoverEnabled: !showPreview + enabled: !showPreview + + toolTipText: modelData.shortcutText + shortcutKey: modelData.shortcutKey + hasShortcut: modelData.hasShortcut ? true : false + source: modelData.iconSrc + focusPolicy: Qt.TabFocus + + normalColor: { + if (showPreview) { + return JamiTheme.primaryBackgroundColor; + } else if (modelData.normalColor) { + return modelData.normalColor; + } else if (modelData.isStyle) { + return JamiTheme.hoveredButtonColor; + } else { + return JamiTheme.primaryBackgroundColor; + } + } + imageColor: { + if (showPreview) { + return JamiTheme.chatViewFooterImgDisableColor; + } else if (hovered) { + return JamiTheme.chatViewFooterImgHoverColor; + } else if (modelData.isStyle) { + return JamiTheme.chatViewFooterImgHoverColor; + } else { + return JamiTheme.chatViewFooterImgColor; + } + } + hoveredColor: JamiTheme.hoveredButtonColor + pressedColor: hoveredColor + + action: modelData + } + } + } + } + + Row { + id: secondRow + anchors.right: messageBarRowLayout.right + anchors.bottom: messageBarRowLayout.bottom + + PushButton { + id: typoButton + + preferredSize: JamiTheme.chatViewFooterButtonSize + imageContainerWidth: 24 + imageContainerHeight: 24 + + radius: JamiTheme.chatViewFooterButtonRadius + + hoverEnabled: !showPreview + enabled: !showPreview + + toolTipText: showTypo ? JamiStrings.hideFormatting : JamiStrings.showFormatting + source: JamiResources.text_edit_black_24dp_svg + + normalColor: showPreview ? JamiTheme.primaryBackgroundColor : (showTypo ? JamiTheme.hoveredButtonColor : JamiTheme.primaryBackgroundColor) + imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered || showTypo ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor) + hoveredColor: JamiTheme.hoveredButtonColor + pressedColor: hoveredColor + + onClicked: { + showTypo = !showTypo; + messageBarTextArea.isShowTypo = showTypo; + if (messageBar.width < messageBarLayoutMaximumWidth + sendMessageButton.width + 2 * JamiTheme.preferredMarginSize) + showTypoSecond = false; + if (!showDefault) + showDefault = true; + UtilsAdapter.setAppValue(Settings.Key.ShowMardownOption, showTypo); + UtilsAdapter.setAppValue(Settings.Key.ShowSendOption, !showDefault); + } + } + + 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 + property list<Action> menuMoreButton: [ + Action { + id: leaveAudioMessage + property string iconSrc: JamiResources.message_audio_black_24dp_svg + property string 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 string iconSrc: JamiResources.message_video_black_24dp_svg + property string 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 string iconSrc: JamiResources.localisation_sharing_send_pin_svg + property string 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.chatViewFooterButtonSize + imageContainerWidth: 20 + imageContainerHeight: 20 + radius: 5 + enabled: !showPreview + hoverEnabled: !showPreview + toolTipText: modelData.toolTip + source: modelData.iconSrc + + normalColor: showPreview ? JamiTheme.primaryBackgroundColor : (showTypo ? JamiTheme.hoveredButtonColor : JamiTheme.primaryBackgroundColor) + imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor) + hoveredColor: JamiTheme.hoveredButtonColor + pressedColor: hoveredColor + action: modelData + } + } + + Rectangle { + height: JamiTheme.chatViewFooterButtonSize + width: JamiTheme.chatViewFooterButtonSize + Layout.alignment: Qt.AlignRight + visible: !CurrentConversation.isSip + color: JamiTheme.transparentColor + ComboBox { + id: showMoreButton + focus: true + width: JamiTheme.chatViewFooterButtonSize + height: JamiTheme.chatViewFooterButtonSize + anchors.bottom: parent.bottom + enabled: !showPreview + hoverEnabled: !showPreview + + // Used to choose the correct color for the button. + readonly property bool highlight: down || hovered + + background: Rectangle { + implicitWidth: showMoreButton.width + implicitHeight: showMoreButton.height + radius: 5 + color: showMoreButton.highlight ? JamiTheme.hoveredButtonColor : JamiTheme.transparentColor + } + + MaterialToolTip { + id: toolTipMoreButton + + parent: showMoreButton + visible: showMoreButton.hovered && (text.length > 0) + delay: Qt.styleHints.mousePressAndHoldInterval + text: showMoreButton.down ? JamiStrings.showLess : JamiStrings.showMore + } + + indicator: ResponsiveImage { + + width: 20 + height: 20 + + anchors.verticalCenter: parent.verticalCenter + anchors.horizontalCenter: parent.horizontalCenter + + source: JamiResources.more_menu_black_24dp_svg + + color: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor) + } + + Component { + id: sharePopupComp + ShareMenu { + id: sharePopup + onAudioRecordMessageButtonClicked: rectangle.audioRecordMessageButtonClicked() + onVideoRecordMessageButtonClicked: rectangle.videoRecordMessageButtonClicked() + onShowMapClicked: rectangle.showMapClicked() + modelList: listViewMoreButton.menuMoreButton + y: showMoreButton.y + 31 + x: showMoreButton.x - 3 + } + } + + popup: ShareMenu { + id: sharePopup + onAudioRecordMessageButtonClicked: rectangle.audioRecordMessageButtonClicked() + onVideoRecordMessageButtonClicked: rectangle.videoRecordMessageButtonClicked() + onShowMapClicked: rectangle.showMapClicked() + modelList: listViewMoreButton.menuMoreButton + y: showMoreButton.y + 31 + x: showMoreButton.x - 3 + } + } + } + + ListView { + id: listViewAction + + width: contentWidth + 2 * leftMargin + + Behavior on width { + NumberAnimation { + duration: JamiTheme.longFadeDuration / 2 + } + } + + height: JamiTheme.chatViewFooterButtonSize + orientation: ListView.Horizontal + interactive: false + + property list<Action> menuActions: [ + Action { + id: sendFile + property string iconSrc: JamiResources.link_black_24dp_svg + property string toolTip: JamiStrings.sendFile + property bool show: true + property bool needWebEngine: false + property bool needVideoDevice: false + property bool noSip: false + onTriggered: function clickAction() { + sendFileButtonClicked(); + textAreaObj.forceActiveFocus(); + } + }, + Action { + id: addEmoji + property string iconSrc: JamiResources.emoji_black_24dp_svg + property string toolTip: JamiStrings.addEmoji + property bool show: true + property bool needWebEngine: true + property bool needVideoDevice: false + property bool noSip: true + onTriggered: function clickAction() { + emojiButtonClicked(); + } + } + ] + + 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: rectangle.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.chatViewFooterButtonSize + imageContainerWidth: 25 + imageContainerHeight: 25 + radius: 5 + + hoverEnabled: !showPreview + enabled: !showPreview + + toolTipText: modelData.toolTip + source: modelData.iconSrc + + normalColor: JamiTheme.primaryBackgroundColor + imageColor: showPreview ? JamiTheme.chatViewFooterImgDisableColor : (hovered ? JamiTheme.chatViewFooterImgHoverColor : JamiTheme.chatViewFooterImgColor) + hoveredColor: JamiTheme.hoveredButtonColor + pressedColor: hoveredColor + + action: modelData + } + } + + Rectangle { + Layout.alignment: Qt.AlignRight + height: JamiTheme.chatViewFooterButtonSize + width: JamiTheme.chatViewFooterButtonSize + Layout.rightMargin: marginSize / 2 + visible: true + color: JamiTheme.transparentColor + + PushButton { + id: sendMessageButton + + objectName: "sendMessageButton" + anchors.bottom: parent.bottom + + enabled: sendButtonVisibility + hoverEnabled: enabled + + 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: enabled ? JamiTheme.chatViewFooterSendButtonColor : JamiTheme.chatViewFooterSendButtonDisableColor + imageColor: enabled ? JamiTheme.chatViewFooterSendButtonImgColor : JamiTheme.chatViewFooterSendButtonImgColorDisable + hoveredColor: JamiTheme.buttonTintedBlueHovered + pressedColor: hoveredColor + + opacity: 1 + scale: opacity + + Behavior on opacity { + enabled: animate + NumberAnimation { + duration: JamiTheme.shortFadeDuration + easing.type: Easing.InOutQuad + } + } + + onClicked: { + rectangle.showPreview = false; + sendMessageButtonClicked(); + } + } + } + } +} diff --git a/src/app/mainview/components/MessageListView.qml b/src/app/mainview/components/MessageListView.qml index 11961b2b4..fe7caf8aa 100644 --- a/src/app/mainview/components/MessageListView.qml +++ b/src/app/mainview/components/MessageListView.qml @@ -19,40 +19,37 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Qt.labs.qmlmodels - import net.jami.Models 1.1 import net.jami.Adapters 1.1 import net.jami.Constants 1.1 - import "../../commoncomponents" JamiListView { id: root function getDistanceToBottom() { - const scrollDiff = ScrollBar.vertical.position - - (1.0 - ScrollBar.vertical.size) - return Math.abs(scrollDiff) * contentHeight + const scrollDiff = ScrollBar.vertical.position - (1.0 - ScrollBar.vertical.size); + return Math.abs(scrollDiff) * contentHeight; } function loadMoreMsgsIfNeeded() { if (atYBeginning && !CurrentConversation.allMessagesLoaded) { - MessagesAdapter.loadMoreMessages() + MessagesAdapter.loadMoreMessages(); } } function computeTimestampVisibility(item1, item1Index, item2, item2Index) { if (item1 && item2) { if (item1Index < item2Index) { - item1.showTime = item1.timestamp - item2.timestamp > JamiTheme.timestampIntervalTime - item1.showDay = item1.formattedDay !== item2.formattedDay + item1.showTime = item1.timestamp - item2.timestamp > JamiTheme.timestampIntervalTime; + item1.showDay = item1.formattedDay !== item2.formattedDay; } else { - item2.showTime = item2.timestamp - item1.timestamp > JamiTheme.timestampIntervalTime - item2.showDay = item2.formattedDay !== item1.formattedDay + item2.showTime = item2.timestamp - item1.timestamp > JamiTheme.timestampIntervalTime; + item2.showDay = item2.formattedDay !== item1.formattedDay; } - return true + return true; } - return false + return false; } function scrollToBottom() { @@ -60,27 +57,28 @@ JamiListView { } function computeChatview(item, itemIndex) { - if (!root) return - var rootItem = root.itemAtIndex(0) - var pItem = root.itemAtIndex(itemIndex - 1) - var pItemIndex = itemIndex - 1 - var nItem = root.itemAtIndex(itemIndex + 1) - var nItemIndex = itemIndex + 1 + if (!root) + return; + var rootItem = root.itemAtIndex(0); + var pItem = root.itemAtIndex(itemIndex - 1); + var pItemIndex = itemIndex - 1; + var nItem = root.itemAtIndex(itemIndex + 1); + var nItemIndex = itemIndex + 1; // middle insertion if (pItem && nItem) { - computeTimestampVisibility(item, itemIndex, nItem, nItemIndex) - computeSequencing(item, nItem, root.itemAtIndex(itemIndex + 2)) + computeTimestampVisibility(item, itemIndex, nItem, nItemIndex); + computeSequencing(item, nItem, root.itemAtIndex(itemIndex + 2)); } // top buffer insertion = scroll up if (pItem && !nItem) { - computeTimestampVisibility(item, itemIndex, pItem, pItemIndex) - computeSequencing(root.itemAtIndex(itemIndex - 2), pItem, item) + computeTimestampVisibility(item, itemIndex, pItem, pItemIndex); + computeSequencing(root.itemAtIndex(itemIndex - 2), pItem, item); } // bottom buffer insertion = scroll down if (!pItem && nItem) { - computeTimestampVisibility(item, itemIndex, nItem, nItemIndex) - computeSequencing(item, nItem, root.itemAtIndex(itemIndex + 2)) + computeTimestampVisibility(item, itemIndex, nItem, nItemIndex); + computeSequencing(item, nItem, root.itemAtIndex(itemIndex + 2)); } // index 0 insertion = new message if (itemIndex === 0) { @@ -88,57 +86,56 @@ JamiListView { // This needs to be done in a delayed fashion because the new message is inserted // at the top of the list and the list is not yet updated. Qt.callLater(() => { - var fItem = root.itemAtIndex(1) - if (fItem) { - computeTimestampVisibility(item, 0, fItem, 1) - computeSequencing(null, item, fItem) - computeSequencing(item, fItem, root.itemAtIndex(2)) - } - }) + var fItem = root.itemAtIndex(1); + if (fItem) { + computeTimestampVisibility(item, 0, fItem, 1); + computeSequencing(null, item, fItem); + computeSequencing(item, fItem, root.itemAtIndex(2)); + } + }); } // top element - if(itemIndex === root.count - 1 && CurrentConversation.allMessagesLoaded) { - item.showTime = true - item.showDay = true + if (itemIndex === root.count - 1 && CurrentConversation.allMessagesLoaded) { + item.showTime = true; + item.showDay = true; } } function computeSequencing(pItem, item, nItem) { if (root === undefined || !item) - return - + return; function isFirst() { - if (!nItem) return true + if (!nItem) + return true; else { - if (item.showTime || item.isReply ) { - return true + if (item.showTime || item.isReply) { + return true; } else if (nItem.author !== item.author) { - return true + return true; } } - return false + return false; } - function isLast() { - if (!pItem) return true + if (!pItem) + return true; else { if (pItem.showTime || pItem.isReply) { - return true + return true; } else if (pItem.author !== item.author) { - return true + return true; } } - return false + return false; } - if (isLast() && isFirst()) - item.seq = MsgSeq.single + item.seq = MsgSeq.single; if (!isLast() && isFirst()) - item.seq = MsgSeq.first + item.seq = MsgSeq.first; if (isLast() && !isFirst()) - item.seq = MsgSeq.last + item.seq = MsgSeq.last; if (!isLast() && !isFirst()) - item.seq = MsgSeq.middle + item.seq = MsgSeq.middle; } // fade-in mechanism @@ -151,12 +148,16 @@ JamiListView { SequentialAnimation { id: fadeAnimation NumberAnimation { - target: overlay; property: "opacity" - to: 1; duration: 0 + target: overlay + property: "opacity" + to: 1 + duration: 0 } NumberAnimation { - target: overlay; property: "opacity" - to: 0; duration: 240 + target: overlay + property: "opacity" + to: 0 + duration: 240 } } } @@ -167,7 +168,7 @@ JamiListView { anchors.fill: parent function instantiateToast(dest) { - instantiate(JamiStrings.fileSaved.arg(dest), 1000, 400) + instantiate(JamiStrings.fileSaved.arg(dest), 1000, 400); } } @@ -175,8 +176,8 @@ JamiListView { target: CurrentConversation function onScrollTo(id) { // Get the filtered index from the interaction ID. - var idx = MessagesAdapter.messageListModel.getDisplayIndex(id) - positionViewAtIndex(idx, ListView.Visible) + var idx = MessagesAdapter.messageListModel.getDisplayIndex(id); + positionViewAtIndex(idx, ListView.Visible); } } @@ -203,8 +204,8 @@ JamiListView { roleValue: Interaction.Type.TEXT TextMessageDelegate { - Component.onCompleted: { - computeChatview(this, index) + Component.onCompleted: { + computeChatview(this, index); } } } @@ -213,8 +214,8 @@ JamiListView { roleValue: Interaction.Type.CALL CallMessageDelegate { - Component.onCompleted: { - computeChatview(this, index) + Component.onCompleted: { + computeChatview(this, index); } } } @@ -223,8 +224,8 @@ JamiListView { roleValue: Interaction.Type.CONTACT ContactMessageDelegate { - Component.onCompleted: { - computeChatview(this, index) + Component.onCompleted: { + computeChatview(this, index); } } } @@ -234,8 +235,8 @@ JamiListView { GeneratedMessageDelegate { font.bold: true - Component.onCompleted: { - computeChatview(this, index) + Component.onCompleted: { + computeChatview(this, index); } } } @@ -244,12 +245,11 @@ JamiListView { roleValue: Interaction.Type.DATA_TRANSFER DataTransferMessageDelegate { - Component.onCompleted: { - computeChatview(this, index) + Component.onCompleted: { + computeChatview(this, index); } } } - } onAtYBeginningChanged: loadMoreMsgsIfNeeded() @@ -271,9 +271,8 @@ JamiListView { target: MessagesAdapter function onNewInteraction() { - if (root.getDistanceToBottom() < 80 && - !root.atYEnd) { - Qt.callLater(root.positionViewAtBeginning) + if (root.getDistanceToBottom() < 80 && !root.atYEnd) { + Qt.callLater(root.positionViewAtBeginning); } } @@ -284,7 +283,7 @@ JamiListView { } function onFileCopied(dest) { - toastManager.instantiateToast(dest) + toastManager.instantiateToast(dest); } } @@ -294,7 +293,7 @@ JamiListView { anchors.bottom: root.bottom anchors.bottomMargin: JamiTheme.chatViewScrollToBottomButtonBottomMargin anchors.horizontalCenter: root.horizontalCenter - visible: 1 - verticalScrollBar.position >= verticalScrollBar.size * 2 + visible: 1 - verticalScrollBar.position >= verticalScrollBar.size * 2 onClicked: scrollToBottom() } @@ -326,36 +325,31 @@ JamiListView { Connections { target: MessagesAdapter - function onCurrentConvComposingListChanged () { - var typeIndicatorNameTextString = "" - var nameList = MessagesAdapter.currentConvComposingList - + function onCurrentConvComposingListChanged() { + var typeIndicatorNameTextString = ""; + var nameList = MessagesAdapter.currentConvComposingList; if (nameList.length > 4) { - typeIndicatorNameText.text = "" - typeIndicatorEndingText.text = JamiStrings.typeIndicatorMax - typeIndicatorNameText.calculateWidth() - return + typeIndicatorNameText.text = ""; + typeIndicatorEndingText.text = JamiStrings.typeIndicatorMax; + typeIndicatorNameText.calculateWidth(); + return; } if (nameList.length === 1) { - typeIndicatorNameText.text = nameList[0] - typeIndicatorEndingText.text = - JamiStrings.typeIndicatorSingle.replace("{}", "") - typeIndicatorNameText.calculateWidth() - return + typeIndicatorNameText.text = nameList[0]; + typeIndicatorEndingText.text = JamiStrings.typeIndicatorSingle.replace("{}", ""); + typeIndicatorNameText.calculateWidth(); + return; } - for (var i = 0; i < nameList.length; i++) { - typeIndicatorNameTextString += nameList[i] - + typeIndicatorNameTextString += nameList[i]; if (i === nameList.length - 2) - typeIndicatorNameTextString += JamiStrings.typeIndicatorAnd + typeIndicatorNameTextString += JamiStrings.typeIndicatorAnd; else if (i !== nameList.length - 1) - typeIndicatorNameTextString += ", " + typeIndicatorNameTextString += ", "; } - typeIndicatorNameText.text = typeIndicatorNameTextString - typeIndicatorEndingText.text = - JamiStrings.typeIndicatorPlural.replace("{}", "") - typeIndicatorNameText.calculateWidth() + typeIndicatorNameText.text = typeIndicatorNameTextString; + typeIndicatorEndingText.text = JamiStrings.typeIndicatorPlural.replace("{}", ""); + typeIndicatorNameText.calculateWidth(); } } @@ -364,17 +358,13 @@ JamiListView { property int textWidth: 0 - function calculateWidth () { + function calculateWidth() { if (!text) - return 0 + return 0; else { - var textSize = JamiQmlUtils.getTextBoundingRect(font, text).width - var typingContentWidth = typingDots.width + typingDots.anchors.leftMargin - + typeIndicatorNameText.anchors.leftMargin - + typeIndicatorEndingText.contentWidth - typeIndicatorNameText.Layout.preferredWidth = - Math.min(typeIndicatorContainer.width - 5 - typingContentWidth, - textSize) + var textSize = JamiQmlUtils.getTextBoundingRect(font, text).width; + var typingContentWidth = typingDots.width + typingDots.anchors.leftMargin + typeIndicatorNameText.anchors.leftMargin + typeIndicatorEndingText.contentWidth; + typeIndicatorNameText.Layout.preferredWidth = Math.min(typeIndicatorContainer.width - 5 - typingContentWidth, textSize); } } diff --git a/src/app/mainview/components/MessagesResearchPanel.qml b/src/app/mainview/components/MessagesResearchPanel.qml index cbe1195e9..717b81218 100644 --- a/src/app/mainview/components/MessagesResearchPanel.qml +++ b/src/app/mainview/components/MessagesResearchPanel.qml @@ -98,7 +98,6 @@ Page { underlineColor: CurrentConversation.color underlineColorHovered: CurrentConversation.color - down: researchTabBar.currentIndex === 1 labelText: JamiStrings.files Layout.fillWidth: true diff --git a/src/app/net/jami/Constants/JamiTheme.qml b/src/app/net/jami/Constants/JamiTheme.qml index 0735aa592..2f148072c 100644 --- a/src/app/net/jami/Constants/JamiTheme.qml +++ b/src/app/net/jami/Constants/JamiTheme.qml @@ -513,6 +513,9 @@ Item { // MessageBar property int messageBarMarginSize: 10 property int messageBarMinimumWidth: 438 + property int showTypoSecondToggleWidth: 540 + property int messageBarMaximumHeight: 150 + property int messageBarMinimumHeight: 36 // InvitationView property real invitationViewAvatarSize: 112 diff --git a/tests/qml/src/tst_ChatViewFooter.qml b/tests/qml/src/tst_ChatViewFooter.qml index a100fe858..37f16ed33 100644 --- a/tests/qml/src/tst_ChatViewFooter.qml +++ b/tests/qml/src/tst_ChatViewFooter.qml @@ -53,19 +53,19 @@ ColumnLayout { var sendMessageButton = findChild(uut, "sendMessageButton") var messageBarTextArea = findChild(uut, "messageBarTextArea") - compare(sendMessageButton.visible, false) + compare(sendMessageButton.enabled, false) // Text in messageBarTextArea will cause sendMessageButton to show messageBarTextArea.insertText("test") - compare(sendMessageButton.visible, true) + compare(sendMessageButton.enabled, true) // Text cleared in messageBarTextArea will cause sendMessageButton to hide messageBarTextArea.clearText() - compare(sendMessageButton.visible, false) + compare(sendMessageButton.enabled, false) // Both are cleared messageBarTextArea.clearText() - compare(sendMessageButton.visible, false) + compare(sendMessageButton.enabled, false) } } } -- GitLab