Spectral/qml/component/MessageDelegate.qml

223 lines
6.4 KiB
QML
Raw Normal View History

2018-07-12 01:44:41 +00:00
import QtQuick 2.9
import QtQuick.Controls 2.2
2018-09-04 06:58:41 +00:00
import QtQuick.Layouts 1.3
2018-07-12 01:44:41 +00:00
import QtQuick.Controls.Material 2.2
2018-08-05 16:53:22 +00:00
import Matrique 0.1
import Matrique.Settings 0.1
2018-09-10 01:51:02 +00:00
import "qrc:/js/util.js" as Util
2018-07-09 14:00:27 +00:00
2018-09-04 06:58:41 +00:00
RowLayout {
2018-09-14 04:16:25 +00:00
readonly property bool avatarVisible: !sentByMe && (aboveAuthor !== author || aboveSection !== section || aboveEventType === "state" || aboveEventType === "emote" || aboveEventType === "other")
2018-09-06 13:00:58 +00:00
readonly property bool highlighted: !(sentByMe || eventType === "notice" )
readonly property bool sentByMe: author === currentRoom.localUser
2018-09-04 06:58:41 +00:00
readonly property bool isText: eventType === "notice" || eventType === "message"
2018-09-04 06:58:41 +00:00
signal saveFileAs()
signal openExternally()
2018-07-20 04:14:02 +00:00
z: -5
2018-07-09 14:00:27 +00:00
2018-09-04 13:13:14 +00:00
id: messageRow
2018-09-04 06:58:41 +00:00
Layout.alignment: sentByMe ? Qt.AlignRight : Qt.AlignLeft
spacing: 6
2018-09-10 01:51:02 +00:00
ImageItem {
2018-09-04 06:58:41 +00:00
Layout.preferredWidth: 40
Layout.preferredHeight: 40
Layout.alignment: Qt.AlignTop
2018-07-09 14:00:27 +00:00
2018-09-04 06:58:41 +00:00
round: false
visible: avatarVisible
2018-09-10 01:51:02 +00:00
hint: author.displayName
image: author.avatar
2018-09-04 06:58:41 +00:00
}
Rectangle {
Layout.preferredWidth: 40
Layout.preferredHeight: 40
Layout.alignment: Qt.AlignTop
2018-09-04 06:58:41 +00:00
color: "transparent"
visible: !(sentByMe || avatarVisible)
}
2018-09-04 06:58:41 +00:00
GenericBubble {
Layout.maximumWidth: messageListView.width - (!sentByMe ? 40 + messageRow.spacing : 0)
id: genericBubble
2018-09-06 13:00:58 +00:00
highlighted: messageRow.highlighted
2018-09-06 04:34:15 +00:00
colored: highlighted && (eventType === "notice" || highlight)
2018-09-04 06:58:41 +00:00
contentItem: ColumnLayout {
id: messageColumn
spacing: 0
AutoLabel {
visible: messageRow.avatarVisible
text: author.displayName
Material.foreground: Material.accent
coloredBackground: highlighted
font.bold: true
2018-09-10 01:51:02 +00:00
MouseArea {
anchors.fill: parent
onClicked: inputField.insert(inputField.cursorPosition, author.displayName)
}
2018-09-04 06:58:41 +00:00
}
TextEdit {
2018-09-04 06:58:41 +00:00
Layout.fillWidth: true
text: (highlighted ? "<style>a{color: white;}</style>" : "") + display
2018-09-04 06:58:41 +00:00
visible: isText
color: highlighted ? "white": Material.foreground
font.family: "Noto Sans"
font.pointSize: 10
selectByMouse: true
readOnly: true
wrapMode: Label.Wrap
selectionColor: Material.accent
textFormat: Text.RichText
onLinkActivated: Qt.openUrlExternally(link)
2018-09-04 06:58:41 +00:00
}
Loader {
sourceComponent: {
switch (eventType) {
case "image":
return imageComponent
case "file":
return fileComponent
case "audio":
return audioComponent
}
}
active: eventType === "image" || eventType === "file" || eventType === "audio"
}
2018-09-13 05:05:51 +00:00
Row {
2018-09-04 06:58:41 +00:00
Layout.alignment: Qt.AlignRight
2018-09-13 05:05:51 +00:00
2018-09-16 12:56:47 +00:00
spacing: 4
2018-09-13 05:05:51 +00:00
2018-09-15 13:09:53 +00:00
Repeater {
model: userMarker
ImageItem {
width: parent.height
height: parent.height
hint: modelData.displayName
image: modelData.avatar
}
}
2018-09-13 05:05:51 +00:00
AutoLabel {
id: timeLabel
visible: Math.abs(time - aboveTime) > 600000 || index == 0
text: Qt.formatTime(time, "hh:mm")
coloredBackground: highlighted
Material.foreground: "grey"
font.pointSize: 8
}
2018-09-04 06:58:41 +00:00
}
}
Component {
id: imageComponent
DownloadableContent {
width: messageImage.width
height: messageImage.height
2018-09-04 13:13:14 +00:00
id: downloadable
2018-09-04 06:58:41 +00:00
AutoImage {
z: -4
2018-09-04 13:13:14 +00:00
id: messageImage
2018-09-04 06:58:41 +00:00
sourceSize: 128
source: "image://mxc/" + (content.thumbnail_url ? content.thumbnail_url : content.url)
onClicked: downloadAndOpen()
}
Component.onCompleted: {
messageRow.saveFileAs.connect(saveFileAs)
messageRow.openExternally.connect(downloadAndOpen)
}
}
}
Component {
id: fileComponent
AutoLabel {
Layout.fillWidth: true
id: downloadDelegate
text: "<b>File: </b>" + content.body
coloredBackground: highlighted
background: DownloadableContent {
id: downloadable
Component.onCompleted: {
messageRow.saveFileAs.connect(saveFileAs)
messageRow.openExternally.connect(downloadAndOpen)
}
}
}
}
Component {
id: audioComponent
AutoLabel {
id: downloadDelegate
text: content.info.duration / 1000 + '"'
coloredBackground: highlighted
MouseArea {
anchors.fill: parent
propagateComposedEvents: true
onClicked: {
if (downloadable.downloaded)
matriqueController.playAudio(progressInfo.localPath)
else
{
playOnFinished = true
currentRoom.downloadFile(eventId, StandardPaths.writableLocation(StandardPaths.CacheLocation) + "/" + eventId.replace(":", "_") + ".tmp")
}
}
}
background: DownloadableContent {
id: downloadable
onDownloadedChanged: downloaded && playOnFinished ? matriqueController.playAudio(progressInfo.localPath) : {}
Component.onCompleted: {
messageRow.saveFileAs.connect(saveFileAs)
messageRow.openExternally.connect(downloadAndOpen)
}
}
}
}
2018-07-09 14:00:27 +00:00
}
}