Skip to content
Snippets Groups Projects
Commit 04a57dfd authored by Capucine Berthet's avatar Capucine Berthet Committed by Sébastien Blin
Browse files

ConversationBubble: add time inside bubble

GitLab: #1325
Change-Id: Ib52222f4adae911e0975f4d7e8bc60739fb63cfb
parent 4a3a49b0
Branches
Tags
No related merge requests found
...@@ -56,13 +56,6 @@ SBSMessageBase { ...@@ -56,13 +56,6 @@ SBSMessageBase {
visible: isActive || ConfId === "" || Duration > 0 visible: isActive || ConfId === "" || Duration > 0
property var baseColor: isOutgoing? CurrentConversation.color : JamiTheme.messageInBgColor property var baseColor: isOutgoing? CurrentConversation.color : JamiTheme.messageInBgColor
bubble.color: {
if (ConfId === "" && Duration === 0) {
// If missed, we can add a darker pattern
return Qt.lighter(root.baseColor, 1.15)
}
return root.baseColor
}
innerContent.children: [ innerContent.children: [
RowLayout { RowLayout {
...@@ -73,9 +66,10 @@ SBSMessageBase { ...@@ -73,9 +66,10 @@ SBSMessageBase {
Label { Label {
id: callLabel id: callLabel
padding: 10
Layout.margins: 8 Layout.margins: 8
Layout.fillWidth: true Layout.fillWidth: true
Layout.rightMargin: root.timeWidth + 16
text: { text: {
if (root.isActive) if (root.isActive)
......
...@@ -79,6 +79,9 @@ Loader { ...@@ -79,6 +79,9 @@ Loader {
formattedTime: root.formattedTime formattedTime: root.formattedTime
formattedDay: root.formattedTime formattedDay: root.formattedTime
extraHeight: progressBar.visible ? 18 : 0 extraHeight: progressBar.visible ? 18 : 0
Component.onCompleted: bubble.timestampItem.visible = false
innerContent.children: [ innerContent.children: [
RowLayout { RowLayout {
id: transferItem id: transferItem
...@@ -257,6 +260,7 @@ Loader { ...@@ -257,6 +260,7 @@ Loader {
id: localMediaMsgItem id: localMediaMsgItem
isOutgoing: Author === CurrentAccount.uri isOutgoing: Author === CurrentAccount.uri
property var transferStats: MessagesAdapter.getTransferStats(Id, Status)
showTime: root.showTime showTime: root.showTime
seq: root.seq seq: root.seq
author: Author author: Author
...@@ -266,7 +270,21 @@ Loader { ...@@ -266,7 +270,21 @@ Loader {
readers: Readers readers: Readers
formattedTime: MessagesAdapter.getFormattedTime(Timestamp) formattedTime: MessagesAdapter.getFormattedTime(Timestamp)
formattedDay: MessagesAdapter.getFormattedDay(Timestamp) formattedDay: MessagesAdapter.getFormattedDay(Timestamp)
bubble.visible: false
Component.onCompleted: {
if (transferStats.totalSize !== undefined) {
var totalSize = transferStats.totalSize !== 0 ? transferStats.totalSize : TotalSize
var txt = UtilsAdapter.humanFileSize(totalSize)
}
bubble.timestampItem.timeLabel.text += " - " + txt
bubble.color = "transparent"
bubble.timestampItem.timeColor = JamiTheme.whiteColor
bubble.timestampItem.timeLabel.opacity = 1
bubble.z = 1
}
innerContent.children: [ innerContent.children: [
Loader { Loader {
id: localMediaCompLoader id: localMediaCompLoader
...@@ -296,6 +314,7 @@ Loader { ...@@ -296,6 +314,7 @@ Loader {
} }
Component { Component {
id: animatedImageComp id: animatedImageComp
AnimatedImage { AnimatedImage {
id: animatedImg id: animatedImg
...@@ -337,6 +356,22 @@ Loader { ...@@ -337,6 +356,22 @@ Loader {
} }
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
} }
LinearGradient {
id: gradient
anchors.fill: parent
start: Qt.point(0, height / 3)
gradient: Gradient {
GradientStop {
position: 0.0
color: JamiTheme.transparentColor
}
GradientStop {
position: 1.0
color: JamiTheme.darkGreyColorOpacityFade
}
}
}
} }
} }
...@@ -394,6 +429,22 @@ Loader { ...@@ -394,6 +429,22 @@ Loader {
} }
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
} }
LinearGradient {
id: gradient
anchors.fill: parent
start: Qt.point(0, height / 3)
gradient: Gradient {
GradientStop {
position: 0.0
color: JamiTheme.transparentColor
}
GradientStop {
position: 1.0
color: JamiTheme.darkGreyColorOpacityFade
}
}
}
} }
} }
} }
......
...@@ -37,6 +37,7 @@ Rectangle { ...@@ -37,6 +37,7 @@ Rectangle {
Rectangle { Rectangle {
id: mask id: mask
visible: type !== MsgSeq.single && !isReply visible: type !== MsgSeq.single && !isReply
z: -1 z: -1
radius: 5 radius: 5
......
...@@ -49,7 +49,7 @@ Control { ...@@ -49,7 +49,7 @@ Control {
property int timestamp: Timestamp property int timestamp: Timestamp
readonly property real senderMargin: 64 readonly property real senderMargin: 64
readonly property real avatarSize: 20 readonly property real avatarSize: 20
readonly property real msgRadius: 20 readonly property real msgRadius: 10
readonly property real hPadding: JamiTheme.sbsMessageBasePreferredPadding readonly property real hPadding: JamiTheme.sbsMessageBasePreferredPadding
property bool textHovered: false property bool textHovered: false
property alias replyAnimation: selectAnimation property alias replyAnimation: selectAnimation
...@@ -59,8 +59,11 @@ Control { ...@@ -59,8 +59,11 @@ Control {
property real textContentWidth property real textContentWidth
property real textContentHeight property real textContentHeight
property bool isReply: ReplyTo !== "" property bool isReply: ReplyTo !== ""
property real timeWidth: timestampItem.width
property real editedWidth: editedRow.visible ? editedRow.width + 10 : 0
property real maxMsgWidth: root.width - senderMargin - 2 * hPadding - avatarBlockWidth property real maxMsgWidth: root.width - senderMargin - 2 * hPadding - avatarBlockWidth
property bool bigMsg
// 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.
...@@ -86,11 +89,8 @@ Control { ...@@ -86,11 +89,8 @@ Control {
spacing: 0 spacing: 0
TimestampInfo { TimestampInfo {
id: timestampItem id: dateItem
showDay: root.showDay showDay: root.showDay
showTime: root.showTime
formattedTime: root.formattedTime
formattedDay: root.formattedDay formattedDay: root.formattedDay
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
Layout.fillWidth: true Layout.fillWidth: true
...@@ -101,12 +101,10 @@ Control { ...@@ -101,12 +101,10 @@ Control {
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 visible: !isReply
Layout.topMargin: (seq === MsgSeq.first || seq === MsgSeq.single) && !isOutgoing && !root.showTime ? 20 : 0
Label { Label {
id: username id: username
text: UtilsAdapter.getBestNameForUri(CurrentAccount.id, Author) text: UtilsAdapter.getBestNameForUri(CurrentAccount.id, Author)
font.bold: true
visible: (seq === MsgSeq.first || seq === MsgSeq.single) && !isOutgoing visible: (seq === MsgSeq.first || seq === MsgSeq.single) && !isOutgoing
font.pointSize: JamiTheme.smallFontSize font.pointSize: JamiTheme.smallFontSize
color: JamiTheme.chatviewSecondaryInformationColor color: JamiTheme.chatviewSecondaryInformationColor
...@@ -212,7 +210,7 @@ Control { ...@@ -212,7 +210,7 @@ Control {
RowLayout { RowLayout {
id: msgRowlayout id: msgRowlayout
Layout.preferredHeight: innerContent.height + root.extraHeight + (emojiReactions.emojis === "" ? 0 : emojiReactions.height - 8) Layout.preferredHeight: innerContent.height + root.extraHeight + (emojiReactions.emojis === "" ? 0 : emojiReactions.height - 8) + (IsEmojiOnly && (root.seq === MsgSeq.last || root.seq === MsgSeq.single) && emojiReactions.emojis === "" ? 15 : 0)
Layout.topMargin: ((seq === MsgSeq.first || seq === MsgSeq.single) && !root.isReply) ? 6 : 0 Layout.topMargin: ((seq === MsgSeq.first || seq === MsgSeq.single) && !root.isReply) ? 6 : 0
Item { Item {
...@@ -238,19 +236,7 @@ Control { ...@@ -238,19 +236,7 @@ Control {
Layout.fillHeight: true Layout.fillHeight: true
Layout.fillWidth: true Layout.fillWidth: true
MouseArea {
id: bubbleArea
anchors.fill: bubble
hoverEnabled: true
onClicked: function (mouse) {
if (root.hoveredLink) {
MessagesAdapter.openUrl(root.hoveredLink);
}
}
property bool bubbleHovered: containsMouse || textHovered
}
Column { Column {
id: innerContent id: innerContent
...@@ -351,18 +337,93 @@ Control { ...@@ -351,18 +337,93 @@ Control {
id: bubble id: bubble
property bool isEdited: PreviousBodies.length !== 0 property bool isEdited: PreviousBodies.length !== 0
visible: !IsEmojiOnly
z: -1 z: -1
out: isOutgoing out: isOutgoing
type: seq type: seq
isReply: root.isReply isReply: root.isReply
color: root.getBaseColor() color: IsEmojiOnly ? "transparent" : root.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: Type === Interaction.Type.TEXT && !isEdited ? root.textContentWidth : innerContent.childrenRect.width property real timePosition: JamiTheme.emojiMargins + emojiReactions.width + 8
height: innerContent.childrenRect.height + (visible ? root.extraHeight : 0) property alias timestampItem: timestampItem
width: (Type === Interaction.Type.TEXT ? root.textContentWidth : innerContent.childrenRect.width)
height: innerContent.childrenRect.height + (visible ? root.extraHeight : 0) + (root.bigMsg ? 15 : 0)
TimestampInfo {
id: timestampItem
showTime: IsEmojiOnly && !(root.seq === MsgSeq.last || root.seq === MsgSeq.single) ? false : true
formattedTime: root.formattedTime
timeColor: IsEmojiOnly ? (JamiTheme.darkTheme ? "white" : "dark") : (UtilsAdapter.luma(bubble.color) ? "white" : "dark")
timeLabel.opacity: 0.5
anchors.bottom: parent.bottom
anchors.right: IsEmojiOnly ? (isOutgoing ? parent.right : undefined) : parent.right
anchors.left: (IsEmojiOnly && !isOutgoing) ? parent.left : undefined
anchors.leftMargin: (IsEmojiOnly && !isOutgoing && emojiReactions.visible) ? bubble.timePosition : 0
anchors.rightMargin: IsEmojiOnly ? ((isOutgoing && emojiReactions.visible) ? bubble.timePosition : 0) : 10
timeLabel.Layout.bottomMargin: {
if (IsEmojiOnly)
return -15;
if (root.bigMsg)
return 5;
return 9;
}
}
RowLayout {
id: editedRow
anchors.left: root.bigMsg ? bubble.left : timestampItem.left
anchors.bottom: parent.bottom
anchors.bottomMargin: root.bigMsg ? 6 : 10
anchors.leftMargin: root.bigMsg ? 10 : - timestampItem.width - 10
visible: bubble.isEdited
z: 1
ResponsiveImage {
id: editedImage
source: JamiResources.round_edit_24dp_svg
width: 12
height: 12
color: editedLabel.color
opacity: 0.5
}
Text {
id: editedLabel
text: JamiStrings.edited
color: UtilsAdapter.luma(bubble.color) ? "white" : "dark"
opacity: 0.5
font.pixelSize: JamiTheme.timestampFont
}
TapHandler {
acceptedButtons: Qt.LeftButton
onTapped: {
viewCoordinator.presentDialog(appWindow, "commoncomponents/EditedPopup.qml", {
"previousBodies": PreviousBodies
});
}
}
}
MouseArea {
id: bubbleArea
anchors.fill: parent
hoverEnabled: true
onClicked: function (mouse) {
if (root.hoveredLink) {
MessagesAdapter.openUrl(root.hoveredLink);
}
}
property bool bubbleHovered: containsMouse || textHovered
}
} }
EmojiReactions { EmojiReactions {
...@@ -376,7 +437,7 @@ Control { ...@@ -376,7 +437,7 @@ Control {
borderColor: root.getBaseColor() borderColor: root.getBaseColor()
maxWidth: 2 / 3 * maxMsgWidth - JamiTheme.emojiMargins maxWidth: 2 / 3 * maxMsgWidth - JamiTheme.emojiMargins
state: root.isOutgoing ? "anchorsRight" : (emojiReactions.width > bubble.width - JamiTheme.emojiMargins ? "anchorsLeft" : "anchorsRight") state: root.isOutgoing ? "anchorsRight" : (IsEmojiOnly ? "anchorsLeft" :(emojiReactions.width > bubble.width - JamiTheme.emojiMargins ? "anchorsLeft" : "anchorsRight"))
TapHandler { TapHandler {
onTapped: { onTapped: {
...@@ -519,7 +580,7 @@ Control { ...@@ -519,7 +580,7 @@ Control {
orientation: ListView.Horizontal orientation: ListView.Horizontal
Layout.preferredHeight: { Layout.preferredHeight: {
if (showTime || seq === MsgSeq.last) if (showTime || seq === MsgSeq.last)
return contentHeight + timestampItem.contentHeight; return contentHeight + dateItem.contentHeight;
else if (readsMultiple.visible) else if (readsMultiple.visible)
return JamiTheme.avatarReadReceiptSize; return JamiTheme.avatarReadReceiptSize;
return 0; return 0;
......
...@@ -33,6 +33,8 @@ SBSMessageBase { ...@@ -33,6 +33,8 @@ SBSMessageBase {
property string colorUrl: UtilsAdapter.luma(bubble.color) ? JamiTheme.chatviewLinkColorLight : JamiTheme.chatviewLinkColorDark property string colorUrl: UtilsAdapter.luma(bubble.color) ? JamiTheme.chatviewLinkColorLight : JamiTheme.chatviewLinkColorDark
property string colorText: UtilsAdapter.luma(bubble.color) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark property string colorText: UtilsAdapter.luma(bubble.color) ? JamiTheme.chatviewTextColorLight : JamiTheme.chatviewTextColorDark
bigMsg: textEditId.lineCount > 1
Connections { Connections {
target: bubble target: bubble
function onColorChanged(color) { function onColorChanged(color) {
...@@ -52,14 +54,14 @@ SBSMessageBase { ...@@ -52,14 +54,14 @@ 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 textContentWidth: textEditId.width + (bigMsg ? 0 : root.timeWidth + root.editedWidth)
textContentHeight: textEditId.height textContentHeight: textEditId.height
innerContent.children: [ innerContent.children: [
TextEdit { TextEdit {
id: textEditId id: textEditId
padding: isEmojiOnly ? 0 : JamiTheme.preferredMarginSize padding: isEmojiOnly ? 0 : 10
anchors.right: isOutgoing ? parent.right : undefined anchors.right: isOutgoing ? parent.right : undefined
text: { text: {
if (Body !== "" && ParsedBody.length === 0) { if (Body !== "" && ParsedBody.length === 0) {
...@@ -80,9 +82,11 @@ SBSMessageBase { ...@@ -80,9 +82,11 @@ SBSMessageBase {
else if (isEmojiOnly) else if (isEmojiOnly)
Math.min((2 / 3) * root.maxMsgWidth, 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((2 / 3) * root.maxMsgWidth, implicitWidth, innerContent.width - senderMargin); Math.max(Math.min((2 / 3) * root.maxMsgWidth - ( bigMsg ? 0 : root.timeWidth + root.editedWidth), implicitWidth + 5, innerContent.width - senderMargin + 5), bigMsg ? root.timeWidth + root.editedWidth + 14: 0) ;
} }
anchors.rightMargin: bigMsg ? 0 : root.timeWidth + root.editedWidth
wrapMode: Label.WrapAtWordBoundaryOrAnywhere wrapMode: Label.WrapAtWordBoundaryOrAnywhere
selectByMouse: true selectByMouse: true
font.pointSize: isEmojiOnly ? JamiTheme.chatviewEmojiSize : JamiTheme.mediumFontSize font.pointSize: isEmojiOnly ? JamiTheme.chatviewEmojiSize : JamiTheme.mediumFontSize
...@@ -126,48 +130,7 @@ SBSMessageBase { ...@@ -126,48 +130,7 @@ SBSMessageBase {
selectOnly: parent.readOnly selectOnly: parent.readOnly
} }
}, },
RowLayout {
id: editedRow
anchors.right: isOutgoing ? parent.right : undefined
visible: PreviousBodies.length !== 0
ResponsiveImage {
id: editedImage
Layout.leftMargin: JamiTheme.preferredMarginSize
Layout.bottomMargin: JamiTheme.preferredMarginSize
source: JamiResources.round_edit_24dp_svg
width: JamiTheme.editedFontSize
height: JamiTheme.editedFontSize
layer {
enabled: true
effect: ColorOverlay {
color: editedLabel.color
}
}
}
Text {
id: editedLabel
Layout.rightMargin: JamiTheme.preferredMarginSize
Layout.bottomMargin: JamiTheme.preferredMarginSize
text: JamiStrings.edited
color: root.colorText
font.pointSize: JamiTheme.editedFontSize
TapHandler {
acceptedButtons: Qt.LeftButton
onTapped: {
viewCoordinator.presentDialog(appWindow, "commoncomponents/EditedPopup.qml", {
"previousBodies": PreviousBodies
});
}
}
}
},
Loader { Loader {
id: extraContent id: extraContent
......
...@@ -31,6 +31,8 @@ ColumnLayout { ...@@ -31,6 +31,8 @@ ColumnLayout {
property string formattedTime property string formattedTime
property string formattedDay property string formattedDay
property real detailsOpacity: 0.6 property real detailsOpacity: 0.6
property color timeColor: JamiTheme.chatviewSecondaryInformationColor
property alias timeLabel: formattedTimeLabel
spacing: 0 spacing: 0
...@@ -97,8 +99,8 @@ ColumnLayout { ...@@ -97,8 +99,8 @@ ColumnLayout {
Layout.topMargin: 30 Layout.topMargin: 30
Layout.bottomMargin: 30 Layout.bottomMargin: 30
Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom Layout.alignment: Qt.AlignHCenter | Qt.AlignBottom
color: JamiTheme.chatviewSecondaryInformationColor color: root.timeColor
visible: showTime || showDay visible: showTime
Layout.preferredHeight: visible * implicitHeight Layout.preferredHeight: visible * implicitHeight
font.pointSize: JamiTheme.smallFontSize font.pointSize: JamiTheme.smallFontSize
} }
......
...@@ -109,7 +109,7 @@ JamiListView { ...@@ -109,7 +109,7 @@ JamiListView {
function isFirst() { function isFirst() {
if (!nItem) return true if (!nItem) return true
else { else {
if (item.showTime || item.isReply || nItem.isEmojiOnly ) { 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
...@@ -121,7 +121,7 @@ JamiListView { ...@@ -121,7 +121,7 @@ JamiListView {
function isLast() { function isLast() {
if (!pItem) return true if (!pItem) return true
else { else {
if (pItem.showTime || pItem.isReply || pItem.isEmojiOnly) { 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
......
...@@ -716,8 +716,7 @@ MessagesAdapter::getFormattedTime(const quint64 timestamp) ...@@ -716,8 +716,7 @@ MessagesAdapter::getFormattedTime(const quint64 timestamp)
auto curLocal = QLocale(curLang); auto curLocal = QLocale(curLang);
auto curTime = QDateTime::fromSecsSinceEpoch(timestamp).time(); auto curTime = QDateTime::fromSecsSinceEpoch(timestamp).time();
QString timeLocale; QString timeLocale;
timeLocale = curLocal.toString(curTime, curLocal.ShortFormat); timeLocale = curLocal.toString(curTime, curLocal.ShortFormat).toLower();
return timeLocale; return timeLocale;
} }
return QObject::tr("just now"); return QObject::tr("just now");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment