mirror of
https://git.jami.net/savoirfairelinux/jami-client-qt.git
synced 2025-08-04 14:55:43 +02:00
MessageListView: fix message bubble UI
+ redesign the "Scroll to end of conversation" + redesign the "bubble / screen ratio" + redesign the reply bubbles: color, shape(in & out a message sequence), "In reply To" message + change the configurable color of the main user's bubbles + show the display name when replying to a transfer message + fix incorrectly loaded reply message data by synchronizing to messages loaded request + fix reply to an internet link + redesign the call bubbles (the new design need to be applied but in another patch) GitLab: #959 GitLab: #967 Change-Id: Id646ff875644425b03367838b5b46f2242294563
This commit is contained in:
parent
84d625c1b4
commit
d5064040d7
12 changed files with 266 additions and 118 deletions
|
@ -61,12 +61,10 @@ SBSMessageBase {
|
||||||
if (ConfId === "" && Duration === 0) {
|
if (ConfId === "" && Duration === 0) {
|
||||||
// If missed, we can add a darker pattern
|
// If missed, we can add a darker pattern
|
||||||
return isOutgoing ?
|
return isOutgoing ?
|
||||||
Qt.darker(JamiTheme.messageOutBgColor, 1.5) :
|
Qt.lighter(CurrentConversation.color, 1.5) :
|
||||||
Qt.darker(JamiTheme.messageInBgColor, 1.5)
|
Qt.darker(JamiTheme.messageInBgColor, 1.5)
|
||||||
}
|
}
|
||||||
return isOutgoing ?
|
return isOutgoing ? CurrentConversation.color : JamiTheme.messageInBgColor
|
||||||
JamiTheme.messageOutBgColor :
|
|
||||||
CurrentConversation.isCoreDialog ? JamiTheme.messageInBgColor : Qt.lighter(CurrentConversation.color, 1.5)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
innerContent.children: [
|
innerContent.children: [
|
||||||
|
@ -88,8 +86,13 @@ SBSMessageBase {
|
||||||
return Body
|
return Body
|
||||||
}
|
}
|
||||||
horizontalAlignment: Qt.AlignHCenter
|
horizontalAlignment: Qt.AlignHCenter
|
||||||
font.pointSize: JamiTheme.contactEventPointSize
|
|
||||||
|
font.pixelSize: JamiTheme.emojiBubbleSize
|
||||||
|
font.hintingPreference: Font.PreferNoHinting
|
||||||
font.bold: true
|
font.bold: true
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
textFormat: Text.MarkdownText
|
||||||
|
|
||||||
color: UtilsAdapter.luma(bubble.color) ?
|
color: UtilsAdapter.luma(bubble.color) ?
|
||||||
JamiTheme.chatviewTextColorLight :
|
JamiTheme.chatviewTextColorLight :
|
||||||
JamiTheme.chatviewTextColorDark
|
JamiTheme.chatviewTextColorDark
|
||||||
|
|
|
@ -26,9 +26,10 @@ Rectangle {
|
||||||
id: root
|
id: root
|
||||||
property bool out: true
|
property bool out: true
|
||||||
property int type: MsgSeq.single
|
property int type: MsgSeq.single
|
||||||
|
property bool isReply: false
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: mask
|
id: mask
|
||||||
visible: type !== MsgSeq.single
|
visible: type !== MsgSeq.single && !isReply
|
||||||
z: -1
|
z: -1
|
||||||
radius: 5
|
radius: 5
|
||||||
color: root.color
|
color: root.color
|
||||||
|
@ -40,4 +41,34 @@ Rectangle {
|
||||||
bottomMargin: type === MsgSeq.last ? root.height /2 : 0
|
bottomMargin: type === MsgSeq.last ? root.height /2 : 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: maskReply
|
||||||
|
visible: isReply
|
||||||
|
z: -1
|
||||||
|
radius: 5
|
||||||
|
color: root.color
|
||||||
|
anchors {
|
||||||
|
fill: parent
|
||||||
|
leftMargin: out ? 0 : root.width/2
|
||||||
|
rightMargin: !out ? 0 : root.width/2
|
||||||
|
topMargin: 0
|
||||||
|
bottomMargin: root.height /2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: maskReplyFirst
|
||||||
|
visible: isReply && type === MsgSeq.first
|
||||||
|
z: -2
|
||||||
|
radius: 5
|
||||||
|
color: root.color
|
||||||
|
anchors {
|
||||||
|
fill: parent
|
||||||
|
leftMargin: out ? root.width/2 : 0
|
||||||
|
rightMargin: out ? 0 : root.width/2
|
||||||
|
topMargin: root.width/5
|
||||||
|
bottomMargin: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,92 +19,89 @@ import QtQuick
|
||||||
import QtQuick.Controls
|
import QtQuick.Controls
|
||||||
import QtQuick.Layouts
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
import net.jami.Models 1.1
|
||||||
import net.jami.Adapters 1.1
|
import net.jami.Adapters 1.1
|
||||||
import net.jami.Constants 1.1
|
import net.jami.Constants 1.1
|
||||||
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
anchors.right: isOutgoing ? parent.right : undefined
|
|
||||||
|
|
||||||
visible: ReplyTo !== ""
|
width: body.width
|
||||||
width: visible ? replyToRow.width : 0
|
height: Math.min(JamiTheme.sbsMessageBaseMaximumReplyHeight, body.height)
|
||||||
height: replyToRow.height + replyToRow.anchors.topMargin
|
clip: true
|
||||||
|
|
||||||
|
property int requestId: -1
|
||||||
|
property var replyTransferName: MessagesAdapter.dataForInteraction(ReplyTo, MessageList.TransferName)
|
||||||
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
// Make sure we show the original post
|
// Make sure we show the original post
|
||||||
// In the future, we may just want to load the previous interaction of the thread
|
// In the future, we may just want to load the previous interaction of the thread
|
||||||
// and not show it, but for now we can simplify.
|
// and not show it, but for now we can simplify.
|
||||||
if (ReplyTo !== "")
|
if (ReplyTo !== "") {
|
||||||
MessagesAdapter.loadConversationUntil(ReplyTo)
|
// Store the request Id for later filtering.
|
||||||
|
requestId = MessagesAdapter.loadConversationUntil(ReplyTo)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
Connections {
|
||||||
|
target: MessagesAdapter
|
||||||
|
|
||||||
z: 2
|
function onMoreMessagesLoaded(loadingRequestId) {
|
||||||
anchors.fill: parent
|
// Filter for the request Id we're waiting for (now the message is loaded).
|
||||||
RowLayout {
|
if (requestId === loadingRequestId) {
|
||||||
id: replyToRow
|
requestId = -1
|
||||||
anchors.top: parent.top
|
replyTransferName = MessagesAdapter.dataForInteraction(ReplyTo, MessageList.TransferName)
|
||||||
anchors.topMargin: JamiTheme.preferredMarginSize / 2
|
}
|
||||||
|
}
|
||||||
property bool isSelf: ReplyToAuthor === CurrentAccount.uri || ReplyToAuthor === ""
|
|
||||||
|
|
||||||
Label {
|
|
||||||
id: replyTo
|
|
||||||
|
|
||||||
text: JamiStrings.inReplyTo
|
|
||||||
|
|
||||||
color: UtilsAdapter.luma(bubble.color) ?
|
|
||||||
JamiTheme.chatviewTextColorLight :
|
|
||||||
JamiTheme.chatviewTextColorDark
|
|
||||||
font.pointSize: JamiTheme.textFontSize
|
|
||||||
font.kerning: true
|
|
||||||
font.bold: true
|
|
||||||
Layout.leftMargin: JamiTheme.preferredMarginSize
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Avatar {
|
TextEdit {
|
||||||
id: avatarReply
|
|
||||||
|
|
||||||
Layout.preferredWidth: JamiTheme.avatarReadReceiptSize
|
|
||||||
Layout.preferredHeight: JamiTheme.avatarReadReceiptSize
|
|
||||||
|
|
||||||
showPresenceIndicator: false
|
|
||||||
|
|
||||||
imageId: {
|
|
||||||
if (replyToRow.isSelf)
|
|
||||||
return CurrentAccount.id
|
|
||||||
return ReplyToAuthor
|
|
||||||
}
|
|
||||||
mode: replyToRow.isSelf ? Avatar.Mode.Account : Avatar.Mode.Contact
|
|
||||||
}
|
|
||||||
|
|
||||||
Text {
|
|
||||||
id: body
|
id: body
|
||||||
Layout.maximumWidth: JamiTheme.preferredFieldWidth - JamiTheme.preferredMarginSize
|
|
||||||
Layout.rightMargin: JamiTheme.preferredMarginSize
|
|
||||||
|
|
||||||
TextMetrics {
|
text: replyTransferName ?
|
||||||
id: metrics
|
replyTransferName :
|
||||||
elide: Text.ElideRight
|
(ReplyToBody === "" && ReplyToAuthor !== "") ?
|
||||||
elideWidth: JamiTheme.preferredFieldWidth - JamiTheme.preferredMarginSize
|
JamiStrings.deleteReplyMessage :
|
||||||
text: ReplyToBody === "" && ReplyToAuthor !== "" ? "*(Deleted Message)*" : ReplyToBody
|
(ReplyToBody ? ReplyToBody : "")
|
||||||
}
|
|
||||||
|
|
||||||
|
width: Math.min(JamiTheme.sbsMessageBaseMaximumReplyWidth, implicitWidth)
|
||||||
|
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
|
||||||
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
|
selectByMouse: true
|
||||||
|
font.pixelSize: IsEmojiOnly? JamiTheme.chatviewEmojiSize : JamiTheme.emojiBubbleSize
|
||||||
|
font.hintingPreference: Font.PreferNoHinting
|
||||||
|
renderType: Text.NativeRendering
|
||||||
textFormat: Text.MarkdownText
|
textFormat: Text.MarkdownText
|
||||||
text: metrics.elidedText
|
readOnly: true
|
||||||
|
color: getBaseColor()
|
||||||
|
|
||||||
color: UtilsAdapter.luma(bubble.color) ?
|
function getBaseColor() {
|
||||||
JamiTheme.chatviewTextColorLight :
|
var baseColor
|
||||||
JamiTheme.chatviewTextColorDark
|
if (IsEmojiOnly) {
|
||||||
font.pointSize: JamiTheme.textFontSize
|
if (JamiTheme.darkTheme)
|
||||||
font.kerning: true
|
baseColor = JamiTheme.chatviewTextColorLight
|
||||||
font.bold: true
|
else
|
||||||
|
baseColor = JamiTheme.chatviewTextColorDark
|
||||||
|
} else {
|
||||||
|
if (UtilsAdapter.luma(replyBubble.color))
|
||||||
|
baseColor = JamiTheme.chatviewTextColorLight
|
||||||
|
else
|
||||||
|
baseColor = JamiTheme.chatviewTextColorDark
|
||||||
|
}
|
||||||
|
return baseColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: function(mouse) {
|
Rectangle {
|
||||||
CurrentConversation.scrollToMsg(ReplyTo)
|
anchors.fill: parent
|
||||||
|
visible: body.height > JamiTheme.sbsMessageBaseMaximumReplyHeight
|
||||||
|
gradient: Gradient {
|
||||||
|
GradientStop {position: 0.66 ; color: "transparent"}
|
||||||
|
GradientStop {position: 1 ; color: replyBubble.color}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,10 @@ Control {
|
||||||
width: listView.width
|
width: listView.width
|
||||||
height: mainColumnLayout.implicitHeight
|
height: mainColumnLayout.implicitHeight
|
||||||
|
|
||||||
|
property real textContentWidth
|
||||||
|
property real textContentHeight
|
||||||
|
property bool isReply: ReplyTo !== ""
|
||||||
|
|
||||||
// If the ListView attached properties are not available,
|
// If the ListView attached properties are not available,
|
||||||
// then the root delegate is likely a Loader.
|
// then the root delegate is likely a Loader.
|
||||||
readonly property ListView listView: ListView.view ?
|
readonly property ListView listView: ListView.view ?
|
||||||
|
@ -89,6 +93,7 @@ Control {
|
||||||
Item {
|
Item {
|
||||||
id: usernameblock
|
id: usernameblock
|
||||||
Layout.preferredHeight: (seq === MsgSeq.first || seq === MsgSeq.single) ? 10 : 0
|
Layout.preferredHeight: (seq === MsgSeq.first || seq === MsgSeq.single) ? 10 : 0
|
||||||
|
visible: !isReply
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
id: username
|
id: username
|
||||||
|
@ -104,11 +109,104 @@ Control {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: replyItem
|
||||||
|
property bool isSelf: ReplyToAuthor === CurrentAccount.uri
|
||||||
|
|
||||||
|
visible: root.isReply
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: childrenRect.height
|
||||||
|
|
||||||
|
Layout.topMargin: JamiTheme.sbsMessageBaseReplyTopMargin
|
||||||
|
Layout.leftMargin: isOutgoing ? undefined : JamiTheme.sbsMessageBaseReplyMargin
|
||||||
|
Layout.rightMargin: !isOutgoing ? undefined : JamiTheme.sbsMessageBaseReplyMargin
|
||||||
|
|
||||||
|
transform: Translate { y: JamiTheme.sbsMessageBaseReplyBottomMargin }
|
||||||
|
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
width: parent.width
|
||||||
|
spacing: 2
|
||||||
|
|
||||||
|
RowLayout{
|
||||||
|
id: replyToLayout
|
||||||
|
|
||||||
|
Layout.alignment: isOutgoing ? Qt.AlignRight : Qt.AlignLeft
|
||||||
|
property var replyUserName: UtilsAdapter.getBestNameForUri(CurrentAccount.id, ReplyToAuthor)
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: replyTo
|
||||||
|
|
||||||
|
text: isOutgoing ? JamiStrings.inReplyTo : UtilsAdapter.getBestNameForUri(CurrentAccount.id, Author) + JamiStrings.repliedTo
|
||||||
|
color: JamiTheme.messageReplyColor
|
||||||
|
font.pointSize: JamiTheme.textFontSize
|
||||||
|
font.kerning: true
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
|
|
||||||
|
Avatar {
|
||||||
|
id: avatarReply
|
||||||
|
|
||||||
|
visible: !replyItem.isSelf
|
||||||
|
Layout.preferredWidth: JamiTheme.avatarReadReceiptSize
|
||||||
|
Layout.preferredHeight: JamiTheme.avatarReadReceiptSize
|
||||||
|
showPresenceIndicator: false
|
||||||
|
imageId: {
|
||||||
|
if (replyItem.isSelf)
|
||||||
|
return CurrentAccount.id
|
||||||
|
return ReplyToAuthor
|
||||||
|
}
|
||||||
|
mode: replyItem.isSelf ? Avatar.Mode.Account : Avatar.Mode.Contact
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: replyToUserName
|
||||||
|
|
||||||
|
text: replyItem.isSelf ? JamiStrings.inReplyToMe : replyToLayout.replyUserName
|
||||||
|
color: JamiTheme.messageReplyColor
|
||||||
|
font.pointSize: JamiTheme.textFontSize
|
||||||
|
font.kerning: true
|
||||||
|
font.bold: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: replyBubble
|
||||||
|
|
||||||
|
z: -2
|
||||||
|
color: replyItem.isSelf ? Qt.lighter(CurrentConversation.color, 1.15) : Qt.lighter(JamiTheme.messageInBgColor, 1.05)
|
||||||
|
radius: msgRadius
|
||||||
|
|
||||||
|
Layout.preferredWidth: replyToRow.width + 2*JamiTheme.preferredMarginSize
|
||||||
|
Layout.preferredHeight: replyToRow.height + 2*JamiTheme.preferredMarginSize
|
||||||
|
Layout.alignment: isOutgoing ? Qt.AlignRight : Qt.AlignLeft
|
||||||
|
|
||||||
|
|
||||||
|
// place actual content here
|
||||||
|
ReplyToRow {
|
||||||
|
id: replyToRow
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
z: 2
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: function(mouse) {
|
||||||
|
CurrentConversation.scrollToMsg(ReplyTo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: msgRowlayout
|
id: msgRowlayout
|
||||||
|
|
||||||
Layout.preferredHeight: innerContent.height + root.extraHeight
|
Layout.preferredHeight: innerContent.height + root.extraHeight
|
||||||
Layout.topMargin: (seq === MsgSeq.first || seq === MsgSeq.single) ? 6 : 0
|
Layout.topMargin: ((seq === MsgSeq.first || seq === MsgSeq.single) && !root.isReply) ? 6 : 0
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: avatarBlock
|
id: avatarBlock
|
||||||
|
@ -151,9 +249,6 @@ Control {
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
visible: true
|
visible: true
|
||||||
|
|
||||||
// place actual content here
|
|
||||||
ReplyToRow {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
@ -232,33 +327,37 @@ Control {
|
||||||
MessageBubble {
|
MessageBubble {
|
||||||
id: bubble
|
id: bubble
|
||||||
|
|
||||||
|
property bool isEdited: PreviousBodies.length !== 0
|
||||||
visible: !IsEmojiOnly
|
visible: !IsEmojiOnly
|
||||||
z:-1
|
z:-1
|
||||||
out: isOutgoing
|
out: isOutgoing
|
||||||
type: seq
|
type: seq
|
||||||
|
isReply: root.isReply
|
||||||
|
|
||||||
|
|
||||||
function getBaseColor() {
|
function getBaseColor() {
|
||||||
var baseColor = isOutgoing ? JamiTheme.messageOutBgColor
|
var baseColor = isOutgoing ? CurrentConversation.color : JamiTheme.messageInBgColor
|
||||||
: CurrentConversation.isCoreDialog ?
|
|
||||||
JamiTheme.messageInBgColor :
|
|
||||||
Qt.lighter(CurrentConversation.color, 1.5)
|
|
||||||
if (Id === MessagesAdapter.replyToId || Id === MessagesAdapter.editId) {
|
if (Id === MessagesAdapter.replyToId || Id === MessagesAdapter.editId) {
|
||||||
// If we are replying to or editing the message
|
// If we are replying to or editing the message
|
||||||
return Qt.darker(baseColor, 1.5)
|
return Qt.darker(baseColor, 1.5)
|
||||||
}
|
}
|
||||||
return baseColor
|
return baseColor
|
||||||
}
|
}
|
||||||
|
|
||||||
color: getBaseColor()
|
color: getBaseColor()
|
||||||
radius: msgRadius
|
radius: msgRadius
|
||||||
anchors.right: isOutgoing ? parent.right : undefined
|
anchors.right: isOutgoing ? parent.right : undefined
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
width: innerContent.childrenRect.width
|
|
||||||
|
width: Type === Interaction.Type.TEXT && !isEdited ? root.textContentWidth : innerContent.childrenRect.width
|
||||||
height: innerContent.childrenRect.height + (visible ? root.extraHeight : 0)
|
height: innerContent.childrenRect.height + (visible ? root.extraHeight : 0)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: bg
|
id: bg
|
||||||
|
|
||||||
color: bubble.getBaseColor()
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
visible: false
|
visible: false
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,9 @@ SBSMessageBase {
|
||||||
formattedDay: MessagesAdapter.getFormattedDay(Timestamp)
|
formattedDay: MessagesAdapter.getFormattedDay(Timestamp)
|
||||||
extraHeight: extraContent.active && !isRemoteImage ? msgRadius : -isRemoteImage
|
extraHeight: extraContent.active && !isRemoteImage ? msgRadius : -isRemoteImage
|
||||||
textHovered: textHoverhandler.hovered
|
textHovered: textHoverhandler.hovered
|
||||||
|
textContentWidth: textEditId.width
|
||||||
|
textContentHeight: textEditId.height
|
||||||
|
|
||||||
|
|
||||||
innerContent.children: [
|
innerContent.children: [
|
||||||
TextEdit {
|
TextEdit {
|
||||||
|
@ -67,12 +70,12 @@ SBSMessageBase {
|
||||||
width: {
|
width: {
|
||||||
if (extraContent.active)
|
if (extraContent.active)
|
||||||
Math.max(extraContent.width,
|
Math.max(extraContent.width,
|
||||||
Math.min(implicitWidth - avatarBlockWidth,
|
Math.min((2/3)*root.maxMsgWidth,implicitWidth - avatarBlockWidth,
|
||||||
extraContent.minSize) - senderMargin )
|
extraContent.minSize) - senderMargin )
|
||||||
else if (isEmojiOnly)
|
else if (isEmojiOnly)
|
||||||
Math.min(implicitWidth, innerContent.width - senderMargin - (innerContent.width - senderMargin) % (JamiTheme.chatviewEmojiSize + 2))
|
Math.min((2/3)*root.maxMsgWidth,implicitWidth, innerContent.width - senderMargin - (innerContent.width - senderMargin) % (JamiTheme.chatviewEmojiSize + 2))
|
||||||
else
|
else
|
||||||
Math.min(implicitWidth, innerContent.width - senderMargin)
|
Math.min((2/3)*root.maxMsgWidth,implicitWidth, innerContent.width - senderMargin)
|
||||||
}
|
}
|
||||||
|
|
||||||
wrapMode: Label.WrapAtWordBoundaryOrAnywhere
|
wrapMode: Label.WrapAtWordBoundaryOrAnywhere
|
||||||
|
|
|
@ -361,7 +361,7 @@ Item {
|
||||||
property string search: qsTr("Search")
|
property string search: qsTr("Search")
|
||||||
|
|
||||||
// Chatview footer
|
// Chatview footer
|
||||||
property string jumpToLatest: qsTr("Jump to latest")
|
property string scrollToEnd: qsTr("Scroll to end of conversation")
|
||||||
property string typeIndicatorSingle: qsTr("{} is typing…")
|
property string typeIndicatorSingle: qsTr("{} is typing…")
|
||||||
property string typeIndicatorPlural: qsTr("{} are typing…")
|
property string typeIndicatorPlural: qsTr("{} are typing…")
|
||||||
property string typeIndicatorMax: qsTr("Several people are typing…")
|
property string typeIndicatorMax: qsTr("Several people are typing…")
|
||||||
|
@ -787,6 +787,8 @@ Item {
|
||||||
property string remove: qsTr("Remove")
|
property string remove: qsTr("Remove")
|
||||||
property string replyTo: qsTr("Reply to")
|
property string replyTo: qsTr("Reply to")
|
||||||
property string inReplyTo: qsTr("In reply to")
|
property string inReplyTo: qsTr("In reply to")
|
||||||
|
property string repliedTo: qsTr(" replied to")
|
||||||
|
property string inReplyToMe: qsTr("Me")
|
||||||
property string reply: qsTr("Reply")
|
property string reply: qsTr("Reply")
|
||||||
property string writeTo: qsTr("Write to %1")
|
property string writeTo: qsTr("Write to %1")
|
||||||
property string edit: qsTr("Edit")
|
property string edit: qsTr("Edit")
|
||||||
|
@ -848,6 +850,7 @@ Item {
|
||||||
|
|
||||||
//message options
|
//message options
|
||||||
property string deleteMessage: qsTr("Delete message")
|
property string deleteMessage: qsTr("Delete message")
|
||||||
|
property string deleteReplyMessage: qsTr("*(Deleted Message)*")
|
||||||
property string editMessage: qsTr("Edit message")
|
property string editMessage: qsTr("Edit message")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,8 +201,9 @@ Item {
|
||||||
property real chatviewFontSize: calcSize(15)
|
property real chatviewFontSize: calcSize(15)
|
||||||
property real chatviewEmojiSize: calcSize(60)
|
property real chatviewEmojiSize: calcSize(60)
|
||||||
property color timestampColor: darkTheme ? "#bbb" : "#777"
|
property color timestampColor: darkTheme ? "#bbb" : "#777"
|
||||||
|
property color messageReplyColor: darkTheme ? "#bbb" : "#A7A7A7"
|
||||||
property color messageOutTxtColor: "#000000"
|
property color messageOutTxtColor: "#000000"
|
||||||
property color messageInBgColor: darkTheme ? "#28b1ed" : "#e5e5e5"
|
property color messageInBgColor: "#e5e5e5"
|
||||||
property color messageOutBgColor: darkTheme? "#616161" : "#005699"
|
property color messageOutBgColor: darkTheme? "#616161" : "#005699"
|
||||||
property color messageInTxtColor: "#FFFFFF"
|
property color messageInTxtColor: "#FFFFFF"
|
||||||
property color fileOutTimestampColor: darkTheme ? "#eee" : "#555"
|
property color fileOutTimestampColor: darkTheme ? "#eee" : "#555"
|
||||||
|
@ -441,6 +442,12 @@ Item {
|
||||||
|
|
||||||
// SBSMessageBase
|
// SBSMessageBase
|
||||||
property int sbsMessageBasePreferredPadding: 12
|
property int sbsMessageBasePreferredPadding: 12
|
||||||
|
property int sbsMessageBaseMaximumReplyWidth: baseZoom * 300
|
||||||
|
property int sbsMessageBaseMaximumReplyHeight: baseZoom * 40
|
||||||
|
property int sbsMessageBaseReplyBottomMargin: baseZoom * 10
|
||||||
|
property int sbsMessageBaseReplyMargin: 45
|
||||||
|
property int sbsMessageBaseReplyTopMargin: 6
|
||||||
|
|
||||||
|
|
||||||
// MessageBar
|
// MessageBar
|
||||||
property int messageBarMarginSize: 10
|
property int messageBarMarginSize: 10
|
||||||
|
|
|
@ -31,6 +31,7 @@ import "../../commoncomponents"
|
||||||
JamiListView {
|
JamiListView {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
|
||||||
function getDistanceToBottom() {
|
function getDistanceToBottom() {
|
||||||
const scrollDiff = ScrollBar.vertical.position -
|
const scrollDiff = ScrollBar.vertical.position -
|
||||||
(1.0 - ScrollBar.vertical.size)
|
(1.0 - ScrollBar.vertical.size)
|
||||||
|
@ -107,7 +108,7 @@ JamiListView {
|
||||||
function isFirst() {
|
function isFirst() {
|
||||||
if (!nItem) return true
|
if (!nItem) return true
|
||||||
else {
|
else {
|
||||||
if (item.showTime) {
|
if (item.showTime || item.isReply ) {
|
||||||
return true
|
return true
|
||||||
} else if (nItem.author !== item.author) {
|
} else if (nItem.author !== item.author) {
|
||||||
return true
|
return true
|
||||||
|
@ -119,7 +120,7 @@ JamiListView {
|
||||||
function isLast() {
|
function isLast() {
|
||||||
if (!pItem) return true
|
if (!pItem) return true
|
||||||
else {
|
else {
|
||||||
if (pItem.showTime) {
|
if (pItem.showTime || pItem.isReply) {
|
||||||
return true
|
return true
|
||||||
} else if (pItem.author !== item.author) {
|
} else if (pItem.author !== item.author) {
|
||||||
return true
|
return true
|
||||||
|
@ -202,12 +203,10 @@ JamiListView {
|
||||||
model: MessagesAdapter.messageListModel
|
model: MessagesAdapter.messageListModel
|
||||||
delegate: DelegateChooser {
|
delegate: DelegateChooser {
|
||||||
id: delegateChooser
|
id: delegateChooser
|
||||||
|
|
||||||
role: "Type"
|
role: "Type"
|
||||||
|
|
||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
id: delegateChoice
|
id: delegateChoice
|
||||||
|
|
||||||
roleValue: Interaction.Type.TEXT
|
roleValue: Interaction.Type.TEXT
|
||||||
|
|
||||||
TextMessageDelegate {
|
TextMessageDelegate {
|
||||||
|
@ -257,8 +256,10 @@ JamiListView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
onAtYBeginningChanged: loadMoreMsgsIfNeeded()
|
onAtYBeginningChanged: loadMoreMsgsIfNeeded()
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
|
@ -271,7 +272,7 @@ JamiListView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onMoreMessagesLoaded() {
|
function onMoreMessagesLoaded(loadingRequestId) {
|
||||||
if (root.contentHeight < root.height || root.atYBeginning) {
|
if (root.contentHeight < root.height || root.atYBeginning) {
|
||||||
root.loadMoreMsgsIfNeeded()
|
root.loadMoreMsgsIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ import QtQuick.Controls
|
||||||
import Qt5Compat.GraphicalEffects
|
import Qt5Compat.GraphicalEffects
|
||||||
|
|
||||||
import net.jami.Constants 1.1
|
import net.jami.Constants 1.1
|
||||||
|
import net.jami.Adapters 1.1
|
||||||
|
|
||||||
|
|
||||||
import "../../commoncomponents"
|
import "../../commoncomponents"
|
||||||
|
|
||||||
|
@ -28,12 +30,10 @@ Control {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property alias activeStateTrigger: activeState.when
|
property alias activeStateTrigger: activeState.when
|
||||||
|
|
||||||
signal clicked
|
signal clicked
|
||||||
|
|
||||||
height: jumpToLatestText.contentHeight + 15
|
height: jumpToLatestText.contentHeight + 15
|
||||||
width: jumpToLatestText.contentWidth + arrowDropDown.width + 50
|
width: jumpToLatestText.contentWidth + arrowDropDown.width + 50
|
||||||
|
|
||||||
opacity: 0
|
opacity: 0
|
||||||
|
|
||||||
states: State {
|
states: State {
|
||||||
|
@ -76,38 +76,41 @@ Control {
|
||||||
Text {
|
Text {
|
||||||
id: jumpToLatestText
|
id: jumpToLatestText
|
||||||
|
|
||||||
anchors.left: parent.left
|
anchors.right: parent.right
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
|
||||||
font.weight: Font.DemiBold
|
font.weight: Font.Bold
|
||||||
font.pointSize: JamiTheme.textFontSize + 2
|
font.pointSize: JamiTheme.textFontSize + 2
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
|
||||||
text: JamiStrings.jumpToLatest
|
text: JamiStrings.scrollToEnd
|
||||||
color: JamiTheme.whiteColor
|
color: UtilsAdapter.luma(CurrentConversation.color) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResponsiveImage {
|
ResponsiveImage {
|
||||||
id: arrowDropDown
|
id: arrowDropDown
|
||||||
|
|
||||||
anchors.left: jumpToLatestText.right
|
anchors.right: jumpToLatestText.left
|
||||||
anchors.leftMargin: 3
|
anchors.rightMargin: 3
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
anchors.verticalCenterOffset: 2
|
anchors.verticalCenterOffset: 0
|
||||||
|
|
||||||
containerWidth: 12
|
containerWidth: jumpToLatestText.contentHeight
|
||||||
containerHeight: 12
|
containerHeight: jumpToLatestText.contentHeight
|
||||||
|
rotation: -90
|
||||||
|
|
||||||
color: JamiTheme.whiteColor
|
color: UtilsAdapter.luma(CurrentConversation.color) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark
|
||||||
source: JamiResources.down_triangle_arrow_black_24dp_svg
|
source: JamiResources.back_24dp_svg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
radius: 20
|
radius: 20
|
||||||
color: JamiTheme.jamiDarkBlue
|
color: CurrentConversation.color
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
|
@ -106,7 +106,7 @@ MessagesAdapter::loadMoreMessages()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
MessagesAdapter::loadConversationUntil(const QString& to)
|
MessagesAdapter::loadConversationUntil(const QString& to)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
@ -118,13 +118,14 @@ MessagesAdapter::loadConversationUntil(const QString& to)
|
||||||
const auto& convInfo = lrcInstance_->getConversationFromConvUid(convId, accountId);
|
const auto& convInfo = lrcInstance_->getConversationFromConvUid(convId, accountId);
|
||||||
if (convInfo.isSwarm()) {
|
if (convInfo.isSwarm()) {
|
||||||
auto* convModel = lrcInstance_->getCurrentConversationModel();
|
auto* convModel = lrcInstance_->getCurrentConversationModel();
|
||||||
convModel->loadConversationUntil(convId, to);
|
return convModel->loadConversationUntil(convId, to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
qWarning() << e.what();
|
qWarning() << e.what();
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -550,11 +551,11 @@ MessagesAdapter::onPreviewInfoReady(QString messageId, QVariantMap info)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MessagesAdapter::onConversationMessagesLoaded(uint32_t, const QString& convId)
|
MessagesAdapter::onConversationMessagesLoaded(uint32_t loadingRequestId, const QString& convId)
|
||||||
{
|
{
|
||||||
if (convId != lrcInstance_->get_selectedConvUid())
|
if (convId != lrcInstance_->get_selectedConvUid())
|
||||||
return;
|
return;
|
||||||
Q_EMIT moreMessagesLoaded();
|
Q_EMIT moreMessagesLoaded(loadingRequestId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -75,13 +75,13 @@ Q_SIGNALS:
|
||||||
void newFilePasted(QString filePath);
|
void newFilePasted(QString filePath);
|
||||||
void newTextPasted();
|
void newTextPasted();
|
||||||
void previewInformationToQML(QString messageId, QStringList previewInformation);
|
void previewInformationToQML(QString messageId, QStringList previewInformation);
|
||||||
void moreMessagesLoaded();
|
void moreMessagesLoaded(qint32 loadingRequestId);
|
||||||
void timestampUpdated();
|
void timestampUpdated();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Q_INVOKABLE bool isDocument(const interaction::Type& type);
|
Q_INVOKABLE bool isDocument(const interaction::Type& type);
|
||||||
Q_INVOKABLE void loadMoreMessages();
|
Q_INVOKABLE void loadMoreMessages();
|
||||||
Q_INVOKABLE void loadConversationUntil(const QString& to);
|
Q_INVOKABLE qint32 loadConversationUntil(const QString& to);
|
||||||
Q_INVOKABLE void connectConversationModel();
|
Q_INVOKABLE void connectConversationModel();
|
||||||
Q_INVOKABLE void sendConversationRequest();
|
Q_INVOKABLE void sendConversationRequest();
|
||||||
Q_INVOKABLE void removeConversation(const QString& convUid);
|
Q_INVOKABLE void removeConversation(const QString& convUid);
|
||||||
|
|
|
@ -485,8 +485,8 @@ MessageListModel::dataForItem(item_t item, int, int role) const
|
||||||
return QVariant("");
|
return QVariant("");
|
||||||
auto linkified = data(repliedMsg, Role::Linkified).toString();
|
auto linkified = data(repliedMsg, Role::Linkified).toString();
|
||||||
if (!linkified.isEmpty())
|
if (!linkified.isEmpty())
|
||||||
return QVariant(linkified.replace("\n", " "));
|
return QVariant(linkified);
|
||||||
return QVariant(data(repliedMsg, Role::Body).toString().replace("\n", " "));
|
return QVariant(data(repliedMsg, Role::Body).toString());
|
||||||
}
|
}
|
||||||
case Role::TotalSize:
|
case Role::TotalSize:
|
||||||
return QVariant(item.second.commit["totalSize"].toInt());
|
return QVariant(item.second.commit["totalSize"].toInt());
|
||||||
|
|
Loading…
Add table
Reference in a new issue