diff --git a/imports/Spectral/Component/Timeline/ImageDelegate.qml b/imports/Spectral/Component/Timeline/ImageDelegate.qml
new file mode 100644
index 0000000..465ff30
--- /dev/null
+++ b/imports/Spectral/Component/Timeline/ImageDelegate.qml
@@ -0,0 +1,103 @@
+import QtQuick 2.9
+import QtQuick.Controls 2.2
+import QtQuick.Layouts 1.3
+import QtQuick.Controls.Material 2.2
+import QtGraphicalEffects 1.0
+
+import Spectral 0.1
+import Spectral.Setting 0.1
+
+import Spectral.Component 2.0
+import Spectral.Font 0.1
+
+ColumnLayout {
+ readonly property int alignment: sentByMe ? Qt.AlignRight : Qt.AlignLeft
+
+ readonly property bool avatarVisible: !sentByMe && (aboveAuthor !== author || aboveSection !== section || aboveEventType === "state" || aboveEventType === "emote" || aboveEventType === "other")
+ readonly property bool sentByMe: author === currentRoom.localUser
+
+ signal saveFileAs()
+ signal openExternally()
+
+ id: root
+
+ spacing: 0
+
+ Label {
+ Layout.leftMargin: 48
+
+ text: author.displayName
+
+ visible: avatarVisible
+
+ font.pixelSize: 13
+ verticalAlignment: Text.AlignVCenter
+ }
+
+ RowLayout {
+ Layout.alignment: sentByMe ? Qt.AlignRight : Qt.AlignLeft
+
+ z: -5
+
+ id: messageRow
+
+ spacing: 4
+
+ ImageItem {
+ Layout.preferredWidth: 32
+ Layout.preferredHeight: 32
+ Layout.alignment: Qt.AlignTop
+
+ visible: avatarVisible
+ hint: author.displayName
+ source: author.paintable
+ }
+
+ Label {
+ Layout.preferredWidth: 32
+ Layout.preferredHeight: 32
+ Layout.alignment: Qt.AlignTop
+
+ visible: !(sentByMe || avatarVisible)
+
+ text: Qt.formatDateTime(time, "hh:mm")
+ color: "#5B7480"
+
+ font.pixelSize: 10
+ horizontalAlignment: Label.AlignHCenter
+ verticalAlignment: Label.AlignVCenter
+ }
+
+ Image {
+ Layout.maximumWidth: messageListView.width - (!sentByMe ? 32 + messageRow.spacing : 0) - 48
+
+ id: img
+
+ source: "image://mxc/" + (content.thumbnail_url ? content.thumbnail_url : content.url)
+ sourceSize.width: Math.min(256, messageListView.width)
+ sourceSize.height: 256
+
+ layer.enabled: true
+ layer.effect: OpacityMask {
+ maskSource: Rectangle {
+ width: img.width
+ height: img.height
+ radius: 24
+ }
+ }
+
+ AutoMouseArea {
+ anchors.fill: parent
+
+ id: messageMouseArea
+
+ onSecondaryClicked: {
+ messageContextMenu.root = root
+ messageContextMenu.model = model
+ messageContextMenu.selectedText = ""
+ messageContextMenu.popup()
+ }
+ }
+ }
+ }
+}
diff --git a/imports/Spectral/Component/Timeline/MessageDelegate.qml b/imports/Spectral/Component/Timeline/MessageDelegate.qml
index d45cec8..e73c589 100644
--- a/imports/Spectral/Component/Timeline/MessageDelegate.qml
+++ b/imports/Spectral/Component/Timeline/MessageDelegate.qml
@@ -10,16 +10,14 @@ import Spectral.Component 2.0
import Spectral.Font 0.1
ColumnLayout {
+ readonly property int alignment: sentByMe ? Qt.AlignRight : Qt.AlignLeft
+
readonly property bool avatarVisible: !sentByMe && (aboveAuthor !== author || aboveSection !== section || aboveEventType === "state" || aboveEventType === "emote" || aboveEventType === "other")
- readonly property bool highlighted: !(sentByMe || eventType === "notice" )
readonly property bool sentByMe: author === currentRoom.localUser
- readonly property bool isText: eventType === "notice" || eventType === "message"
signal saveFileAs()
signal openExternally()
- Layout.alignment: sentByMe ? Qt.AlignRight : Qt.AlignLeft
-
id: root
spacing: 0
@@ -95,139 +93,30 @@ ColumnLayout {
}
}
- contentItem: ColumnLayout {
- id: messageColumn
+ contentItem: TextEdit {
+ Layout.fillWidth: true
- spacing: 0
+ id: contentLabel
- TextEdit {
- Layout.fillWidth: true
+ text: "" + display
- id: contentLabel
+ color: "white"
- text: "" + display
+ font.family: CommonFont.font.family
+ font.pixelSize: 14
+ selectByMouse: true
+ readOnly: true
+ wrapMode: Label.Wrap
+ selectedTextColor: "white"
+ selectionColor: Material.accent
+ textFormat: Text.RichText
- visible: isText
- color: "white"
+ onLinkActivated: Qt.openUrlExternally(link)
- font.family: CommonFont.font.family
- font.pixelSize: 14
- selectByMouse: true
- readOnly: true
- wrapMode: Label.Wrap
- selectedTextColor: highlighted ? Material.accent : "white"
- selectionColor: highlighted ? "white" : Material.accent
- textFormat: Text.RichText
-
- onLinkActivated: Qt.openUrlExternally(link)
-
- MouseArea {
- anchors.fill: parent
- acceptedButtons: Qt.NoButton
- cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
- }
- }
-
- Loader {
- sourceComponent: {
- switch (eventType) {
- case "image":
- return imageComponent
- case "file":
- return fileComponent
- case "audio":
- return audioComponent
- }
- }
-
- active: eventType === "image" || eventType === "file" || eventType === "audio"
- }
- }
-
- Component {
- id: imageComponent
-
- DownloadableContent {
- width: messageImage.width
- height: messageImage.height
-
- id: downloadable
-
- TimelineImage {
- z: -4
-
- id: messageImage
-
- sourceSize: 128
- source: "image://mxc/" + (content.thumbnail_url ? content.thumbnail_url : content.url)
-
- onClicked: downloadAndOpen()
- }
-
- Component.onCompleted: {
- root.saveFileAs.connect(saveFileAs)
- root.openExternally.connect(downloadAndOpen)
- }
- }
- }
-
- Component {
- id: fileComponent
-
- TimelineLabel {
- Layout.fillWidth: true
-
- id: downloadDelegate
-
- text: "File: " + content.body
- coloredBackground: highlighted
-
- background: DownloadableContent {
- id: downloadable
-
- Component.onCompleted: {
- root.saveFileAs.connect(saveFileAs)
- root.openExternally.connect(downloadAndOpen)
- }
- }
- }
- }
-
- Component {
- id: audioComponent
-
- TimelineLabel {
- id: downloadDelegate
-
- text: content.info.duration / 1000 + '"'
- coloredBackground: highlighted
-
- MouseArea {
- anchors.fill: parent
-
- propagateComposedEvents: true
-
- onClicked: {
- if (downloadable.downloaded)
- spectralController.playAudio(progressInfo.localPath)
- else
- {
- playOnFinished = true
- currentRoom.downloadFile(eventId, StandardPaths.writableLocation(StandardPaths.CacheLocation) + "/" + eventId.replace(":", "_") + ".tmp")
- }
- }
- }
-
- background: DownloadableContent {
- id: downloadable
-
- onDownloadedChanged: downloaded && playOnFinished ? spectralController.playAudio(progressInfo.localPath) : {}
-
- Component.onCompleted: {
- root.saveFileAs.connect(saveFileAs)
- root.openExternally.connect(downloadAndOpen)
- }
- }
+ MouseArea {
+ anchors.fill: parent
+ acceptedButtons: Qt.NoButton
+ cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
}
diff --git a/imports/Spectral/Component/Timeline/StateDelegate.qml b/imports/Spectral/Component/Timeline/StateDelegate.qml
index 91bc2e7..2c3a262 100644
--- a/imports/Spectral/Component/Timeline/StateDelegate.qml
+++ b/imports/Spectral/Component/Timeline/StateDelegate.qml
@@ -6,6 +6,8 @@ import QtQuick.Controls.Material 2.2
import Spectral.Setting 0.1
Label {
+ readonly property int alignment: Qt.AlignHCenter
+
text: "" + author.displayName + " " + display
color: Material.accent
diff --git a/imports/Spectral/Panel/RoomPanel.qml b/imports/Spectral/Panel/RoomPanel.qml
index 73326ca..643c235 100644
--- a/imports/Spectral/Panel/RoomPanel.qml
+++ b/imports/Spectral/Panel/RoomPanel.qml
@@ -103,7 +103,7 @@ Item {
var lastScrollPosition = sortedMessageEventModel.mapFromSource(currentRoom.savedTopVisibleIndex())
messageListView.currentIndex = lastScrollPosition
if (messageListView.contentY < messageListView.originY + 10 || currentRoom.timelineSize < 20)
- currentRoom.getPreviousContent(100)
+ currentRoom.getPreviousContent(50)
}
}
}
@@ -112,7 +112,7 @@ Item {
onContentYChanged: {
if(currentRoom && contentY - 5000 < originY)
- currentRoom.getPreviousContent(50);
+ currentRoom.getPreviousContent(20);
}
onMovementEnded: currentRoom.saveViewport(sortedMessageEventModel.mapToSource(indexAt(contentX, contentY)), sortedMessageEventModel.mapToSource(largestVisibleIndex))
@@ -138,29 +138,27 @@ Item {
visible: section !== aboveSection || Math.abs(time - aboveTime) > 600000
}
- MessageDelegate {
- visible: eventType === "notice" || eventType === "message"
- || eventType === "image" || eventType === "video"
- || eventType === "audio" || eventType === "file"
- }
-
- StateDelegate {
- Layout.maximumWidth: parent.width
- Layout.alignment: Qt.AlignHCenter
-
- visible: eventType === "emote" || eventType === "state"
- }
-
- Label {
- Layout.alignment: Qt.AlignHCenter
-
- visible: eventType === "other"
-
- text: display
- color: "grey"
- font.italic: true
+ Loader {
+ Layout.maximumWidth: delegateColumn.width
+ Layout.alignment: item ? item.alignment : 0
+
+ source: {
+ switch (eventType) {
+ case "message":
+ case "notice":
+ return "qrc:/imports/Spectral/Component/Timeline/MessageDelegate.qml"
+ case "emote":
+ case "state":
+ return "qrc:/imports/Spectral/Component/Timeline/StateDelegate.qml"
+ case "image":
+ return "qrc:/imports/Spectral/Component/Timeline/ImageDelegate.qml"
+ default:
+ return ""
+ }
+ }
}
+ // Read marker
RowLayout {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
diff --git a/res.qrc b/res.qrc
index 7b3a6aa..a1be77d 100644
--- a/res.qrc
+++ b/res.qrc
@@ -46,5 +46,6 @@
imports/Spectral/Effect/RippleEffect.qml
imports/Spectral/Effect/CircleMask.qml
assets/img/roompanel-dark.svg
+ imports/Spectral/Component/Timeline/ImageDelegate.qml