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

0001 // SPDX-FileCopyrightText: 2019 Black Hat <bhat@encom.eu.org>
0002 // SPDX-FileCopyrightText: 2020 Carl Schwan <carl@carlschwan.eu>
0003 // SPDX-License-Identifier: GPL-3.0-only
0004 
0005 import QtQuick
0006 import QtQuick.Controls as QQC2
0007 import QtQuick.Layouts
0008 
0009 import org.kde.coreaddons
0010 import org.kde.kirigami as Kirigami
0011 import org.kde.kirigamiaddons.labs.components as KirigamiComponents
0012 
0013 import org.kde.neochat
0014 
0015 /**
0016  * @brief A component to show a message that has been replied to.
0017  *
0018  * Similar to the main timeline delegate a reply delegate is chosen based on the type
0019  * of message being replied to. The main difference is that not all messages can be
0020  * show in their original form and are instead visualised with a MIME type delegate
0021  * e.g. Videos.
0022  */
0023 RowLayout {
0024     id: root
0025 
0026     /**
0027      * @brief The reply author.
0028      *
0029      * This should consist of the following:
0030      *  - id - The matrix ID of the reply author.
0031      *  - isLocalUser - Whether the reply author is the local user.
0032      *  - avatarSource - The mxc URL for the reply author's avatar in the current room.
0033      *  - avatarMediaId - The media ID of the reply author's avatar.
0034      *  - avatarUrl - The mxc URL for the reply author's avatar.
0035      *  - displayName - The display name of the reply author.
0036      *  - display - The name of the reply author.
0037      *  - color - The color for the reply author.
0038      *  - object - The Quotient::User object for the reply author.
0039      *
0040      * @sa Quotient::User
0041      */
0042     required property var author
0043 
0044     /**
0045      * @brief The delegate type of the reply message.
0046      */
0047     required property int type
0048 
0049     /**
0050      * @brief The display text of the message.
0051      */
0052     required property string display
0053 
0054     /**
0055      * @brief The media info for the reply event.
0056      *
0057      * This could be an image, audio, video or file.
0058      *
0059      * This should consist of the following:
0060      *  - source - The mxc URL for the media.
0061      *  - mimeType - The MIME type of the media.
0062      *  - mimeIcon - The MIME icon name.
0063      *  - size - The file size in bytes.
0064      *  - duration - The length in seconds of the audio media (audio/video only).
0065      *  - width - The width in pixels of the audio media (image/video only).
0066      *  - height - The height in pixels of the audio media (image/video only).
0067      *  - tempInfo - mediaInfo (with the same properties as this except no tempInfo) for a temporary image while the file downloads (image/video only).
0068      */
0069     required property var mediaInfo
0070 
0071     property real contentMaxWidth
0072 
0073     /**
0074      * @brief The reply has been clicked.
0075      */
0076     signal replyClicked
0077 
0078     spacing: Kirigami.Units.largeSpacing
0079 
0080     Rectangle {
0081         id: verticalBorder
0082         Layout.fillHeight: true
0083 
0084         implicitWidth: Kirigami.Units.smallSpacing
0085         color: root.author.color
0086     }
0087     ColumnLayout {
0088         spacing: Kirigami.Units.smallSpacing
0089 
0090         RowLayout {
0091             spacing: Kirigami.Units.largeSpacing
0092 
0093             KirigamiComponents.Avatar {
0094                 id: replyAvatar
0095 
0096                 implicitWidth: Kirigami.Units.iconSizes.small
0097                 implicitHeight: Kirigami.Units.iconSizes.small
0098 
0099                 source: root.author.avatarSource
0100                 name: root.author.displayName
0101                 color: root.author.color
0102             }
0103             QQC2.Label {
0104                 id: replyName
0105                 Layout.fillWidth: true
0106 
0107                 color: root.author.color
0108                 text: root.author.displayName
0109                 elide: Text.ElideRight
0110             }
0111         }
0112         Loader {
0113             id: loader
0114 
0115             Layout.fillWidth: true
0116             Layout.maximumHeight: loader.item && (root.type == DelegateType.Image || root.type == DelegateType.Sticker) ? loader.item.height : loader.item.implicitHeight
0117             Layout.columnSpan: 2
0118 
0119             sourceComponent: {
0120                 switch (root.type) {
0121                 case DelegateType.Image:
0122                 case DelegateType.Sticker:
0123                     return imageComponent;
0124                 case DelegateType.Message:
0125                 case DelegateType.Notice:
0126                     return textComponent;
0127                 case DelegateType.File:
0128                 case DelegateType.Video:
0129                 case DelegateType.Audio:
0130                     return mimeComponent;
0131                 case DelegateType.Encrypted:
0132                     return encryptedComponent;
0133                 default:
0134                     return textComponent;
0135                 }
0136             }
0137         }
0138     }
0139     HoverHandler {
0140         cursorShape: Qt.PointingHandCursor
0141     }
0142     TapHandler {
0143         acceptedButtons: Qt.LeftButton
0144         onTapped: root.replyClicked()
0145     }
0146 
0147     Component {
0148         id: textComponent
0149         RichLabel {
0150             textMessage: root.display
0151 
0152             HoverHandler {
0153                 enabled: !hoveredLink
0154                 cursorShape: Qt.PointingHandCursor
0155             }
0156             TapHandler {
0157                 enabled: !hoveredLink
0158                 acceptedButtons: Qt.LeftButton
0159                 onTapped: root.replyClicked()
0160             }
0161         }
0162     }
0163     Component {
0164         id: imageComponent
0165         Image {
0166             id: image
0167             width: mediaSizeHelper.currentSize.width
0168             height: mediaSizeHelper.currentSize.height
0169             fillMode: Image.PreserveAspectFit
0170             source: root?.mediaInfo.source ?? ""
0171 
0172             MediaSizeHelper {
0173                 id: mediaSizeHelper
0174                 contentMaxWidth: root.contentMaxWidth - verticalBorder.width - root.spacing
0175                 mediaWidth: root?.mediaInfo.width ?? -1
0176                 mediaHeight: root?.mediaInfo.height ?? -1
0177             }
0178         }
0179     }
0180     Component {
0181         id: mimeComponent
0182         MimeComponent {
0183             mimeIconSource: root.mediaInfo.mimeIcon
0184             label: root.display
0185             subLabel: root.type === DelegateType.File ? Format.formatByteSize(root.mediaInfo.size) : Format.formatDuration(root.mediaInfo.duration)
0186         }
0187     }
0188     Component {
0189         id: encryptedComponent
0190         RichLabel {
0191             textMessage: i18n("This message is encrypted and the sender has not shared the key with this device.")
0192             textFormat: Text.RichText
0193         }
0194     }
0195 }