Page MenuHomePhorge

No OneTemporary

Size
10 KB
Referenced Files
None
Subscribers
None
diff --git a/src/contents/ui/EventView.qml b/src/contents/ui/EventView.qml
index a9fb324..7f4fa4e 100644
--- a/src/contents/ui/EventView.qml
+++ b/src/contents/ui/EventView.qml
@@ -1,241 +1,240 @@
/*
* This file is part of kazv.
- * SPDX-FileCopyrightText: 2020-2021 Tusooa Zhu <tusooa@kazv.moe>
+ * SPDX-FileCopyrightText: 2020-2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.2
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import Qt.labs.qmlmodels 1.0
import org.kde.kirigami 2.13 as Kirigami
import 'event-types' as Types
Item {
id: eventView
property var event
property var sender
property var stateKeyUser
property var messageType: getMessageType(event)
property var iconSize: Kirigami.Units.iconSizes.large
property var inlineBadgeSize: Kirigami.Units.iconSizes.smallMedium
property var senderNameSize: Kirigami.Units.gridUnit * 1.2
property var redactPromise: undefined
- height: loader.item.implicitHeight
- anchors.left: parent.left
- anchors.right: parent.right
- //padding: Kirigami.Units.largeSpacing
+ property var minHeight: Kirigami.Units.gridUnit * 2
+
+ height: Math.max(loader.item.implicitHeight || 0, minHeight)
Component {
id: textEV
Types.Text {
event: eventView.event
sender: eventView.sender
}
}
Component {
id: emoteEV
Types.Emote {
event: eventView.event
sender: eventView.sender
}
}
Component {
id: noticeEV
Types.Notice {
event: eventView.event
sender: eventView.sender
}
}
Component {
id: stateEV
Types.State {
event: eventView.event
sender: eventView.sender
stateKeyUser: eventView.stateKeyUser
}
}
Component {
id: imageEV
Types.Image {
event: eventView.event
sender: eventView.sender
}
}
Component {
id: fileEV
Types.File {
event: eventView.event
sender: eventView.sender
}
}
Component {
id: videoEV
Types.Video {
event: eventView.event
sender: eventView.sender
}
}
Component {
id: audioEV
Types.Audio {
event: eventView.event
sender: eventView.sender
}
}
Component {
id: unknownEV
Label {
text: 'unknown event'
}
}
Component {
id: redactedEV
Types.Redacted {
event: eventView.event
sender: eventView.sender
}
}
Component {
id: ignoreEV
Item {
}
}
/* ColumnLayout { */
/* id: layout */
/* anchors.left: eventView.left */
/* anchors.right: eventView.right */
/* } */
Loader {
sourceComponent: getSource(messageType)
id: loader
/* onLoaded: { */
/* item.parent = layout; */
/* } */
anchors.left: eventView.left
anchors.right: eventView.right
}
function getSource(t) {
switch (t) {
case 'text':
return textEV;
case 'emote':
return emoteEV;
case 'notice':
return noticeEV;
case 'state':
return stateEV;
case 'image':
return imageEV;
case 'file':
return fileEV;
case 'video':
return videoEV;
case 'audio':
return audioEV;
case 'redacted':
return redactedEV;
case 'ignore':
return ignoreEV;
default:
return unknownEV;
}
}
function getMessageType(e) {
if (e.redacted) {
return 'redacted';
}
if (e.isState) {
return 'state';
}
switch (e.type) {
case 'm.room.message':
switch (e.content.msgtype) {
case 'm.text':
console.log('msg type=text');
return 'text';
case 'm.emote':
return 'emote';
case 'm.notice':
return 'notice';
case 'm.image':
return 'image';
case 'm.file':
return 'file';
case 'm.audio':
return 'audio';
case 'm.video':
return 'video';
case 'm.location':
return 'location';
default:
console.log('msg type=unknown');
return 'unknown';
}
case 'm.room.redaction':
return 'ignore';
default:
console.log('msg type=unknown');
return 'unknown';
}
}
function redactSelf(reason) {
eventView.redactPromise = room.redactEvent(eventView.event.eventId, reason);
}
Connections {
target: eventView.redactPromise
function onResolved(success, data) {
console.log('redactPromise resolved');
if (!success) {
console.log('redactPromise failed');
showPassiveNotification(l10n.get('event-delete-failed', { errorMsg: data.error, errorCode: data.errorCode }));
} else {
console.log('redactPromise successful');
}
eventView.redactPromise = null;
}
}
}
diff --git a/src/contents/ui/RoomTimelineView.qml b/src/contents/ui/RoomTimelineView.qml
index 720df2e..e14b029 100644
--- a/src/contents/ui/RoomTimelineView.qml
+++ b/src/contents/ui/RoomTimelineView.qml
@@ -1,61 +1,62 @@
/*
* This file is part of kazv.
- * SPDX-FileCopyrightText: 2020 Tusooa Zhu <tusooa@kazv.moe>
+ * SPDX-FileCopyrightText: 2020-2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import QtQuick 2.2
import QtQuick.Layouts 1.15
import QtQuick.Controls 2.15
import org.kde.kirigami 2.13 as Kirigami
ListView {
id: roomTimelineView
property var timeline
property var eventIds: timeline.eventIds
property string selectedEventId
spacing: Kirigami.Units.largeSpacing
//width: parent.width
//Layout.fillHeight: true
//anchors.fill: parent
model: timeline
//Layout.minimumHeight: childrenRect.height
currentIndex: -1
verticalLayoutDirection: ListView.BottomToTop
delegate: EventView {
event: timeline.at(index)
sender: room.member(event.sender || matrixSdk.userId)
stateKeyUser: event.stateKey ? room.member(event.stateKey) : {}
+ width: roomTimelineView.view.width
}
/* Kirigami.BasicListItem { */
/* property var item: timeline.at(index) */
/* //onClicked: roomTimelineView.selectedEventId = item.eventId */
/* onClicked: {} */
/* checkable: false */
/* checked: false */
/* //onClicked: print("clicked room %1".arg(index)) */
/* //checkable: true */
/* //checked: roomTimelineView.selectedEventId == item.eventId */
/* //autoExclusive: true */
/* Label { */
/* text: i18n("Message from %1 of type %2: %3", item.sender, item.type, item.content) */
/* } */
/* /\* actions: [ */
/* Kirigami.Action { */
/* text: i18n("Set as favourite") */
/* iconName: "non-starred-symbolic" */
/* onTriggered: showPassiveNotification(i18n("Set %1 as favourite", item.name)) */
/* } */
/* ]*\/ */
/* } */
}
diff --git a/src/matrix-room-timeline.cpp b/src/matrix-room-timeline.cpp
index 78fe227..850be5c 100644
--- a/src/matrix-room-timeline.cpp
+++ b/src/matrix-room-timeline.cpp
@@ -1,97 +1,104 @@
/*
* This file is part of kazv.
- * SPDX-FileCopyrightText: 2020 Tusooa Zhu <tusooa@kazv.moe>
+ * SPDX-FileCopyrightText: 2020-2023 tusooa <tusooa@kazv.moe>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#include <libkazv-config.hpp>
#include <immer/config.hpp> // https://github.com/arximboldi/immer/issues/168
#include <cmath>
#include <lager/lenses/optional.hpp>
+#include <QTimer>
+
#include <cursorutil.hpp>
#include "matrix-room-timeline.hpp"
#include "matrix-event.hpp"
#include "helper.hpp"
+#include "kazv-log.hpp"
+
using namespace Kazv;
MatrixRoomTimeline::MatrixRoomTimeline(Kazv::Room room, QObject *parent)
: QAbstractListModel(parent)
, m_room(room)
, m_timeline(m_room.timelineEvents())
, m_internalCount(0)
, m_localEchoes(m_room.localEchoes())
, LAGER_QT(count)(lager::with(
m_timeline.xform(containerSize),
m_localEchoes.xform(containerSize)
).map([](const auto &tlSize, const auto &localSize) { return tlSize + localSize; }))
, LAGER_QT(eventIds)(m_timeline.xform(zug::map(
[](auto container) {
return zug::into(
QStringList{},
zug::map([](Kazv::Event event) {
return QString::fromStdString(event.id());
}),
std::move(container));
})))
{
- m_internalCount = count();
-
connect(this, &MatrixRoomTimeline::countChanged, this, &MatrixRoomTimeline::updateInternalCount);
+ // HACK: If internally the count is set to its full count at the beginning,
+ // ListView will instantiate everything in the timeline.
+ // I don't know why it is the case, so I keep the internal count as 0
+ // when it is constructed, and update it in the next tick.
+ QTimer::singleShot(0, this, [this] { Q_EMIT countChanged(count()); });
}
MatrixRoomTimeline::~MatrixRoomTimeline() = default;
MatrixEvent *MatrixRoomTimeline::at(int index) const
{
return new MatrixEvent(lager::with(m_timeline, m_localEchoes, LAGER_QT(count))
.map([index](const auto &tl, const auto &localEchoes, const auto &count) -> std::variant<Kazv::Event, Kazv::LocalEchoDesc> {
auto rIndex = count - index - 1;
if (static_cast<unsigned int>(rIndex) < tl.size()) {
return tl[rIndex];
} else {
auto remainingIndex = rIndex - tl.size();
if (remainingIndex < localEchoes.size()) {
return localEchoes[remainingIndex];
} else {
return Event();
}
}
}));
}
int MatrixRoomTimeline::rowCount(const QModelIndex &index) const
{
if (index.isValid()) {
return 0;
} else {
- return count();
+ return m_internalCount;
}
}
QVariant MatrixRoomTimeline::data(const QModelIndex &, int) const
{
return QVariant();
}
void MatrixRoomTimeline::updateInternalCount()
{
auto curCount = count();
auto oldCount = m_internalCount;
auto diff = std::abs(curCount - oldCount);
if (curCount > oldCount) {
beginInsertRows(QModelIndex(), 0, diff - 1);
m_internalCount = curCount;
endInsertRows();
} else if (curCount < oldCount) {
beginRemoveRows(QModelIndex(), 0, diff - 1);
m_internalCount = curCount;
endRemoveRows();
}
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Sep 19, 3:38 PM (16 h, 49 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1769606
Default Alt Text
(10 KB)

Event Timeline