diff --git a/qml.qrc b/qml.qrc index db29de3b8b1abe9a38e05d3960851ee564a5efbe..99bff5e8ec0024b2978b55443bc6a5a6059ee674 100644 --- a/qml.qrc +++ b/qml.qrc @@ -203,5 +203,6 @@ <file>src/app/mainview/components/CustomizeTipBox.qml</file> <file>src/app/mainview/components/BackupTipBox.qml</file> <file>src/app/mainview/components/InformativeTipBox.qml</file> + <file>src/app/commoncomponents/TimestampInfo.qml</file> </qresource> </RCC> diff --git a/src/app/commoncomponents/ContactMessageDelegate.qml b/src/app/commoncomponents/ContactMessageDelegate.qml index b79cf28e8621e2f37648797466c4b60b7aaaa2ed..33c82aceb2424bf46721340bbabc1e111cb71620 100644 --- a/src/app/commoncomponents/ContactMessageDelegate.qml +++ b/src/app/commoncomponents/ContactMessageDelegate.qml @@ -27,74 +27,67 @@ Column { id: root property bool showTime: false - property int seq: MsgSeq.single - property alias font: textLabel.font - + property bool showDay: false + property int timestamp: Timestamp + property string formattedTime: MessagesAdapter.getFormattedTime(Timestamp) + property string formattedDay: MessagesAdapter.getFormattedDay(Timestamp) + property int seq: MsgSeq.single//a changer par textlabel width: ListView.view ? ListView.view.width : 0 - spacing: 2 topPadding: 12 bottomPadding: 12 - Rectangle { - id: msg - + ColumnLayout { anchors.horizontalCenter: parent.horizontalCenter - width: childrenRect.width - height: JamiTheme.contactMessageAvatarSize + 12 - radius: JamiTheme.contactMessageAvatarSize / 2 + 6 - - color: "transparent" - border.width: 1 - border.color: CurrentConversation.isCoreDialog ? JamiTheme.messageInBgColor : CurrentConversation.color - - RowLayout { - anchors.verticalCenter: parent.verticalCenter - - Avatar { - Layout.leftMargin: 6 - - width: JamiTheme.contactMessageAvatarSize - height: JamiTheme.contactMessageAvatarSize - visible: ActionUri !== "" - - imageId: ActionUri !== CurrentAccount.uri ? ActionUri : CurrentAccount.id - showPresenceIndicator: false - mode: ActionUri !== CurrentAccount.uri ? Avatar.Mode.Contact : Avatar.Mode.Account - } + TimestampInfo { + id:timestampItem - Label { - Layout.rightMargin: 6 - - id: textLabel - width: parent.width - text: Body - horizontalAlignment: Qt.AlignHCenter - font.pointSize: JamiTheme.contactEventPointSize - font.bold: true - color: JamiTheme.chatviewTextColor - } + showDay: root.showDay + showTime: root.showTime + formattedTime: root.formattedTime + formattedDay: root.formattedDay + Layout.alignment: Qt.AlignHCenter } - } - - Item { - id: infoCell - width: parent.width - height: childrenRect.height - - Label { - text: MessagesAdapter.getFormattedTime(Timestamp) - color: JamiTheme.timestampColor - visible: showTime || seq === MsgSeq.last - height: visible * implicitHeight - font.pointSize: 9 - - anchors.horizontalCenter: parent.horizontalCenter + Rectangle { + id: msg + + width: childrenRect.width + height: JamiTheme.contactMessageAvatarSize + 12 + radius: JamiTheme.contactMessageAvatarSize / 2 + 6 + Layout.alignment: Qt.AlignVCenter + color: "transparent" + border.width: 1 + border.color: CurrentConversation.isCoreDialog ? JamiTheme.messageInBgColor : CurrentConversation.color + + RowLayout { + anchors.verticalCenter: parent.verticalCenter + + Avatar { + Layout.leftMargin: 6 + width: JamiTheme.contactMessageAvatarSize + height: JamiTheme.contactMessageAvatarSize + visible: ActionUri !== "" + imageId: ActionUri !== CurrentAccount.uri ? ActionUri : CurrentAccount.id + showPresenceIndicator: false + mode: ActionUri !== CurrentAccount.uri ? Avatar.Mode.Contact : Avatar.Mode.Account + } + + Label { + id: textLabel + + Layout.rightMargin: 6 + width: parent.width + text: Body + horizontalAlignment: Qt.AlignHCenter + font.pointSize: JamiTheme.contactEventPointSize + font.bold: true + color: JamiTheme.chatviewTextColor + } + } } } - opacity: 0 Behavior on opacity { NumberAnimation { duration: 100 } } Component.onCompleted: opacity = 1 diff --git a/src/app/commoncomponents/DataTransferMessageDelegate.qml b/src/app/commoncomponents/DataTransferMessageDelegate.qml index 6eb572079d3549ba28e9a0ada21dba54160131d1..d4dd426fa847f1262fa80b8de3d2dd95c4480049 100644 --- a/src/app/commoncomponents/DataTransferMessageDelegate.qml +++ b/src/app/commoncomponents/DataTransferMessageDelegate.qml @@ -31,7 +31,12 @@ Loader { id: root property var mediaInfo - property bool showTime: false + property bool showTime + property bool showDay + property int timestamp: Timestamp + property string formattedTime: MessagesAdapter.getFormattedTime(Timestamp) + property string formattedDay: MessagesAdapter.getFormattedDay(Timestamp) + property int seq: MsgSeq.single property string author: Author @@ -70,7 +75,9 @@ Loader { transferName: TransferName transferId: Id readers: Readers - formattedTime: MessagesAdapter.getFormattedTime(Timestamp) + timestamp: root.timestamp + formattedTime: root.formattedTime + formattedDay: root.formattedTime extraHeight: progressBar.visible ? 18 : 0 innerContent.children: [ RowLayout { @@ -247,6 +254,7 @@ Loader { transferId: Id readers: Readers formattedTime: MessagesAdapter.getFormattedTime(Timestamp) + formattedDay: MessagesAdapter.getFormattedDay(Timestamp) bubble.visible: false innerContent.children: [ Loader { @@ -332,7 +340,7 @@ Loader { sourceSize.width: width sourceSize.height: height source: "file:///" + Body - property real aspectRatio: implicitWidth / implicitHeight + property real aspectRatio: width / implicitHeight property real adjustedWidth: Math.min(maxSize, Math.max(minSize, innerContent.width - senderMargin)) diff --git a/src/app/commoncomponents/GeneratedMessageDelegate.qml b/src/app/commoncomponents/GeneratedMessageDelegate.qml index fa37c3198c281158f89121cd4527cebca790b58e..d37fc01341cc48fd9f21b80b6687ed9b83e8d478 100644 --- a/src/app/commoncomponents/GeneratedMessageDelegate.qml +++ b/src/app/commoncomponents/GeneratedMessageDelegate.qml @@ -29,38 +29,37 @@ Column { id: root property bool showTime: false + property bool showDay: false property int seq: MsgSeq.single property alias font: textLabel.font - + property int timestamp: Timestamp + property string formattedTime: MessagesAdapter.getFormattedTime(Timestamp) + property string formattedDay: MessagesAdapter.getFormattedDay(Timestamp) width: ListView.view ? ListView.view.width : 0 - spacing: 2 topPadding: 12 bottomPadding: 12 + ColumnLayout { - Label { - id: textLabel width: parent.width - text: Body - horizontalAlignment: Qt.AlignHCenter - font.pointSize: 12 - color: JamiTheme.chatviewTextColor - } - Item { - id: infoCell + TimestampInfo { + id:timestampItem - width: parent.width - height: childrenRect.height + showDay: root.showDay + showTime: root.showTime + formattedTime: root.formattedTime + formattedDay: root.formattedDay + Layout.alignment: Qt.AlignHCenter + } Label { - text: MessagesAdapter.getFormattedTime(Timestamp) - color: JamiTheme.timestampColor - visible: showTime || seq === MsgSeq.last - height: visible * implicitHeight - font.pointSize: 9 + id: textLabel - anchors.horizontalCenter: parent.horizontalCenter + text: Body + Layout.alignment: Qt.AlignHCenter + font.pointSize: 12 + color: JamiTheme.chatviewTextColor } } diff --git a/src/app/commoncomponents/SBSMessageBase.qml b/src/app/commoncomponents/SBSMessageBase.qml index b4b075435b2dac520111c790bd3295dfcb59e634..a2d1bc3e1716f96c1b45f01f9ea94a98bba6fa63 100644 --- a/src/app/commoncomponents/SBSMessageBase.qml +++ b/src/app/commoncomponents/SBSMessageBase.qml @@ -37,26 +37,26 @@ Control { // these MUST be set but we won't use the 'required' keyword yet property bool isOutgoing - property bool showTime + property bool showTime: false + property bool showDay: false property int seq property string author property string transferId property string registeredNameText property string transferName - property string formattedTime + property string formattedTime: MessagesAdapter.getFormattedTime(Timestamp) + property string formattedDay: MessagesAdapter.getFormattedDay(Timestamp) property string location property string id: Id property string hoveredLink property var readers: [] - + property int timestamp: Timestamp readonly property real senderMargin: 64 readonly property real avatarSize: 20 readonly property real msgRadius: 20 readonly property real hPadding: JamiTheme.sbsMessageBasePreferredPadding - width: ListView.view ? ListView.view.width : 0 height: mainColumnLayout.implicitHeight - rightPadding: hPadding leftPadding: hPadding @@ -64,11 +64,21 @@ Control { id: mainColumnLayout anchors.centerIn: parent - width: parent.width - hPadding * 2 - spacing: 0 + TimestampInfo { + id: timestampItem + + showDay: root.showDay + showTime: root.showTime + formattedTime: root.formattedTime + formattedDay: root.formattedDay + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: true + Layout.fillHeight: true + } + Item { id: usernameblock @@ -78,7 +88,7 @@ Control { id: username 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.pixelSize: JamiTheme.usernameBlockFontSize color: JamiTheme.chatviewUsernameColor lineHeight: JamiTheme.usernameBlockLineHeight @@ -107,17 +117,15 @@ Control { } } - MouseArea { id: itemMouseArea - + Layout.fillWidth: true Layout.fillHeight: true - acceptedButtons: Qt.LeftButton | Qt.RightButton onClicked: function (mouse) { if (mouse.button === Qt.RightButton - && (transferId !== "" || Type === Interaction.Type.TEXT)) { + && (transferId !== "" || Type === Interaction.Type.TEXT)) { // Context Menu for Transfers ctxMenu.x = mouse.x ctxMenu.y = mouse.y @@ -142,8 +150,8 @@ Control { type: seq function getBaseColor() { var baseColor = isOutgoing ? JamiTheme.messageOutBgColor - : CurrentConversation.isCoreDialog ? - JamiTheme.messageInBgColor : Qt.lighter(CurrentConversation.color, 1.5) + : CurrentConversation.isCoreDialog ? + JamiTheme.messageInBgColor : Qt.lighter(CurrentConversation.color, 1.5) if (Id === MessagesAdapter.replyToId) { // If we are replying to return Qt.darker(baseColor, 1.5) @@ -194,6 +202,7 @@ Control { id: readsOne visible: root.readers.length === 1 && CurrentAccount.sendReadReceipt + width: { if (root.readers.length === 0) return 0 @@ -216,28 +225,12 @@ Control { orientation: ListView.Horizontal Layout.preferredHeight: { if (showTime || seq === MsgSeq.last) - return contentHeight + formattedTimeLabel.contentHeight + return contentHeight + timestampItem.contentHeight else if (readsMultiple.visible) return JamiTheme.avatarReadReceiptSize return 0 } - - Label { - id: formattedTimeLabel - - text: formattedTime - color: JamiTheme.timestampColor - visible: showTime || seq === MsgSeq.last - height: visible * implicitHeight - font.pointSize: 9 - topPadding : 4 - anchors.rightMargin: status.width - anchors.right: !isOutgoing ? undefined : readsMultiple.left - anchors.left: isOutgoing ? undefined : parent.left - anchors.leftMargin: avatarBlockWidth + 6 - } - ReadStatus { id: readsMultiple visible: root.readers.length > 1 && CurrentAccount.sendReadReceipt @@ -254,7 +247,6 @@ Control { anchors.topMargin: 1 readers: root.readers } - } } diff --git a/src/app/commoncomponents/TextMessageDelegate.qml b/src/app/commoncomponents/TextMessageDelegate.qml index 35b95d2fb2f5a00a47b2e902acc69c69420b634c..0177699767b9c880086e776e1f97173272c64a09 100644 --- a/src/app/commoncomponents/TextMessageDelegate.qml +++ b/src/app/commoncomponents/TextMessageDelegate.qml @@ -21,7 +21,6 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts import Qt5Compat.GraphicalEffects - import net.jami.Models 1.1 import net.jami.Adapters 1.1 import net.jami.Constants 1.1 @@ -31,25 +30,21 @@ SBSMessageBase { id : root property bool isRemoteImage - property real maxMsgWidth: root.width - senderMargin - 2 * hPadding - avatarBlockWidth - isOutgoing: Author === "" author: Author readers: Readers + timestamp: Timestamp formattedTime: MessagesAdapter.getFormattedTime(Timestamp) + formattedDay: MessagesAdapter.getFormattedDay(Timestamp) extraHeight: extraContent.active && !isRemoteImage ? msgRadius : -isRemoteImage innerContent.children: [ TextEdit { - padding: JamiTheme.preferredMarginSize anchors.right: isOutgoing ? parent.right : undefined - text: Body - horizontalAlignment: Text.AlignLeft - width: { if (extraContent.active) Math.max(extraContent.width, @@ -62,9 +57,7 @@ SBSMessageBase { height: implicitHeight wrapMode: Label.WrapAtWordBoundaryOrAnywhere selectByMouse: true - font.pixelSize: JamiTheme.chatviewFontSize - font.hintingPreference: Font.PreferNoHinting renderType: Text.NativeRendering textFormat: Text.MarkdownText diff --git a/src/app/commoncomponents/TimestampInfo.qml b/src/app/commoncomponents/TimestampInfo.qml new file mode 100644 index 0000000000000000000000000000000000000000..8ba9e3a53147b0d0157858596681ac5e8a60d2de --- /dev/null +++ b/src/app/commoncomponents/TimestampInfo.qml @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2022 Savoir-faire Linux Inc. + * Author: Nicolas Vengeon <nicolas.vengeon@savoirfairelinux.com> + * + * 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 "../mainview/components/" +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import net.jami.Models 1.1 +import net.jami.Adapters 1.1 +import net.jami.Constants 1.1 + +ColumnLayout{ + id: root + + property bool showTime + property bool showDay + property string formattedTime + property string formattedDay + property real detailsOpacity: 0.6 + + Connections { + target: MessagesAdapter.messageListModel + function onTimestampUpdate() { + if (showTime || showDay) { + formattedTime = MessagesAdapter.getFormattedTime(Timestamp) + } + } + } + + Item { + visible: showDay + Layout.alignment: Qt.AlignHCenter + Layout.fillHeight: true + Layout.fillWidth: true + Layout.topMargin: JamiTheme.dayTimestampTopMargin + + Rectangle { + id: line + + height: 1 + opacity: detailsOpacity + color:JamiTheme.timestampColor + width: chatView.width - JamiTheme.timestampLinePadding + anchors.centerIn: parent + } + + Rectangle { + id: dayRectangle + + width: borderRectangle.width + height: borderRectangle.height + radius: 5 + color: JamiTheme.chatviewBgColor + Layout.fillHeight: true + anchors.centerIn: parent + + Rectangle { + id: borderRectangle + + border { color: JamiTheme.timestampColor; width: 1} + opacity: detailsOpacity + width: formattedDayLabel.width + JamiTheme.dayTimestampVPadding + height: formattedDayLabel.height + JamiTheme.dayTimestampHPadding + radius: dayRectangle.radius + color: JamiTheme.transparentColor + } + + Text { + id: formattedDayLabel + + color: JamiTheme.chatviewTextColor + anchors { verticalCenter: parent.verticalCenter; horizontalCenter: parent.horizontalCenter} + text: formattedDay + font.pointSize: JamiTheme.timestampFont + } + } + } + + Label { + id: formattedTimeLabel + + text: formattedTime + Layout.bottomMargin: JamiTheme.timestampBottomMargin + Layout.topMargin: JamiTheme.timestampTopMargin + Layout.alignment: Qt.AlignHCenter + color: JamiTheme.timestampColor + visible: showTime + height: visible * implicitHeight + font.pointSize: JamiTheme.timestampFont + } +} diff --git a/src/app/constant/JamiTheme.qml b/src/app/constant/JamiTheme.qml index 509e056183b886b18321514bbd5bfab85f9264eb..0bccb0fef408e2b5b3c811af3e3d068bd51f1b0d 100644 --- a/src/app/constant/JamiTheme.qml +++ b/src/app/constant/JamiTheme.qml @@ -321,6 +321,16 @@ Item { property real lineEditContextMenuItemsWidth: 100 property real lineEditContextMenuSeparatorsHeight: 2 + //TimestampInfo + property int timestampLinePadding: 40 + property int dayTimestampTopMargin: 30 + property int timestampBottomMargin: 42 + property int timestampTopMargin: 20 + property int dayTimestampHPadding: 16 + property real dayTimestampVPadding: 32 + property real timestampFont: calcSize(12) + property int timestampIntervalTime: 120 + // Jami switch property real switchIndicatorRadius: 30 diff --git a/src/app/mainview/components/MessageListView.qml b/src/app/mainview/components/MessageListView.qml index 4ba0b162e226712216d117a791f5e3e6d36c64f3..0c4357035e22917a73793a72fb87890faffb24cf 100644 --- a/src/app/mainview/components/MessageListView.qml +++ b/src/app/mainview/components/MessageListView.qml @@ -44,105 +44,95 @@ JamiListView { MessagesAdapter.loadMoreMessages() } - // sequencing/timestamps (2-sided style) - function computeTimestampVisibility(item, itemIndex) { - if (root === undefined) - return - var nItem = root.itemAtIndex(itemIndex - 1) - if (nItem && itemIndex !== root.count - 1) { - item.showTime = (nItem.timestamp - item.timestamp) > 60 && - nItem.formattedTime !== item.formattedTime - } else { - item.showTime = true - var pItem = root.itemAtIndex(itemIndex + 1) - if (pItem) { - pItem.showTime = (item.timestamp - pItem.timestamp) > 60 && - pItem.formattedTime !== item.formattedTime + + 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 + }else { + item2.showTime = item2.timestamp - item1.timestamp > JamiTheme.timestampIntervalTime + item2.showDay = item2.formattedDay !== item1.formattedDay } + return true } + return false } - function computeSequencing(computeItem, computeItemIndex) { - if (root === undefined) - return - var cItem = { - 'author': computeItem.author, - 'showTime': computeItem.showTime + 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 + //Middle insertion + if (pItem && nItem) { + computeTimestampVisibility(item, itemIndex, nItem, nItemIndex) + computeSequencing(nItemIndex, nItem, root.itemAtIndex(itemIndex + 2), item) } - var pItem = root.itemAtIndex(computeItemIndex + 1) - var nItem = root.itemAtIndex(computeItemIndex - 1) - - let isSeq = (item0, item1) => - item0.author === item1.author && !item0.showTime - - let setSeq = function (newSeq, item) { - if (item === undefined) - computeItem.seq = newSeq - else - item.seq = newSeq + //top buffer insertion = scroll up + if (pItem && !nItem) { + computeTimestampVisibility(item, itemIndex, pItem, pItemIndex) + computeSequencing(pItemIndex, pItem, item, root.itemAtIndex(itemIndex - 2)) } - - let rAdjustSeq = function (item) { - if (item.seq === MsgSeq.last) - item.seq = MsgSeq.middle - else if (item.seq === MsgSeq.single) - setSeq(MsgSeq.first, item) + //bottom buffer insertion = scroll down + if (!pItem && nItem) { + computeTimestampVisibility(item, itemIndex, nItem, nItemIndex) + computeSequencing(nItemIndex, nItem, root.itemAtIndex(itemIndex + 2), item) } - - let adjustSeq = function (item) { - if (item.seq === MsgSeq.first) - item.seq = MsgSeq.middle - else if (item.seq === MsgSeq.single) - setSeq(MsgSeq.last, item) + //index 0 insertion = new message + if (itemIndex === 0) { + Qt.callLater(computeSequencing, itemIndex, item, root.itemAtIndex(itemIndex + 1), null) + if (! computeTimestampVisibility(item, itemIndex, nItem, nItemIndex)) { + Qt.callLater(computeChatview, item, itemIndex) + } + } + //top element + if(itemIndex === root.count - 1 && CurrentConversation.allMessagesLoaded) { + item.showTime = true + item.showDay = true } + } - if (pItem && !nItem) { - if (!isSeq(pItem, cItem)) { - computeItem.seq = MsgSeq.single - } else { - computeItem.seq = MsgSeq.last - rAdjustSeq(pItem) - } - } else if (nItem && !pItem) { - if (!isSeq(cItem, nItem)) { - computeItem.seq = MsgSeq.single - } else { - setSeq(MsgSeq.first) - adjustSeq(nItem) - } - } else if (!nItem && !pItem) { - computeItem.seq = MsgSeq.single - } else { - if (isSeq(pItem, nItem)) { - if (isSeq(pItem, cItem)) { - computeItem.seq = MsgSeq.middle - } else { - computeItem.seq = MsgSeq.single - - if (pItem.seq === MsgSeq.first) - pItem.seq = MsgSeq.single - else if (item.seq === MsgSeq.middle) - pItem.seq = MsgSeq.last - - if (nItem.seq === MsgSeq.last) - nItem.seq = MsgSeq.single - else if (nItem.seq === MsgSeq.middle) - nItem.seq = MsgSeq.first + function computeSequencing(index, item, nItem, pItem) { + if (root === undefined || !item) + return + + function isFirst() { + if (!nItem) return true + else{ + if (item.showTime) { + return true } - } else { - if (!isSeq(pItem, cItem)) { - computeItem.seq = MsgSeq.first - adjustSeq(pItem) - } else { - computeItem.seq = MsgSeq.last - rAdjustSeq(nItem) + if (nItem.author !== item.author) { + return true } } + return false } - if (computeItem.seq === MsgSeq.last) { - computeItem.showTime = true + function isLast() { + if (!pItem) return true + else{ + if (pItem.showTime) { + return true + } + if (pItem.author !== item.author) { + return true + } + } + return false } + + if (isLast() && isFirst()) + item.seq = MsgSeq.single + if (!isLast() && isFirst()) + item.seq = MsgSeq.first + if (isLast() && !isFirst()) + item.seq = MsgSeq.last + if (!isLast() && !isFirst()) + item.seq = MsgSeq.middle } // fade-in mechanism @@ -189,6 +179,7 @@ JamiListView { width: parent.width // this offscreen caching is pretty huge // displayMarginEnd may be removed + displayMarginBeginning: 2048 displayMarginEnd: 2048 maximumFlickVelocity: 2048 @@ -216,65 +207,55 @@ JamiListView { id: delegateChooser role: "Type" + DelegateChoice { + id: delegateChoice + roleValue: Interaction.Type.TEXT + TextMessageDelegate { - Component.onCompleted: { - if (index) { - computeTimestampVisibility(this, index) - computeSequencing(this, index) - } else { - Qt.callLater(computeTimestampVisibility, this, index) - Qt.callLater(computeSequencing, this, index) - } + Component.onCompleted: { + computeChatview(this,index) } } } + DelegateChoice { roleValue: Interaction.Type.CALL + GeneratedMessageDelegate { - Component.onCompleted: { - if (index) - computeTimestampVisibility(this, index) - else - Qt.callLater(computeTimestampVisibility, this, index) + Component.onCompleted: { + computeChatview(this,index) } } } + DelegateChoice { roleValue: Interaction.Type.CONTACT + ContactMessageDelegate { - Component.onCompleted: { - if (index) - computeTimestampVisibility(this, index) - else - Qt.callLater(computeTimestampVisibility, this, index) + Component.onCompleted: { + computeChatview(this,index) } } } + DelegateChoice { roleValue: Interaction.Type.INITIAL + GeneratedMessageDelegate { font.bold: true - Component.onCompleted: { - if (index) - computeTimestampVisibility(this, index) - else - Qt.callLater(computeTimestampVisibility, this, index) + Component.onCompleted: { + computeChatview(this,index) } } } DelegateChoice { roleValue: Interaction.Type.DATA_TRANSFER + DataTransferMessageDelegate { - Component.onCompleted: { - if (index) { - computeTimestampVisibility(this, index) - computeSequencing(this, index) - } else { - Qt.callLater(computeTimestampVisibility, this, index) - Qt.callLater(computeSequencing, this, index) - } + Component.onCompleted: { + computeChatview(this,index) } } } @@ -382,8 +363,8 @@ JamiListView { else { var textSize = JamiQmlUtils.getTextBoundingRect(font, text).width var typingContentWidth = typingDots.width + typingDots.anchors.leftMargin - + typeIndicatorNameText.anchors.leftMargin - + typeIndicatorEndingText.contentWidth + + typeIndicatorNameText.anchors.leftMargin + + typeIndicatorEndingText.contentWidth typeIndicatorNameText.Layout.preferredWidth = Math.min(typeIndicatorContainer.width - 5 - typingContentWidth, textSize) diff --git a/src/app/messagesadapter.cpp b/src/app/messagesadapter.cpp index fd37fcc14e785cabd791cadc1b3e9f0914e17c97..b3ae25b315235eb1341dd5f40f271715d536ed9d 100644 --- a/src/app/messagesadapter.cpp +++ b/src/app/messagesadapter.cpp @@ -581,21 +581,41 @@ MessagesAdapter::getFormattedTime(const quint64 timestamp) { const auto now = QDateTime::currentDateTime(); const auto seconds = now.toSecsSinceEpoch() - timestamp; - auto interval = qFloor(seconds / (3600 * 24)); - if (interval > 5) - return QLocale::system().toString(QDateTime::fromSecsSinceEpoch(timestamp), - QLocale::ShortFormat); - if (interval > 1) - return QObject::tr("%1 days ago").arg(interval); - if (interval == 1) - return QObject::tr("one day ago"); - interval = qFloor(seconds / 3600); - if (interval > 1) - return QObject::tr("%1 hours ago").arg(interval); - if (interval == 1) - return QObject::tr("one hour ago"); - interval = qFloor(seconds / 60); - if (interval > 1) - return QObject::tr("%1 minutes ago").arg(interval); + auto interval = qFloor(seconds / 60); + + if (interval > 1) { + auto curLang = settingsManager_->getValue(Settings::Key::LANG); + auto curLocal(QLocale(curLang.toString())); + auto curTime = QDateTime::fromSecsSinceEpoch(timestamp).time(); + QString timeLocale; + if (curLang == "SYSTEM") + timeLocale = QLocale::system().toString(curTime, QLocale::system().ShortFormat); + else + timeLocale = curLocal.toString(curTime, curLocal.ShortFormat); + + return timeLocale; + } return QObject::tr("just now"); } + +QString +MessagesAdapter::getFormattedDay(const quint64 timestamp) +{ + auto now = QDate::currentDate(); + auto before = QDateTime::fromSecsSinceEpoch(timestamp).date(); + if (before == now) + return QObject::tr("Today"); + if (before.daysTo(now) == 1) + return QObject::tr("Yesterday"); + + auto curLang = settingsManager_->getValue(Settings::Key::LANG); + auto curLocal(QLocale(curLang.toString())); + auto curDate = QDateTime::fromSecsSinceEpoch(timestamp).date(); + QString dateLocale; + if (curLang == "SYSTEM") + dateLocale = QLocale::system().toString(curDate, QLocale::system().ShortFormat); + else + dateLocale = curLocal.toString(curDate, curLocal.ShortFormat); + + return dateLocale; +} diff --git a/src/app/messagesadapter.h b/src/app/messagesadapter.h index a01f1d12e84c8dd39954e524cb911d29167807fa..21097934740140bbce9c82933c20b6c995501b10 100644 --- a/src/app/messagesadapter.h +++ b/src/app/messagesadapter.h @@ -79,6 +79,7 @@ protected: Q_INVOKABLE QVariantMap isLocalImage(const QString& mimeName); Q_INVOKABLE QVariantMap getMediaInfo(const QString& msg); Q_INVOKABLE bool isRemoteImage(const QString& msg); + Q_INVOKABLE QString getFormattedDay(const quint64 timestamp); Q_INVOKABLE QString getFormattedTime(const quint64 timestamp); Q_INVOKABLE void parseMessageUrls(const QString& messageId, const QString& msg, diff --git a/src/app/settingsview/components/SettingSpinBox.qml b/src/app/settingsview/components/SettingSpinBox.qml index 1685f41756e5673b0d3784bf06f40dc7e07d8cdf..0c4329853428b97252dca17f3817762ec000f580 100644 --- a/src/app/settingsview/components/SettingSpinBox.qml +++ b/src/app/settingsview/components/SettingSpinBox.qml @@ -62,7 +62,6 @@ RowLayout { Layout.preferredWidth: root.itemWidth Layout.preferredHeight: JamiTheme.preferredFieldHeight Layout.alignment: Qt.AlignCenter - font.pointSize: JamiTheme.buttonFontSize font.kerning: true @@ -91,7 +90,6 @@ RowLayout { MaterialToolTip { id: toolTip - parent: textField visible: textField.hovered && (root.tooltipText.length > 0) delay: Qt.styleHints.mousePressAndHoldInterval diff --git a/src/libclient/messagelistmodel.cpp b/src/libclient/messagelistmodel.cpp index affb368aa97b383e7217ea4ddcb9ad9b6848acbc..f796f6fdc79b0e1ee198f6028e02789318047806 100644 --- a/src/libclient/messagelistmodel.cpp +++ b/src/libclient/messagelistmodel.cpp @@ -36,7 +36,11 @@ using reverseIterator = MessageListModel::reverseIterator; MessageListModel::MessageListModel(QObject* parent) : QAbstractListModel(parent) -{} + , timestampTimer_(new QTimer(this)) +{ + connect(timestampTimer_, &QTimer::timeout, this, &MessageListModel::timestampUpdate); + timestampTimer_->start(1000); +} QPair<iterator, bool> MessageListModel::emplace(const QString& msgId, interaction::Info message, bool beginning) diff --git a/src/libclient/messagelistmodel.h b/src/libclient/messagelistmodel.h index ba7cadac71b60cf9913b79169d9b245413df001e..88028550fbeda72f5ede99c39c01dc7422602099 100644 --- a/src/libclient/messagelistmodel.h +++ b/src/libclient/messagelistmodel.h @@ -22,6 +22,7 @@ #include "api/interaction.h" #include <QAbstractListModel> +#include <QTimer> namespace lrc { namespace api { @@ -125,6 +126,8 @@ public: void emitDataChanged(iterator it, VectorInt roles = {}); void emitDataChanged(const QString& msgId, VectorInt roles = {}); + Q_SIGNAL void timestampUpdate(); + protected: using Role = MessageList::Role; @@ -144,6 +147,8 @@ private: iterator insertMessage(iterator it, item_t& message); void removeMessage(int index, iterator it); void moveMessage(int from, int to); + + QTimer* timestampTimer_ {nullptr}; }; } // namespace api } // namespace lrc