Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85713088
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
10 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
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)
Attached To
Mode
rK kazv
Attached
Detach File
Event Timeline
Log In to Comment