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 }