From eb55c3193a452d6469cebfc04c9df30e463756ab Mon Sep 17 00:00:00 2001 From: Nicolas Vengeon <nicolas.vengeon@savoirfairelinux.com> Date: Mon, 3 Oct 2022 15:38:44 -0400 Subject: [PATCH] feature: Display emojis stand alone -Emojis are shown without bubbles when sent alone -Changes on message reply design ( animation now include files and emojis) GitLab: #690 Signed-off-by: Nicolas Vengeon <nicolas.vengeon@savoirfairelinux.com> Change-Id: I81d128367a9c393c76493e02ce88daf4f6a11bf4 --- .../DataTransferMessageDelegate.qml | 3 ++ src/app/commoncomponents/SBSMessageBase.qml | 48 ++++++++++++++++--- .../commoncomponents/TextMessageDelegate.qml | 36 +++++++++++--- src/app/constant/JamiTheme.qml | 1 + .../mainview/components/MessageListView.qml | 3 -- src/libclient/messagelistmodel.cpp | 25 ++++++++++ src/libclient/messagelistmodel.h | 4 +- 7 files changed, 103 insertions(+), 17 deletions(-) diff --git a/src/app/commoncomponents/DataTransferMessageDelegate.qml b/src/app/commoncomponents/DataTransferMessageDelegate.qml index d4dd426fa..6c0926274 100644 --- a/src/app/commoncomponents/DataTransferMessageDelegate.qml +++ b/src/app/commoncomponents/DataTransferMessageDelegate.qml @@ -326,8 +326,10 @@ Loader { Component { id: imageComp + Image { id: img + anchors.right: isOutgoing ? parent.right : undefined property real minSize: 192 property real maxSize: 256 @@ -346,6 +348,7 @@ Loader { innerContent.width - senderMargin)) width: adjustedWidth height: Math.ceil(adjustedWidth / aspectRatio) + Rectangle { color: JamiTheme.previewImageBackgroundColor z: -1 diff --git a/src/app/commoncomponents/SBSMessageBase.qml b/src/app/commoncomponents/SBSMessageBase.qml index a2d1bc3e1..343b4da43 100644 --- a/src/app/commoncomponents/SBSMessageBase.qml +++ b/src/app/commoncomponents/SBSMessageBase.qml @@ -32,7 +32,6 @@ Control { property alias avatarBlockWidth: avatarBlock.width property alias innerContent: innerContent property alias bubble: bubble - property alias selectAnimation: selectAnimation property real extraHeight: 0 // these MUST be set but we won't use the 'required' keyword yet @@ -145,6 +144,8 @@ Control { MessageBubble { id: bubble + + visible: !IsEmojiOnly z:-1 out: isOutgoing type: seq @@ -166,15 +167,48 @@ Control { height: innerContent.childrenRect.height + (visible ? root.extraHeight : 0) } + Rectangle { + id: bg + + color: bubble.getBaseColor() + anchors.fill: parent + visible: false + } + SequentialAnimation { id: selectAnimation - ColorAnimation { - target: bubble; property: "color" - to: Qt.darker(bubble.getBaseColor(), 1.5); duration: 240 + + PropertyAnimation { + properties: "opacity" + target: opacityMask + from: 0 + to: 1 + duration: JamiTheme.longFadeDuration } - ColorAnimation { - target: bubble; property: "color" - to: bubble.getBaseColor(); duration: 240 + PropertyAnimation { + properties: "opacity" + target: opacityMask + from: 1 + to: 0 + duration: JamiTheme.longFadeDuration + } + } + + OpacityMask { + id: opacityMask + + opacity: 0 + anchors.fill: bubble + source: bubble + maskSource: bg + } + + Connections { + target: CurrentConversation + function onScrollTo(id) { + if (id !== root.id) + return + selectAnimation.start() } } } diff --git a/src/app/commoncomponents/TextMessageDelegate.qml b/src/app/commoncomponents/TextMessageDelegate.qml index 017769976..0cbe4b0d5 100644 --- a/src/app/commoncomponents/TextMessageDelegate.qml +++ b/src/app/commoncomponents/TextMessageDelegate.qml @@ -21,6 +21,7 @@ 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 @@ -30,7 +31,9 @@ SBSMessageBase { id : root property bool isRemoteImage + property bool isEmojiOnly: IsEmojiOnly property real maxMsgWidth: root.width - senderMargin - 2 * hPadding - avatarBlockWidth + isOutgoing: Author === "" author: Author readers: Readers @@ -41,10 +44,15 @@ SBSMessageBase { innerContent.children: [ TextEdit { - padding: JamiTheme.preferredMarginSize + id: textEditId + + padding: isEmojiOnly ? 0 : JamiTheme.preferredMarginSize anchors.right: isOutgoing ? parent.right : undefined + text: Body - horizontalAlignment: Text.AlignLeft + + horizontalAlignment: isOutgoing ? Text.AlignLeft : Text.AlignRight + width: { if (extraContent.active) Math.max(extraContent.width, @@ -57,16 +65,31 @@ SBSMessageBase { height: implicitHeight wrapMode: Label.WrapAtWordBoundaryOrAnywhere selectByMouse: true - font.pixelSize: JamiTheme.chatviewFontSize + font.pixelSize: isEmojiOnly? JamiTheme.chatviewEmojiSize : JamiTheme.chatviewFontSize + font.hintingPreference: Font.PreferNoHinting renderType: Text.NativeRendering textFormat: Text.MarkdownText onLinkHovered: root.hoveredLink = hoveredLink onLinkActivated: Qt.openUrlExternally(hoveredLink) readOnly: true - color: UtilsAdapter.luma(bubble.color) ? - JamiTheme.chatviewTextColorLight : - JamiTheme.chatviewTextColorDark + color: getBaseColor() + + function getBaseColor() { + var baseColor + if (isEmojiOnly) { + if (JamiTheme.darkTheme) + baseColor = JamiTheme.chatviewTextColorLight + else + baseColor = JamiTheme.chatviewTextColorDark + } else { + if (UtilsAdapter.luma(bubble.color)) + baseColor = JamiTheme.chatviewTextColorLight + else + baseColor = JamiTheme.chatviewTextColorDark + } + return baseColor + } TapHandler { enabled: parent.selectedText.length > 0 @@ -104,6 +127,7 @@ SBSMessageBase { } AnimatedImage { id: img + cache: false source: isRemoteImage ? LinkPreviewInfo.url : diff --git a/src/app/constant/JamiTheme.qml b/src/app/constant/JamiTheme.qml index 0bccb0fef..5267a12e9 100644 --- a/src/app/constant/JamiTheme.qml +++ b/src/app/constant/JamiTheme.qml @@ -188,6 +188,7 @@ Item { property color chatviewTextColorLight: "#f0f0f0" property color chatviewTextColorDark: "#353637" property real chatviewFontSize: calcSize(15) + property real chatviewEmojiSize: calcSize(60) property color timestampColor: darkTheme ? "#bbb" : "#777" property color messageOutTxtColor: "#000000" property color messageInBgColor: darkTheme ? "#28b1ed" : "#e5e5e5" diff --git a/src/app/mainview/components/MessageListView.qml b/src/app/mainview/components/MessageListView.qml index 0c4357035..ffc2c0125 100644 --- a/src/app/mainview/components/MessageListView.qml +++ b/src/app/mainview/components/MessageListView.qml @@ -166,9 +166,6 @@ JamiListView { } } positionViewAtIndex(idx, ListView.Center) - var delegate = root.itemAtIndex(idx) - if (delegate.selectAnimation) - delegate.selectAnimation.start() } } diff --git a/src/libclient/messagelistmodel.cpp b/src/libclient/messagelistmodel.cpp index f796f6fdc..8e3f0b1cb 100644 --- a/src/libclient/messagelistmodel.cpp +++ b/src/libclient/messagelistmodel.cpp @@ -357,6 +357,29 @@ MessageListModel::roleNames() const return roles; } +bool +MessageListModel::isOnlyEmoji(const QString& text) const +{ + auto codepointList = text.toUcs4(); + for (QList<uint>::iterator it = codepointList.begin(); it != codepointList.end(); it++) { + auto cur = false; + if (*it == 20 or *it == 0x200D) { + cur = true; + } else if (0x1f000 <= *it && 0x1ffff >= *it) { + cur = true; + } else if (0x2600 <= *it && 0x27BF >= *it) { + cur = true; + } else if (0xFE00 <= *it && 0xFE0f >= *it) { + cur = true; + } else if (0xE0000 <= *it && 0xE007F >= *it) { + cur = true; + } + if (!cur) + return false; + } + return true; +} + QVariant MessageListModel::dataForItem(item_t item, int, int role) const { @@ -401,6 +424,8 @@ MessageListModel::dataForItem(item_t item, int, int role) const return QVariant(item.second.commit["displayName"]); case Role::Readers: return QVariant(messageToReaders_[item.first]); + case Role::IsEmojiOnly: + return QVariant(isOnlyEmoji(item.second.body)); default: return {}; } diff --git a/src/libclient/messagelistmodel.h b/src/libclient/messagelistmodel.h index 88028550f..2613276b7 100644 --- a/src/libclient/messagelistmodel.h +++ b/src/libclient/messagelistmodel.h @@ -50,7 +50,8 @@ struct Info; X(ReplyToAuthor) \ X(TotalSize) \ X(TransferName) \ - X(Readers) + X(Readers) \ + X(IsEmojiOnly) namespace MessageList { Q_NAMESPACE @@ -125,6 +126,7 @@ public: // these emission wrappers void emitDataChanged(iterator it, VectorInt roles = {}); void emitDataChanged(const QString& msgId, VectorInt roles = {}); + bool isOnlyEmoji(const QString& text) const; Q_SIGNAL void timestampUpdate(); -- GitLab