summary refs log tree commit diff
path: root/resources/qml
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2020-01-11 14:07:51 +0100
committerNicolas Werner <nicolas.werner@hotmail.de>2020-01-11 14:07:51 +0100
commit2b3dc3d8b9d1108c3f6ad226ad65060bd3999033 (patch)
tree42419bdee5b28c98eaafb44724c64f351a275199 /resources/qml
parenttry to make appveyor happy (diff)
downloadnheko-2b3dc3d8b9d1108c3f6ad226ad65060bd3999033.tar.xz
Implement fancy reply rendering
This currently assumes the event, that is replied to, is already
fetched. If it isn't, it will render an empty reply. In the future we
should fetch replies before rendering them.
Diffstat (limited to 'resources/qml')
-rw-r--r--resources/qml/TimelineRow.qml61
-rw-r--r--resources/qml/delegates/FileMessage.qml6
-rw-r--r--resources/qml/delegates/ImageMessage.qml12
-rw-r--r--resources/qml/delegates/MessageDelegate.qml128
-rw-r--r--resources/qml/delegates/NoticeMessage.qml2
-rw-r--r--resources/qml/delegates/Placeholder.qml2
-rw-r--r--resources/qml/delegates/PlayableMediaMessage.qml16
-rw-r--r--resources/qml/delegates/TextMessage.qml2
8 files changed, 145 insertions, 84 deletions
diff --git a/resources/qml/TimelineRow.qml b/resources/qml/TimelineRow.qml
index 2c2ed02a..86780413 100644
--- a/resources/qml/TimelineRow.qml
+++ b/resources/qml/TimelineRow.qml
@@ -14,23 +14,70 @@ RowLayout {
 	anchors.left: parent.left
 	anchors.right: parent.right
 
-	height: Math.max(contentItem.height, 16)
+	//height: Math.max(model.replyTo ? reply.height + contentItem.height + 4 : contentItem.height, 16)
 
 	Column {
 		Layout.fillWidth: true
 		Layout.alignment: Qt.AlignTop
+		spacing: 4
 
-		//property var replyTo: model.replyTo
+		// fancy reply, if this is a reply
+		Rectangle {
+			visible: model.replyTo
+			width: parent.width
+			height: replyContainer.height
+
+			Rectangle {
+				id: colorLine
+				height: replyContainer.height
+				width: 4
+				color: chat.model.userColor(reply.modelData.userId, colors.window)
+			}
+
+			Column {
+				id: replyContainer
+				anchors.left: colorLine.right
+				anchors.leftMargin: 4
+				width: parent.width - 8
+
+
+				Text { 
+					id: userName
+					text: chat.model.escapeEmoji(reply.modelData.userName)
+					color: chat.model.userColor(reply.modelData.userId, colors.window)
+					textFormat: Text.RichText
+
+					MouseArea {
+						anchors.fill: parent
+						onClicked: chat.model.openUserProfile(reply.modelData.userId)
+						cursorShape: Qt.PointingHandCursor
+					}
+				}
+
+				MessageDelegate {
+					id: reply
+					width: parent.width
 
-		//Text {
-		//	property int idx: timelineManager.timeline.idToIndex(replyTo)
-		//	text: "" + (idx != -1 ? timelineManager.timeline.data(timelineManager.timeline.index(idx, 0), 2) : "nothing")
-		//}
+					modelData: chat.model.getDump(model.replyTo)
+				}
+			}
+
+			color: { var col = chat.model.userColor(reply.modelData.userId, colors.window); col.a = 0.2; return col }
+
+			MouseArea {
+				anchors.fill: parent
+				onClicked: chat.positionViewAtIndex(chat.model.idToIndex(model.replyTo), ListView.Contain)
+				cursorShape: Qt.PointingHandCursor
+			}
+		}
+
+		// actual message content
 		MessageDelegate {
 			id: contentItem
 
 			width: parent.width
-			height: childrenRect.height
+
+			modelData: model
 		}
 	}
 
diff --git a/resources/qml/delegates/FileMessage.qml b/resources/qml/delegates/FileMessage.qml
index 2c911c5e..9a5300bb 100644
--- a/resources/qml/delegates/FileMessage.qml
+++ b/resources/qml/delegates/FileMessage.qml
@@ -31,7 +31,7 @@ Rectangle {
 			}
 			MouseArea {
 				anchors.fill: parent
-				onClicked: timelineManager.timeline.saveMedia(model.id)
+				onClicked: timelineManager.timeline.saveMedia(model.data.id)
 				cursorShape: Qt.PointingHandCursor
 			}
 		}
