Warning, /network/neochat/src/qml/Bubble.qml is written in an unsupported language. File is not indexed.

0001 // SPDX-FileCopyrightText: 2023 James Graham <james.h.graham@protonmail.com>
0002 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0003 
0004 import QtQuick
0005 import QtQuick.Controls as QQC2
0006 import QtQuick.Layouts
0007 
0008 import org.kde.kirigami as Kirigami
0009 
0010 import org.kde.neochat
0011 
0012 /**
0013  * @brief A chat bubble for displaying the content of message events.
0014  *
0015  * The content of the bubble is set via the content property which is then managed
0016  * by the bubble to apply the correct sizing (including limiting the width if a
0017  * maxContentWidth is set).
0018  *
0019  * The bubble also supports a header with the author and message timestamp and a
0020  * reply.
0021  */
0022 QQC2.Control {
0023     id: root
0024 
0025     /**
0026      * @brief The message author.
0027      *
0028      * This should consist of the following:
0029      *  - id - The matrix ID of the author.
0030      *  - isLocalUser - Whether the author is the local user.
0031      *  - avatarSource - The mxc URL for the author's avatar in the current room.
0032      *  - avatarMediaId - The media ID of the author's avatar.
0033      *  - avatarUrl - The mxc URL for the author's avatar.
0034      *  - displayName - The display name of the author.
0035      *  - display - The name of the author.
0036      *  - color - The color for the author.
0037      *  - object - The Quotient::User object for the author.
0038      *
0039      * @sa Quotient::User
0040      */
0041     property var author
0042 
0043     /**
0044      * @brief Whether the author should be shown.
0045      */
0046     required property bool showAuthor
0047 
0048     /**
0049      * @brief The timestamp of the message.
0050      */
0051     property var time
0052 
0053     /**
0054      * @brief The timestamp of the message as a string.
0055      */
0056     property string timeString
0057 
0058     /**
0059      * @brief Whether the message should be highlighted.
0060      */
0061     property bool showHighlight: false
0062 
0063     /**
0064      * @brief The main delegate content item to show in the bubble.
0065      */
0066     property Item content
0067 
0068     /**
0069      * @brief Whether this message is replying to another.
0070      */
0071     property bool isReply: false
0072 
0073     /**
0074      * @brief The matrix ID of the reply event.
0075      */
0076     required property var replyId
0077 
0078     /**
0079      * @brief The reply author.
0080      *
0081      * This should consist of the following:
0082      *  - id - The matrix ID of the reply author.
0083      *  - isLocalUser - Whether the reply author is the local user.
0084      *  - avatarSource - The mxc URL for the reply author's avatar in the current room.
0085      *  - avatarMediaId - The media ID of the reply author's avatar.
0086      *  - avatarUrl - The mxc URL for the reply author's avatar.
0087      *  - displayName - The display name of the reply author.
0088      *  - display - The name of the reply author.
0089      *  - color - The color for the reply author.
0090      *  - object - The Quotient::User object for the reply author.
0091      *
0092      * @sa Quotient::User
0093      */
0094     required property var replyAuthor
0095 
0096     /**
0097      * @brief The delegate type of the message replied to.
0098      */
0099     required property int replyDelegateType
0100 
0101     /**
0102      * @brief The display text of the message replied to.
0103      */
0104     required property string replyDisplay
0105 
0106     /**
0107      * @brief The media info for the reply event.
0108      *
0109      * This could be an image, audio, video or file.
0110      *
0111      * This should consist of the following:
0112      *  - source - The mxc URL for the media.
0113      *  - mimeType - The MIME type of the media.
0114      *  - mimeIcon - The MIME icon name.
0115      *  - size - The file size in bytes.
0116      *  - duration - The length in seconds of the audio media (audio/video only).
0117      *  - width - The width in pixels of the audio media (image/video only).
0118      *  - height - The height in pixels of the audio media (image/video only).
0119      *  - tempInfo - mediaInfo (with the same properties as this except no tempInfo) for a temporary image while the file downloads (image/video only).
0120      */
0121     required property var replyMediaInfo
0122 
0123     /**
0124      * @brief Whether the bubble background should be shown.
0125      */
0126     property alias showBackground: bubbleBackground.visible
0127 
0128     /**
0129      * @brief The maximum width that the bubble's content can be.
0130      */
0131     property real maxContentWidth: -1
0132 
0133     /**
0134      * @brief The reply has been clicked.
0135      */
0136     signal replyClicked(string eventID)
0137 
0138     contentItem: ColumnLayout {
0139         RowLayout {
0140             Layout.maximumWidth: root.maxContentWidth
0141             visible: root.showAuthor
0142             QQC2.AbstractButton {
0143                 Layout.fillWidth: true
0144                 contentItem: QQC2.Label {
0145                     text: root.author.displayName
0146                     color: root.author.color
0147                     textFormat: Text.PlainText
0148                     font.weight: Font.Bold
0149                     elide: Text.ElideRight
0150                 }
0151                 Accessible.name: contentItem.text
0152                 onClicked: RoomManager.resolveResource(root.author.id, "mention")
0153             }
0154             QQC2.Label {
0155                 text: root.timeString
0156                 horizontalAlignment: Text.AlignRight
0157                 color: Kirigami.Theme.disabledTextColor
0158                 QQC2.ToolTip.visible: timeHoverHandler.hovered
0159                 QQC2.ToolTip.text: root.time.toLocaleString(Qt.locale(), Locale.LongFormat)
0160                 QQC2.ToolTip.delay: Kirigami.Units.toolTipDelay
0161 
0162                 HoverHandler {
0163                     id: timeHoverHandler
0164                 }
0165             }
0166         }
0167         Loader {
0168             id: replyLoader
0169             Layout.fillWidth: true
0170             Layout.maximumWidth: root.maxContentWidth
0171 
0172             active: root.isReply && root.replyDelegateType !== DelegateType.Other
0173             visible: active
0174 
0175             sourceComponent: ReplyComponent {
0176                 author: root.replyAuthor
0177                 type: root.replyDelegateType
0178                 display: root.replyDisplay
0179                 mediaInfo: root.replyMediaInfo
0180                 contentMaxWidth: root.maxContentWidth
0181             }
0182 
0183             Connections {
0184                 target: replyLoader.item
0185                 function onReplyClicked() {
0186                     replyClicked(root.replyId);
0187                 }
0188             }
0189         }
0190         Item {
0191             id: contentParent
0192             Layout.fillWidth: true
0193             Layout.maximumWidth: root.maxContentWidth
0194             implicitWidth: root.content ? root.content.implicitWidth : 0
0195             implicitHeight: root.content ? root.content.implicitHeight : 0
0196         }
0197     }
0198 
0199     background: Kirigami.ShadowedRectangle {
0200         id: bubbleBackground
0201         visible: root.showBackground
0202         Kirigami.Theme.colorSet: Kirigami.Theme.View
0203         Kirigami.Theme.inherit: false
0204         color: if (root.author.isLocalUser) {
0205             return Kirigami.ColorUtils.tintWithAlpha(Kirigami.Theme.backgroundColor, Kirigami.Theme.highlightColor, 0.15);
0206         } else if (root.showHighlight) {
0207             return Kirigami.Theme.positiveBackgroundColor;
0208         } else {
0209             return Kirigami.Theme.backgroundColor;
0210         }
0211         radius: Kirigami.Units.smallSpacing
0212         shadow {
0213             size: Kirigami.Units.smallSpacing
0214             color: root.showHighlight ? Qt.rgba(0.0, 0.0, 0.0, 0.10) : Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.10)
0215         }
0216 
0217         Behavior on color {
0218             ColorAnimation {
0219                 duration: Kirigami.Units.shortDuration
0220             }
0221         }
0222     }
0223 
0224     onContentChanged: {
0225         if (!root.content) {
0226             return;
0227         }
0228         root.content.parent = contentParent;
0229         root.content.anchors.fill = contentParent;
0230     }
0231 }