Skip to content
Snippets Groups Projects
TimelineView.qml 4 KiB
Newer Older
import QtQuick 2.6
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.2
import QtGraphicalEffects 1.0
import QtQuick.Window 2.2
import com.github.nheko 1.0

Nicolas Werner's avatar
Nicolas Werner committed
import "./delegates"

	property var colors: currentActivePalette
	property var systemInactive: SystemPalette { colorGroup: SystemPalette.Disabled }
	property var inactiveColors: currentInactivePalette ? currentInactivePalette : systemInactive
	property int avatarSize: 40
	Rectangle {
		anchors.fill: parent
		color: colors.window

		Text {
			visible: !timelineManager.timeline && !timelineManager.isInitialSync
			anchors.centerIn: parent
			text: qsTr("No room open")
			font.pointSize: 24
			color: colors.windowText
		}
		BusyIndicator {
			anchors.centerIn: parent
			running: timelineManager.isInitialSync
			height: 200
			width: 200
		}

			visible: timelineManager.timeline != null
			anchors.fill: parent
			anchors.leftMargin: 4
			anchors.rightMargin: scrollbar.width
			onModelChanged: {
				if (model) {
					currentIndex = model.currentIndex
					if (model.currentIndex == count - 1) {
						positionViewAtEnd()
					} else {
						positionViewAtIndex(model.currentIndex, ListView.End)
					}
			ScrollBar.vertical: ScrollBar {
				id: scrollbar
				anchors.top: parent.top
				anchors.left: parent.right
				anchors.bottom: parent.bottom
				onPressedChanged: if (!pressed) chat.updatePosition()
			property bool atBottom: false
			onCountChanged: {
				if (atBottom) {
					var newIndex = count - 1 // last index
					positionViewAtEnd()
					currentIndex = newIndex
					model.currentIndex = newIndex
				}
				if (contentHeight < height && model) {
					model.fetchHistory();
				}
			onAtYBeginningChanged: if (atYBeginning) { chat.model.currentIndex = 0; chat.currentIndex = 0; model.fetchHistory(); }

			function updatePosition() {
				for (var y = chat.contentY + chat.height; y > chat.height; y -= 9) {
					var i = chat.itemAt(100, y);
					if (!i) continue;
					if (!i.isFullyVisible()) continue;
					chat.model.currentIndex = i.getIndex();
					chat.currentIndex = i.getIndex()
					atBottom = i.getIndex() == count - 1;
					break;
				}
			spacing: 4
			delegate: TimelineRow {
				function isFullyVisible() {
					return height > 1 && (y - chat.contentY - 1) + height < chat.height
				function getIndex() {
					return index;
				}
			}

			section {
				property: "section"
				delegate: Column {
					topPadding: 4
					bottomPadding: 4
					spacing: 8

					width: parent.width
					height: (section.includes(" ") ? dateBubble.height + 8 + userName.height : userName.height) + 8

					Label {
						id: dateBubble
						anchors.horizontalCenter: parent.horizontalCenter
						visible: section.includes(" ")
						text: chat.model.formatDateSeparator(new Date(Number(section.split(" ")[1])))
						color: colors.windowText

						height: contentHeight * 1.2
						width: contentWidth * 1.2
						horizontalAlignment: Text.AlignHCenter
						background: Rectangle {
							radius: parent.height / 2
							color: colors.dark
					Row {
						height: userName.height
						spacing: 4
						Avatar {
							width: avatarSize
							height: avatarSize
							url: chat.model.avatarUrl(section.split(" ")[0]).replace("mxc://", "image://MxcImage/")
							displayName: chat.model.displayName(section.split(" ")[0])

							MouseArea {
								anchors.fill: parent
								onClicked: chat.model.openUserProfile(section.split(" ")[0])
								cursorShape: Qt.PointingHandCursor
							}
						}
						Text { 
							id: userName
							text: chat.model.escapeEmoji(chat.model.displayName(section.split(" ")[0]))
							color: chat.model.userColor(section.split(" ")[0], colors.window)
							textFormat: Text.RichText

							MouseArea {
								anchors.fill: parent
								onClicked: chat.model.openUserProfile(section.split(" ")[0])
								cursorShape: Qt.PointingHandCursor
							}