nheko/resources/qml/TimelineView.qml
Nicolas Werner a83ae7e95f Fix section layout issues and pagination issues
Pagination could get stuck, if the messages request failed.
Section height seemes to have been calculated to late, which would make
some section overlap the next message in some cases. Fix that by doing
the height calculation manually.
2019-11-23 20:06:15 +01:00

184 lines
4.4 KiB
QML

import QtQuick 2.6
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.2
import QtGraphicalEffects 1.0
import QtQuick.Window 2.2
import Qt.labs.qmlmodels 1.0
import com.github.nheko 1.0
import "./delegates"
Rectangle {
anchors.fill: parent
SystemPalette { id: colors; colorGroup: SystemPalette.Active }
SystemPalette { id: inactiveColors; colorGroup: SystemPalette.Disabled }
property int avatarSize: 32
color: colors.window
Text {
visible: !timelineManager.timeline
anchors.centerIn: parent
text: qsTr("No room open")
font.pointSize: 24
color: colors.windowText
}
ListView {
id: chat
cacheBuffer: parent.height
visible: timelineManager.timeline != null
anchors.fill: parent
model: timelineManager.timeline
onModelChanged: {
if (model) {
currentIndex = model.currentIndex
if (model.currentIndex == count - 1) {
positionViewAtEnd()
} else {
positionViewAtIndex(model.currentIndex, ListView.End)
}
if (contentHeight < height) {
model.fetchHistory();
}
}
}
ScrollBar.vertical: ScrollBar {
id: scrollbar
anchors.top: parent.top
anchors.right: parent.right
anchors.bottom: parent.bottom
onPressedChanged: if (!pressed) chat.updatePosition()
}
property bool atBottom: false
onCountChanged: {
if (atBottom && Window.active) {
var newIndex = count - 1 // last index
positionViewAtEnd()
currentIndex = newIndex
model.currentIndex = newIndex
}
if (contentHeight < height && model) {
model.fetchHistory();
}
}
onAtYBeginningChanged: if (atYBeginning) model.fetchHistory()
function updatePosition() {
for (var y = chat.contentY + chat.height; y > chat.height; y -= 5) {
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;
console.log("bottom:" + atBottom)
break;
}
}
onMovementEnded: updatePosition()
spacing: 4
delegate: DelegateChooser {
role: "type"
DelegateChoice {
roleValue: MtxEvent.TextMessage
TimelineRow { view: chat; TextMessage { id: kid } }
}
DelegateChoice {
roleValue: MtxEvent.NoticeMessage
TimelineRow { view: chat; NoticeMessage { id: kid } }
}
DelegateChoice {
roleValue: MtxEvent.EmoteMessage
TimelineRow { view: chat; TextMessage { id: kid } }
}
DelegateChoice {
roleValue: MtxEvent.ImageMessage
TimelineRow { view: chat; ImageMessage { id: kid } }
}
DelegateChoice {
roleValue: MtxEvent.Sticker
TimelineRow { view: chat; ImageMessage { id: kid } }
}
DelegateChoice {
roleValue: MtxEvent.FileMessage
TimelineRow { view: chat; FileMessage { id: kid } }
}
DelegateChoice {
roleValue: MtxEvent.VideoMessage
TimelineRow { view: chat; PlayableMediaMessage { id: kid } }
}
DelegateChoice {
roleValue: MtxEvent.AudioMessage
TimelineRow { view: chat; PlayableMediaMessage { id: kid } }
}
DelegateChoice {
roleValue: MtxEvent.Redacted
TimelineRow { view: chat; Redacted { id: kid } }
}
DelegateChoice {
//roleValue: MtxEvent.Redacted
TimelineRow { view: chat; Placeholder { id: kid } }
}
}
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])
}
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
}
}
}
}
}
}