Skip to content
Snippets Groups Projects
Commit a29d5f79 authored by Andreas Hatziiliou's avatar Andreas Hatziiliou
Browse files

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
parent 5186c273
No related branches found
No related tags found
No related merge requests found
......@@ -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
......
......@@ -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,21 +199,23 @@ 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
......@@ -226,8 +234,10 @@ Rectangle {
}
}
JamiPushButton { QWKSetParentHitTestVisible {}
JamiPushButton {
id: detailsButton
QWKSetParentHitTestVisible {
}
objectName: "detailsButton"
checkable: true
......
......@@ -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
......
......@@ -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,93 +52,18 @@ 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 )
onShowTypoChanged: {
onSendMessageButtonClicked: {
messageBarTextArea.restoreVisibilityAfterSend();
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
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;
}
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
}
}
onShowTypoChanged: {
messageBarTextArea.forceActiveFocus();
}
Rectangle {
id: rectangle
Layout.fillWidth: true
Layout.fillHeight: true
Layout.alignment: Qt.AlignBottom
height: Math.min(JamiTheme.chatViewFooterTextAreaMaximumHeight + 2 * marginSize, colLayout.height + 2 * marginSize)
radius: 5
color: JamiTheme.transparentColor
......@@ -148,8 +71,7 @@ RowLayout {
border.width: 2
onWidthChanged: {
height = Qt.binding(() => root.height);
if (width < JamiTheme.messageBarMinimumWidth) {
if (width < JamiTheme.showTypoSecondToggleWidth) {
showTypoSecond = false;
} else {
showTypoSecond = true;
......@@ -157,23 +79,46 @@ RowLayout {
}
GridLayout {
id: rowLayout
id: colLayout
columns: 2
rows: 3
columnSpacing: 0
rowSpacing: 0
anchors.fill: parent
anchors {
left: parent.left
right: parent.right
top: parent.top
margins: marginSize
}
Rectangle {
id: messageRow
property bool isExpanding: !(showTypo && dataTransferSendContainer.visible) && (textAreaObj.textWidth >= rectangle.width - formatRow.width - 8 * marginSize)
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,586 +257,12 @@ 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
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
}
}
}
}
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
visible: showTypo && messageBarTextArea.text
anchors.top: parent.top
anchors.right: parent.right
anchors.rightMargin: marginSize
preferredSize: JamiTheme.chatViewFooterButtonSize
imageContainerWidth: 25
imageContainerHeight: 25
......@@ -916,67 +273,43 @@ RowLayout {
hoveredColor: JamiTheme.hoveredButtonColor
pressedColor: hoveredColor
toolTipText: showPreview ? JamiStrings.continueEditing : JamiStrings.showPreview
Layout.margins: marginSize / 2
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
FilesToSendContainer {
id: dataTransferSendContainer
Behavior on opacity {
enabled: animate
NumberAnimation {
duration: JamiTheme.shortFadeDuration
easing.type: Easing.InOutQuad
}
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
}
}
}
......@@ -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,39 +80,25 @@ 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;
}
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() {
cachedText = textArea.text;
MessagesAdapter.parseMessage("", textArea.text, false, "", "");
} else {
textArea.textFormatChanged.disconnect(resetEditableText);
textArea.textFormatChanged.connect(resetEditableText);
}
}
......@@ -124,54 +106,29 @@ JamiFlickable {
target: MessagesAdapter
function onMessageParsed(messageId, messageText) {
if (messageId === "") {
textAreaPreview.text = messageText;
}
textArea.text = messageText;
textArea.update();
}
}
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);
}
}
......
/*
* 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();
}
}
}
}
}
......@@ -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)
var fItem = root.itemAtIndex(1);
if (fItem) {
computeTimestampVisibility(item, 0, fItem, 1)
computeSequencing(null, item, fItem)
computeSequencing(item, fItem, root.itemAtIndex(2))
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
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
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);
}
}
......@@ -204,7 +205,7 @@ JamiListView {
TextMessageDelegate {
Component.onCompleted: {
computeChatview(this, index)
computeChatview(this, index);
}
}
}
......@@ -214,7 +215,7 @@ JamiListView {
CallMessageDelegate {
Component.onCompleted: {
computeChatview(this, index)
computeChatview(this, index);
}
}
}
......@@ -224,7 +225,7 @@ JamiListView {
ContactMessageDelegate {
Component.onCompleted: {
computeChatview(this, index)
computeChatview(this, index);
}
}
}
......@@ -235,7 +236,7 @@ JamiListView {
GeneratedMessageDelegate {
font.bold: true
Component.onCompleted: {
computeChatview(this, index)
computeChatview(this, index);
}
}
}
......@@ -245,11 +246,10 @@ JamiListView {
DataTransferMessageDelegate {
Component.onCompleted: {
computeChatview(this, index)
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);
}
}
......@@ -327,35 +326,30 @@ JamiListView {
target: MessagesAdapter
function onCurrentConvComposingListChanged() {
var typeIndicatorNameTextString = ""
var nameList = MessagesAdapter.currentConvComposingList
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();
}
}
......@@ -366,15 +360,11 @@ JamiListView {
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);
}
}
......
......@@ -98,7 +98,6 @@ Page {
underlineColor: CurrentConversation.color
underlineColorHovered: CurrentConversation.color
down: researchTabBar.currentIndex === 1
labelText: JamiStrings.files
Layout.fillWidth: true
......
......@@ -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
......
......@@ -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)
}
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment