diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml
index bab1d932..f0f73ec9 100644
--- a/resources/qml/TimelineView.qml
+++ b/resources/qml/TimelineView.qml
@@ -1,7 +1,9 @@
-import QtQuick 2.5
+import QtQuick 2.6
import QtQuick.Controls 2.5
import QtQuick.Layouts 1.5
+import com.github.nheko 1.0
+
Rectangle {
anchors.fill: parent
@@ -26,20 +28,43 @@ Rectangle {
}
model: timelineManager.timeline
+ spacing: 4
delegate: RowLayout {
anchors.leftMargin: 52
anchors.left: parent.left
anchors.right: parent.right
anchors.rightMargin: scrollbar.width
- Text {
+ Loader {
+ id: loader
Layout.fillWidth: true
- height: contentHeight
- text: "Event content"
+ height: item.height
+ Layout.alignment: Qt.AlignTop
+
+ source: switch(model.type) {
+ case MtxEvent.Aliases: return "delegates/Aliases.qml"
+ case MtxEvent.Avatar: return "delegates/Avatar.qml"
+ case MtxEvent.CanonicalAlias: return "delegates/CanonicalAlias.qml"
+ case MtxEvent.Create: return "delegates/Create.qml"
+ case MtxEvent.GuestAccess: return "delegates/GuestAccess.qml"
+ case MtxEvent.HistoryVisibility: return "delegates/HistoryVisibility.qml"
+ case MtxEvent.JoinRules: return "delegates/JoinRules.qml"
+ case MtxEvent.Member: return "delegates/Member.qml"
+ case MtxEvent.Name: return "delegates/Name.qml"
+ case MtxEvent.PowerLevels: return "delegates/PowerLevels.qml"
+ case MtxEvent.Topic: return "delegates/Topic.qml"
+ case MtxEvent.NoticeMessage: return "delegates/NoticeMessage.qml"
+ case MtxEvent.TextMessage: return "delegates/TextMessage.qml"
+ case MtxEvent.ImageMessage: return "delegates/ImageMessage.qml"
+ case MtxEvent.VideoMessage: return "delegates/VideoMessage.qml"
+ default: return "delegates/placeholder.qml"
+ }
+ property variant eventData: model
}
+
Button {
- Layout.alignment: Qt.AlignRight
+ Layout.alignment: Qt.AlignRight | Qt.AlignTop
id: replyButton
flat: true
height: replyButtonImg.contentHeight
@@ -54,7 +79,7 @@ Rectangle {
}
}
Button {
- Layout.alignment: Qt.AlignRight
+ Layout.alignment: Qt.AlignRight | Qt.AlignTop
id: optionsButton
flat: true
height: optionsButtonImg.contentHeight
@@ -90,7 +115,7 @@ Rectangle {
}
Text {
- Layout.alignment: Qt.AlignRight
+ Layout.alignment: Qt.AlignRight | Qt.AlignTop
text: model.timestamp.toLocaleTimeString("HH:mm")
}
}
@@ -98,13 +123,18 @@ Rectangle {
section {
property: "section"
delegate: Column {
+ topPadding: 4
+ bottomPadding: 4
+ spacing: 8
+
width: parent.width
- height: dateBubble.visible ? dateBubble.height + userName.height : userName.height
+
Label {
id: dateBubble
anchors.horizontalCenter: parent.horizontalCenter
visible: section.includes(" ")
text: chat.model.formatDateSeparator(new Date(Number(section.split(" ")[1])))
+
height: contentHeight * 1.2
width: contentWidth * 1.2
horizontalAlignment: Text.AlignHCenter
@@ -114,6 +144,7 @@ Rectangle {
}
}
Row {
+ height: userName.height
spacing: 4
Rectangle {
width: 48
diff --git a/resources/qml/delegates/TextMessage.qml b/resources/qml/delegates/TextMessage.qml
new file mode 100644
index 00000000..5f4b33fa
--- /dev/null
+++ b/resources/qml/delegates/TextMessage.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.5
+
+TextEdit {
+ text: eventData.formattedBody
+ textFormat: TextEdit.RichText
+ readOnly: true
+ wrapMode: Text.Wrap
+ width: parent.width
+ selectByMouse: true
+}
diff --git a/resources/res.qrc b/resources/res.qrc
index 65770c8c..b2f27814 100644
--- a/resources/res.qrc
+++ b/resources/res.qrc
@@ -116,5 +116,6 @@
qml/TimelineView.qml
+ qml/delegates/TextMessage.qml
diff --git a/src/timeline2/TimelineModel.cpp b/src/timeline2/TimelineModel.cpp
index 6f212833..112b2752 100644
--- a/src/timeline2/TimelineModel.cpp
+++ b/src/timeline2/TimelineModel.cpp
@@ -1,5 +1,7 @@
#include "TimelineModel.h"
+#include
+
#include
#include "Logging.h"
@@ -31,6 +33,119 @@ eventTimestamp(const T &event)
{
return QDateTime::fromMSecsSinceEpoch(event.origin_server_ts);
}
+
+template
+QString
+eventFormattedBody(const mtx::events::Event &)
+{
+ return QString("");
+}
+template
+auto
+eventFormattedBody(const mtx::events::RoomEvent &e)
+ -> std::enable_if_t::value, QString>
+{
+ auto temp = e.content.formatted_body;
+ if (!temp.empty()) {
+ auto pos = temp.find("");
+ if (pos != std::string::npos)
+ temp.erase(pos, std::string("").size());
+ pos = temp.find("");
+ if (pos != std::string::npos)
+ temp.erase(pos, std::string("").size());
+ return QString::fromStdString(temp);
+ } else
+ return QString::fromStdString(e.content.body);
+}
+
+template
+qml_mtx_events::EventType
+toRoomEventType(const mtx::events::Event &e)
+{
+ using mtx::events::EventType;
+ switch (e.type) {
+ case EventType::RoomKeyRequest:
+ return qml_mtx_events::EventType::KeyRequest;
+ case EventType::RoomAliases:
+ return qml_mtx_events::EventType::Aliases;
+ case EventType::RoomAvatar:
+ return qml_mtx_events::EventType::Avatar;
+ case EventType::RoomCanonicalAlias:
+ return qml_mtx_events::EventType::CanonicalAlias;
+ case EventType::RoomCreate:
+ return qml_mtx_events::EventType::Create;
+ case EventType::RoomEncrypted:
+ return qml_mtx_events::EventType::Encrypted;
+ case EventType::RoomEncryption:
+ return qml_mtx_events::EventType::Encryption;
+ case EventType::RoomGuestAccess:
+ return qml_mtx_events::EventType::GuestAccess;
+ case EventType::RoomHistoryVisibility:
+ return qml_mtx_events::EventType::HistoryVisibility;
+ case EventType::RoomJoinRules:
+ return qml_mtx_events::EventType::JoinRules;
+ case EventType::RoomMember:
+ return qml_mtx_events::EventType::Member;
+ case EventType::RoomMessage:
+ return qml_mtx_events::EventType::UnknownMessage;
+ case EventType::RoomName:
+ return qml_mtx_events::EventType::Name;
+ case EventType::RoomPowerLevels:
+ return qml_mtx_events::EventType::PowerLevels;
+ case EventType::RoomTopic:
+ return qml_mtx_events::EventType::Topic;
+ case EventType::RoomTombstone:
+ return qml_mtx_events::EventType::Tombstone;
+ case EventType::RoomRedaction:
+ return qml_mtx_events::EventType::Redaction;
+ case EventType::RoomPinnedEvents:
+ return qml_mtx_events::EventType::PinnedEvents;
+ case EventType::Sticker:
+ return qml_mtx_events::EventType::Sticker;
+ case EventType::Tag:
+ return qml_mtx_events::EventType::Tag;
+ case EventType::Unsupported:
+ default:
+ return qml_mtx_events::EventType::Unsupported;
+ }
+}
+qml_mtx_events::EventType
+toRoomEventType(const mtx::events::Event &)
+{
+ return qml_mtx_events::EventType::AudioMessage;
+}
+qml_mtx_events::EventType
+toRoomEventType(const mtx::events::Event &)
+{
+ return qml_mtx_events::EventType::EmoteMessage;
+}
+qml_mtx_events::EventType
+toRoomEventType(const mtx::events::Event &)
+{
+ return qml_mtx_events::EventType::FileMessage;
+}
+qml_mtx_events::EventType
+toRoomEventType(const mtx::events::Event &)
+{
+ return qml_mtx_events::EventType::ImageMessage;
+}
+qml_mtx_events::EventType
+toRoomEventType(const mtx::events::Event &)
+{
+ return qml_mtx_events::EventType::NoticeMessage;
+}
+qml_mtx_events::EventType
+toRoomEventType(const mtx::events::Event &)
+{
+ return qml_mtx_events::EventType::TextMessage;
+}
+qml_mtx_events::EventType
+toRoomEventType(const mtx::events::Event &)
+{
+ return qml_mtx_events::EventType::VideoMessage;
+}
+// ::EventType::Type toRoomEventType(const Event &e) { return
+// ::EventType::LocationMessage; }
}
TimelineModel::TimelineModel(QString room_id, QObject *parent)
@@ -105,6 +220,14 @@ TimelineModel::data(const QModelIndex &index, int role) const
case Timestamp:
return QVariant(boost::apply_visitor(
[](const auto &e) -> QDateTime { return eventTimestamp(e); }, events.value(id)));
+ case Type:
+ return QVariant(boost::apply_visitor(
+ [](const auto &e) -> qml_mtx_events::EventType { return toRoomEventType(e); },
+ events.value(id)));
+ case FormattedBody:
+ return QVariant(utils::replaceEmoji(boost::apply_visitor(
+ [](const auto &e) -> QString { return eventFormattedBody(e); },
+ events.value(id))));
default:
return QVariant();
}
diff --git a/src/timeline2/TimelineModel.h b/src/timeline2/TimelineModel.h
index e2c7b73a..3af94643 100644
--- a/src/timeline2/TimelineModel.h
+++ b/src/timeline2/TimelineModel.h
@@ -7,6 +7,65 @@
#include
+namespace qml_mtx_events {
+Q_NAMESPACE
+
+enum EventType
+{
+ // Unsupported event
+ Unsupported,
+ /// m.room_key_request
+ KeyRequest,
+ /// m.room.aliases
+ Aliases,
+ /// m.room.avatar
+ Avatar,
+ /// m.room.canonical_alias
+ CanonicalAlias,
+ /// m.room.create
+ Create,
+ /// m.room.encrypted.
+ Encrypted,
+ /// m.room.encryption.
+ Encryption,
+ /// m.room.guest_access
+ GuestAccess,
+ /// m.room.history_visibility
+ HistoryVisibility,
+ /// m.room.join_rules
+ JoinRules,
+ /// m.room.member
+ Member,
+ /// m.room.name
+ Name,
+ /// m.room.power_levels
+ PowerLevels,
+ /// m.room.tombstone
+ Tombstone,
+ /// m.room.topic
+ Topic,
+ /// m.room.redaction
+ Redaction,
+ /// m.room.pinned_events
+ PinnedEvents,
+ // m.sticker
+ Sticker,
+ // m.tag
+ Tag,
+ /// m.room.message
+ AudioMessage,
+ EmoteMessage,
+ FileMessage,
+ ImageMessage,
+ LocationMessage,
+ NoticeMessage,
+ TextMessage,
+ VideoMessage,
+ UnknownMessage,
+};
+Q_ENUM_NS(EventType)
+}
+
class TimelineModel : public QAbstractListModel
{
Q_OBJECT
@@ -26,8 +85,8 @@ public:
};
QHash roleNames() const override;
- int rowCount(const QModelIndex &parent = QModelIndex()) const;
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
Q_INVOKABLE QColor userColor(QString id, QColor background);
Q_INVOKABLE QString displayName(QString id) const;
@@ -40,6 +99,7 @@ public slots:
private slots:
// Add old events at the top of the timeline.
+
void addBackwardsEvents(const mtx::responses::Messages &msgs);
signals:
@@ -57,4 +117,4 @@ private:
QHash userColors;
};
-
+
diff --git a/src/timeline2/TimelineViewManager.cpp b/src/timeline2/TimelineViewManager.cpp
index 32321fd2..df9a2270 100644
--- a/src/timeline2/TimelineViewManager.cpp
+++ b/src/timeline2/TimelineViewManager.cpp
@@ -7,6 +7,13 @@
TimelineViewManager::TimelineViewManager(QWidget *parent)
{
+ qmlRegisterUncreatableMetaObject(qml_mtx_events::staticMetaObject,
+ "com.github.nheko",
+ 1,
+ 0,
+ "MtxEvent",
+ "Can't instantiate enum!");
+
view = new QQuickView();
container = QWidget::createWindowContainer(view, parent);
container->setMinimumSize(200, 200);