@@ -40,14 +40,14 @@ Rectangle {
 
 			Text {
 				Layout.fillWidth: true
-				text: model.body
+				text: model.data.body
 				textFormat: Text.PlainText
 				elide: Text.ElideRight
 				color: colors.text
 			}
 			Text {
 				Layout.fillWidth: true
-				text: model.filesize
+				text: model.data.filesize
 				textFormat: Text.PlainText
 				elide: Text.ElideRight
 				color: colors.text
diff --git a/resources/qml/delegates/ImageMessage.qml b/resources/qml/delegates/ImageMessage.qml
index 15ce29b7..3393f043 100644
--- a/resources/qml/delegates/ImageMessage.qml
+++ b/resources/qml/delegates/ImageMessage.qml
@@ -3,26 +3,26 @@ import QtQuick 2.6
 import im.nheko 1.0
 
 Item {
-	property double tempWidth: Math.min(parent ? parent.width : undefined, model.width)
-	property double tempHeight: tempWidth * model.proportionalHeight
+	property double tempWidth: Math.min(parent ? parent.width : undefined, model.data.width)
+	property double tempHeight: tempWidth * model.data.proportionalHeight
 
 	property bool tooHigh: tempHeight > chat.height - 40
 
 	height: tooHigh ? chat.height - 40 : tempHeight
-	width: tooHigh ? (chat.height - 40) / model.proportionalHeight : tempWidth
+	width: tooHigh ? (chat.height - 40) / model.data.proportionalHeight : tempWidth
 
 	Image {
 		id: img
 		anchors.fill: parent
 
-		source: model.url.replace("mxc://", "image://MxcImage/")
+		source: model.data.url.replace("mxc://", "image://MxcImage/")
 		asynchronous: true
 		fillMode: Image.PreserveAspectFit
 
 		MouseArea {
-			enabled: model.type == MtxEvent.ImageMessage
+			enabled: model.data.type == MtxEvent.ImageMessage
 			anchors.fill: parent
-			onClicked: timelineManager.openImageOverlay(model.url, model.id)
+			onClicked: timelineManager.openImageOverlay(model.data.url, model.data.id)
 		}
 	}
 }
diff --git a/resources/qml/delegates/MessageDelegate.qml b/resources/qml/delegates/MessageDelegate.qml
index 20ec71e5..1716d2d4 100644
--- a/resources/qml/delegates/MessageDelegate.qml
+++ b/resources/qml/delegates/MessageDelegate.qml
@@ -1,67 +1,81 @@
 import QtQuick 2.6
 import im.nheko 1.0
 
-DelegateChooser {
-	//role: "type" //< not supported in our custom implementation, have to use roleValue
-	roleValue: model.type
-
-	DelegateChoice {
-		roleValue: MtxEvent.TextMessage
-		TextMessage {}
-	}
-	DelegateChoice {
-		roleValue: MtxEvent.NoticeMessage
-		NoticeMessage {}
-	}
-	DelegateChoice {
-		roleValue: MtxEvent.EmoteMessage
-		TextMessage {}
-	}
-	DelegateChoice {
-		roleValue: MtxEvent.ImageMessage
-		ImageMessage {}
-	}
-	DelegateChoice {
-		roleValue: MtxEvent.Sticker
-		ImageMessage {}
-	}
-	DelegateChoice {
-		roleValue: MtxEvent.FileMessage
-		FileMessage {}
+Item {
+	// Workaround to have an assignable global property
+	Item {
+		id: model
+		property var data;
 	}
-	DelegateChoice {
-		roleValue: MtxEvent.VideoMessage
-		PlayableMediaMessage {}
-	}
-	DelegateChoice {
-		roleValue: MtxEvent.AudioMessage
-		PlayableMediaMessage {}
-	}
-	DelegateChoice {
-		roleValue: MtxEvent.Redacted
-		Pill {
-			text: qsTr("redacted")
+	
+	property alias modelData: model.data
+
+	height: chooser.childrenRect.height
+
+	DelegateChooser {
+		id: chooser
+		//role: "type" //< not supported in our custom implementation, have to use roleValue
+		roleValue: model.data.type
+		anchors.fill: parent
+
+		DelegateChoice {
+			roleValue: MtxEvent.TextMessage
+			TextMessage {}
 		}
-	}
-	DelegateChoice {
-		roleValue: MtxEvent.Encryption
-		Pill {
-			text: qsTr("Encryption enabled")
+		DelegateChoice {
+			roleValue: MtxEvent.NoticeMessage
+			NoticeMessage {}
 		}
-	}
-	DelegateChoice {
-		roleValue: MtxEvent.Name
-		NoticeMessage {
-			notice: model.roomName ? qsTr("room name changed to: %1").arg(model.roomName) : qsTr("removed room name")
+		DelegateChoice {
+			roleValue: MtxEvent.EmoteMessage
+			TextMessage {}
 		}
-	}
-	DelegateChoice {
-		roleValue: MtxEvent.Topic
-		NoticeMessage {
-			notice: model.roomTopic ? qsTr("topic changed to: %1").arg(model.roomTopic) : qsTr("removed topic")
+		DelegateChoice {
+			roleValue: MtxEvent.ImageMessage
+			ImageMessage {}
+		}
+		DelegateChoice {
+			roleValue: MtxEvent.Sticker
+			ImageMessage {}
+		}
+		DelegateChoice {
+			roleValue: MtxEvent.FileMessage
+			FileMessage {}
+		}
+		DelegateChoice {
+			roleValue: MtxEvent.VideoMessage
+			PlayableMediaMessage {}
+		}
+		DelegateChoice {
+			roleValue: MtxEvent.AudioMessage
+			PlayableMediaMessage {}
+		}
+		DelegateChoice {
+			roleValue: MtxEvent.Redacted
+			Pill {
+				text: qsTr("redacted")
+			}
+		}
+		DelegateChoice {
+			roleValue: MtxEvent.Encryption
+			Pill {
+				text: qsTr("Encryption enabled")
+			}
+		}
+		DelegateChoice {
+			roleValue: MtxEvent.Name
+			NoticeMessage {
+				notice: model.data.roomName ? qsTr("room name changed to: %1").arg(model.data.roomName) : qsTr("removed room name")
+			}
+		}
+		DelegateChoice {
+			roleValue: MtxEvent.Topic
+			NoticeMessage {
+				notice: model.data.roomTopic ? qsTr("topic changed to: %1").arg(model.data.roomTopic) : qsTr("removed topic")
+			}
+		}
+		DelegateChoice {
+			Placeholder {}
 		}
-	}
-	DelegateChoice {
-		Placeholder {}
 	}
 }
diff --git a/resources/qml/delegates/NoticeMessage.qml b/resources/qml/delegates/NoticeMessage.qml
index f7467eca..34132bcf 100644
--- a/resources/qml/delegates/NoticeMessage.qml
+++ b/resources/qml/delegates/NoticeMessage.qml
@@ -1,7 +1,7 @@
 import ".."
 
 MatrixText {
-	property string notice: model.formattedBody.replace("<pre>", "<pre style='white-space: pre-wrap'>")
+	property string notice: model.data.formattedBody.replace("<pre>", "<pre style='white-space: pre-wrap'>")
 	text: notice
 	width: parent ? parent.width : undefined
 	font.italic: true
diff --git a/resources/qml/delegates/Placeholder.qml b/resources/qml/delegates/Placeholder.qml
index 4c0e68c3..36d7b2bc 100644
--- a/resources/qml/delegates/Placeholder.qml
+++ b/resources/qml/delegates/Placeholder.qml
@@ -1,7 +1,7 @@
 import ".."
 
 MatrixText {
-	text: qsTr("unimplemented event: ") + model.type
+	text: qsTr("unimplemented event: ") + model.data.type
 	width: parent ? parent.width : undefined
 	color: inactiveColors.text
 }
diff --git a/resources/qml/delegates/PlayableMediaMessage.qml b/resources/qml/delegates/PlayableMediaMessage.qml
index b3275462..ebf7487c 100644
--- a/resources/qml/delegates/PlayableMediaMessage.qml
+++ b/resources/qml/delegates/PlayableMediaMessage.qml
@@ -19,12 +19,12 @@ Rectangle {
 
 		Rectangle {
 			id: videoContainer
-			visible: model.type == MtxEvent.VideoMessage
-			width: Math.min(parent.width, model.width ? model.width : 400) // some media has 0 as size...
-			height: width*model.proportionalHeight
+			visible: model.data.type == MtxEvent.VideoMessage
+			width: Math.min(parent.width, model.data.width ? model.data.width : 400) // some media has 0 as size...
+			height: width*model.data.proportionalHeight
 			Image {
 				anchors.fill: parent
-				source: model.thumbnailUrl.replace("mxc://", "image://MxcImage/")
+				source: model.data.thumbnailUrl.replace("mxc://", "image://MxcImage/")
 				asynchronous: true
 				fillMode: Image.PreserveAspectFit
 
@@ -97,7 +97,7 @@ Rectangle {
 					anchors.fill: parent
 					onClicked: {
 						switch (button.state) {
-							case "": timelineManager.timeline.cacheMedia(model.id); break;
+							case "": timelineManager.timeline.cacheMedia(model.data.id); break;
 							case "stopped":
 							media.play(); console.log("play");
 							button.state = "playing"
@@ -120,7 +120,7 @@ Rectangle {
 				Connections {
 					target: timelineManager.timeline
 					onMediaCached: {
-						if (mxcUrl == model.url) {
+						if (mxcUrl == model.data.url) {
 							media.source = "file://" + cacheUrl
 							button.state = "stopped"
 							console.log("media loaded: " + mxcUrl + " at " + cacheUrl)
@@ -145,14 +145,14 @@ Rectangle {
 
 				Text {
 					Layout.fillWidth: true
-					text: model.body
+					text: model.data.body
 					textFormat: Text.PlainText
 					elide: Text.ElideRight
 					color: colors.text
 				}
 				Text {
 					Layout.fillWidth: true
-					text: model.filesize
+					text: model.data.filesize
 					textFormat: Text.PlainText
 					elide: Text.ElideRight
 					color: colors.text
diff --git a/resources/qml/delegates/TextMessage.qml b/resources/qml/delegates/TextMessage.qml
index f984b32f..92ba560b 100644
--- a/resources/qml/delegates/TextMessage.qml
+++ b/resources/qml/delegates/TextMessage.qml
@@ -1,6 +1,6 @@
 import ".."
 
 MatrixText {
-	text: model.formattedBody.replace("<pre>", "<pre style='white-space: pre-wrap'>")
+	text: model.data.formattedBody.replace("<pre>", "<pre style='white-space: pre-wrap'>")
 	width: parent ? parent.width : undefined
 }