mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-25 12:38:48 +03:00
invert timeline
This commit is contained in:
parent
0222996cbd
commit
946ab4d0f2
3 changed files with 88 additions and 21 deletions
|
@ -115,30 +115,68 @@ Item {
|
||||||
onMovementEnded: updatePosition()
|
onMovementEnded: updatePosition()
|
||||||
|
|
||||||
spacing: 4
|
spacing: 4
|
||||||
delegate: TimelineRow {
|
verticalLayoutDirection: ListView.BottomToTop
|
||||||
|
|
||||||
|
delegate: Rectangle {
|
||||||
|
// This would normally be previousSection, but our model's order is inverted.
|
||||||
|
property bool sectionBoundary: (ListView.nextSection != "" && ListView.nextSection !== ListView.section) || model.index === chat.count - 1
|
||||||
|
|
||||||
|
id: wrapper
|
||||||
|
property Item section
|
||||||
|
width: chat.width
|
||||||
|
height: section ? section.height + timelinerow.height : timelinerow.height
|
||||||
|
|
||||||
|
TimelineRow {
|
||||||
|
id: timelinerow
|
||||||
|
y: section ? section.y + section.height : 0
|
||||||
|
}
|
||||||
function isFullyVisible() {
|
function isFullyVisible() {
|
||||||
return height > 1 && (y - chat.contentY - 1) + height < chat.height
|
return height > 1 && (y - chat.contentY - 1) + height < chat.height
|
||||||
}
|
}
|
||||||
function getIndex() {
|
function getIndex() {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSectionBoundaryChanged: {
|
||||||
|
if (sectionBoundary) {
|
||||||
|
var properties = {
|
||||||
|
'modelData': model.dump,
|
||||||
|
'section': ListView.section,
|
||||||
|
'nextSection': ListView.nextSection
|
||||||
|
}
|
||||||
|
section = sectionHeader.createObject(wrapper, properties)
|
||||||
|
} else {
|
||||||
|
section.destroy()
|
||||||
|
section = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
section {
|
section {
|
||||||
property: "section"
|
property: "section"
|
||||||
delegate: Column {
|
}
|
||||||
|
Component {
|
||||||
|
id: sectionHeader
|
||||||
|
Column {
|
||||||
|
property var modelData
|
||||||
|
property string section
|
||||||
|
property string nextSection
|
||||||
|
|
||||||
topPadding: 4
|
topPadding: 4
|
||||||
bottomPadding: 4
|
bottomPadding: 4
|
||||||
spacing: 8
|
spacing: 8
|
||||||
|
|
||||||
|
visible: !!modelData
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: (section.includes(" ") ? dateBubble.height + 8 + userName.height : userName.height) + 8
|
height: (section.includes(" ") ? dateBubble.height + 8 + userName.height : userName.height) + 8
|
||||||
|
|
||||||
Label {
|
Label {
|
||||||
id: dateBubble
|
id: dateBubble
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined
|
||||||
visible: section.includes(" ")
|
visible: section.includes(" ")
|
||||||
text: chat.model.formatDateSeparator(new Date(Number(section.split(" ")[1])))
|
text: chat.model.formatDateSeparator(modelData.timestamp)
|
||||||
color: colors.windowText
|
color: colors.windowText
|
||||||
|
|
||||||
height: contentHeight * 1.2
|
height: contentHeight * 1.2
|
||||||
|
@ -155,20 +193,20 @@ Item {
|
||||||
Avatar {
|
Avatar {
|
||||||
width: avatarSize
|
width: avatarSize
|
||||||
height: avatarSize
|
height: avatarSize
|
||||||
url: chat.model.avatarUrl(section.split(" ")[0]).replace("mxc://", "image://MxcImage/")
|
url: chat.model.avatarUrl(modelData.userId).replace("mxc://", "image://MxcImage/")
|
||||||
displayName: chat.model.displayName(section.split(" ")[0])
|
displayName: modelData.userName
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onClicked: chat.model.openUserProfile(section.split(" ")[0])
|
onClicked: chat.model.openUserProfile(modelData.userId)
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: userName
|
id: userName
|
||||||
text: chat.model.escapeEmoji(chat.model.displayName(section.split(" ")[0]))
|
text: chat.model.escapeEmoji(modelData.userName)
|
||||||
color: chat.model.userColor(section.split(" ")[0], colors.window)
|
color: chat.model.userColor(modelData.userId, colors.window)
|
||||||
textFormat: Text.RichText
|
textFormat: Text.RichText
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
|
|
|
@ -202,6 +202,7 @@ TimelineModel::roleNames() const
|
||||||
{ReplyTo, "replyTo"},
|
{ReplyTo, "replyTo"},
|
||||||
{RoomName, "roomName"},
|
{RoomName, "roomName"},
|
||||||
{RoomTopic, "roomTopic"},
|
{RoomTopic, "roomTopic"},
|
||||||
|
{Dump, "dump"},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
int
|
int
|
||||||
|
@ -235,7 +236,7 @@ TimelineModel::data(const QModelIndex &index, int role) const
|
||||||
|
|
||||||
std::string userId = acc::sender(event);
|
std::string userId = acc::sender(event);
|
||||||
|
|
||||||
for (int r = index.row() - 1; r > 0; r--) {
|
for (size_t r = index.row() + 1; r < eventOrder.size(); r++) {
|
||||||
auto tempEv = events.value(eventOrder[r]);
|
auto tempEv = events.value(eventOrder[r]);
|
||||||
QDateTime prevDate = origin_server_ts(tempEv);
|
QDateTime prevDate = origin_server_ts(tempEv);
|
||||||
prevDate.setTime(QTime());
|
prevDate.setTime(QTime());
|
||||||
|
@ -314,6 +315,35 @@ TimelineModel::data(const QModelIndex &index, int role) const
|
||||||
return QVariant(QString::fromStdString(room_name(event)));
|
return QVariant(QString::fromStdString(room_name(event)));
|
||||||
case RoomTopic:
|
case RoomTopic:
|
||||||
return QVariant(QString::fromStdString(room_topic(event)));
|
return QVariant(QString::fromStdString(room_topic(event)));
|
||||||
|
case Dump: {
|
||||||
|
QVariantMap m;
|
||||||
|
auto names = roleNames();
|
||||||
|
|
||||||
|
// m.insert(names[Section], data(index, static_cast<int>(Section)));
|
||||||
|
m.insert(names[Type], data(index, static_cast<int>(Type)));
|
||||||
|
m.insert(names[Body], data(index, static_cast<int>(Body)));
|
||||||
|
m.insert(names[FormattedBody], data(index, static_cast<int>(FormattedBody)));
|
||||||
|
m.insert(names[UserId], data(index, static_cast<int>(UserId)));
|
||||||
|
m.insert(names[UserName], data(index, static_cast<int>(UserName)));
|
||||||
|
m.insert(names[Timestamp], data(index, static_cast<int>(Timestamp)));
|
||||||
|
m.insert(names[Url], data(index, static_cast<int>(Url)));
|
||||||
|
m.insert(names[ThumbnailUrl], data(index, static_cast<int>(ThumbnailUrl)));
|
||||||
|
m.insert(names[Filename], data(index, static_cast<int>(Filename)));
|
||||||
|
m.insert(names[Filesize], data(index, static_cast<int>(Filesize)));
|
||||||
|
m.insert(names[MimeType], data(index, static_cast<int>(MimeType)));
|
||||||
|
m.insert(names[Height], data(index, static_cast<int>(Height)));
|
||||||
|
m.insert(names[Width], data(index, static_cast<int>(Width)));
|
||||||
|
m.insert(names[ProportionalHeight],
|
||||||
|
data(index, static_cast<int>(ProportionalHeight)));
|
||||||
|
m.insert(names[Id], data(index, static_cast<int>(Id)));
|
||||||
|
m.insert(names[State], data(index, static_cast<int>(State)));
|
||||||
|
m.insert(names[IsEncrypted], data(index, static_cast<int>(IsEncrypted)));
|
||||||
|
m.insert(names[ReplyTo], data(index, static_cast<int>(ReplyTo)));
|
||||||
|
m.insert(names[RoomName], data(index, static_cast<int>(RoomName)));
|
||||||
|
m.insert(names[RoomTopic], data(index, static_cast<int>(RoomTopic)));
|
||||||
|
|
||||||
|
return QVariant(m);
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
@ -335,10 +365,8 @@ TimelineModel::addEvents(const mtx::responses::Timeline &timeline)
|
||||||
if (ids.empty())
|
if (ids.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
beginInsertRows(QModelIndex(),
|
beginInsertRows(QModelIndex(), 0, static_cast<int>(ids.size() - 1));
|
||||||
static_cast<int>(this->eventOrder.size()),
|
this->eventOrder.insert(this->eventOrder.begin(), ids.rbegin(), ids.rend());
|
||||||
static_cast<int>(this->eventOrder.size() + ids.size() - 1));
|
|
||||||
this->eventOrder.insert(this->eventOrder.end(), ids.begin(), ids.end());
|
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
|
|
||||||
updateLastMessage();
|
updateLastMessage();
|
||||||
|
@ -362,7 +390,7 @@ isMessage(const mtx::events::Event<T> &)
|
||||||
void
|
void
|
||||||
TimelineModel::updateLastMessage()
|
TimelineModel::updateLastMessage()
|
||||||
{
|
{
|
||||||
for (auto it = eventOrder.rbegin(); it != eventOrder.rend(); ++it) {
|
for (auto it = eventOrder.begin(); it != eventOrder.end(); ++it) {
|
||||||
auto event = events.value(*it);
|
auto event = events.value(*it);
|
||||||
if (auto e = std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
|
if (auto e = std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
|
||||||
&event)) {
|
&event)) {
|
||||||
|
@ -499,8 +527,10 @@ TimelineModel::addBackwardsEvents(const mtx::responses::Messages &msgs)
|
||||||
std::vector<QString> ids = internalAddEvents(msgs.chunk);
|
std::vector<QString> ids = internalAddEvents(msgs.chunk);
|
||||||
|
|
||||||
if (!ids.empty()) {
|
if (!ids.empty()) {
|
||||||
beginInsertRows(QModelIndex(), 0, static_cast<int>(ids.size() - 1));
|
beginInsertRows(QModelIndex(),
|
||||||
this->eventOrder.insert(this->eventOrder.begin(), ids.rbegin(), ids.rend());
|
static_cast<int>(this->eventOrder.size()),
|
||||||
|
static_cast<int>(this->eventOrder.size() + ids.size() - 1));
|
||||||
|
this->eventOrder.insert(this->eventOrder.end(), ids.begin(), ids.end());
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1120,11 +1150,9 @@ TimelineModel::addPendingMessage(mtx::events::collections::TimelineEvents event)
|
||||||
internalAddEvents({event});
|
internalAddEvents({event});
|
||||||
|
|
||||||
QString txn_id_qstr = QString::fromStdString(mtx::accessors::event_id(event));
|
QString txn_id_qstr = QString::fromStdString(mtx::accessors::event_id(event));
|
||||||
beginInsertRows(QModelIndex(),
|
beginInsertRows(QModelIndex(), 0, 0);
|
||||||
static_cast<int>(this->eventOrder.size()),
|
|
||||||
static_cast<int>(this->eventOrder.size()));
|
|
||||||
pending.push_back(txn_id_qstr);
|
pending.push_back(txn_id_qstr);
|
||||||
this->eventOrder.insert(this->eventOrder.end(), txn_id_qstr);
|
this->eventOrder.insert(this->eventOrder.begin(), txn_id_qstr);
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
updateLastMessage();
|
updateLastMessage();
|
||||||
|
|
||||||
|
|
|
@ -147,6 +147,7 @@ public:
|
||||||
ReplyTo,
|
ReplyTo,
|
||||||
RoomName,
|
RoomName,
|
||||||
RoomTopic,
|
RoomTopic,
|
||||||
|
Dump,
|
||||||
};
|
};
|
||||||
|
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
Loading…
Reference in a new issue