fix: show new messages at the bottom

This commit is contained in:
Richard Ramos 2020-06-04 19:42:11 -04:00 committed by Iuri Matias
parent 722ab36bf1
commit 1b086b006d
2 changed files with 58 additions and 75 deletions

View File

@ -1,27 +1,45 @@
import QtQuick 2.14
import QtQuick.Controls 2.3
import QtQuick.Controls 2.14 as QQC2
import QtQuick.Layouts 1.3
import Qt.labs.platform 1.1
import QtQml.Models 2.3
import "../../../../shared"
import "../../../../imports"
import "./samples/"
ScrollView {
id: scrollView
property var messageList: MessagesData {}
contentItem: chatLogView
anchors.fill: parent
Layout.fillWidth: true
Layout.fillHeight: true
ScrollBar.vertical.policy: chatLogView.contentHeight > chatLogView.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff
ScrollBar.vertical.policy: ScrollBar.AlwaysOn
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
SortFilterModel {
id: messageListDelegate
lessThan: function(left, right) {
return left.clock < right.clock;
function scrollToBottom(goToBottom) {
chatLogView.positionViewAtEnd();
}
ListView {
anchors.fill: parent
spacing: 4
id: chatLogView
Layout.fillWidth: true
Layout.fillHeight: true
onCountChanged: {
scrollToBottom();
}
model: messageListDelegate
}
DelegateModel {
id: messageListDelegate
model: messageList
delegate: Message {
userName: model.userName
@ -33,29 +51,47 @@ ScrollView {
sticker: model.sticker
contentType: model.contentType
}
}
ListView {
anchors.fill: parent
spacing: 4
id: chatLogView
model: messageListDelegate
Layout.fillWidth: true
Layout.fillHeight: true
highlightFollowsCurrentItem: true
onCountChanged: {
if (!this.atYEnd) {
// User has scrolled up, we don't want to scroll back
return
property var lessThan: function(left, right) { return left.clock < right.clock }
function insertPosition(lessThan, item) {
var lower = 0
var upper = items.count
while (lower < upper) {
var middle = Math.floor(lower + (upper - lower) / 2)
var result = lessThan(item.model, items.get(middle).model);
if (result) {
upper = middle
} else {
lower = middle + 1
}
}
return lower
}
// positionViewAtEnd doesn't work well. Instead, we use highlightFollowsCurrentItem
// and set the current Item/Index to the latest item
while (this.currentIndex < this.count - 1) {
this.incrementCurrentIndex()
function sort(lessThan) {
while (unsortedItems.count > 0) {
var item = unsortedItems.get(0)
var index = insertPosition(lessThan, item)
item.groups = "items"
items.move(item.itemsIndex, index)
}
}
items.includeByDefault: false
groups: DelegateModelGroup {
id: unsortedItems
name: "unsorted"
includeByDefault: true
onChanged: {
messageListDelegate.sort(messageListDelegate.lessThan)
scrollToBottom();
}
}
}
}
/*##^##

View File

@ -1,53 +0,0 @@
import QtQuick 2.9
import QtQml.Models 2.3
// https://martin.rpdev.net/2019/01/15/using-delegatemodel-in-qml-for-sorting-and-filtering.html
DelegateModel {
id: delegateModel
property var lessThan: function(left, right) { return true; }
property var filterAcceptsItem: function(item) { return true; }
function update() {
if (items.count > 0) {
items.setGroups(0, items.count, "items");
}
// Step 1: Filter items
var visible = [];
for (var i = 0; i < items.count; ++i) {
var item = items.get(i);
if (filterAcceptsItem(item.model)) {
visible.push(item);
}
}
// Step 2: Sort the list of visible items
visible.sort(function(a, b) {
return lessThan(a.model, b.model) ? -1 : 1;
});
// Step 3: Add all items to the visible group:
for (i = 0; i < visible.length; ++i) {
item = visible[i];
item.inVisible = true;
if (item.visibleIndex !== i) {
visibleItems.move(item.visibleIndex, i, 1);
}
}
}
items.onChanged: update()
onLessThanChanged: update()
onFilterAcceptsItemChanged: update()
groups: DelegateModelGroup {
id: visibleItems
name: "visible"
includeByDefault: false
}
filterOnGroup: "visible"
}