Move visitors out of TimelineModel
This commit is contained in:
parent
768ae9a5e0
commit
e084543cc0
@ -219,6 +219,7 @@ set(SRC_FILES
|
|||||||
src/ChatPage.cpp
|
src/ChatPage.cpp
|
||||||
src/CommunitiesListItem.cpp
|
src/CommunitiesListItem.cpp
|
||||||
src/CommunitiesList.cpp
|
src/CommunitiesList.cpp
|
||||||
|
src/EventAccessors.cpp
|
||||||
src/InviteeItem.cpp
|
src/InviteeItem.cpp
|
||||||
src/LoginPage.cpp
|
src/LoginPage.cpp
|
||||||
src/Logging.cpp
|
src/Logging.cpp
|
||||||
|
363
src/EventAccessors.cpp
Normal file
363
src/EventAccessors.cpp
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
#include "EventAccessors.h"
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct nonesuch
|
||||||
|
{
|
||||||
|
~nonesuch() = delete;
|
||||||
|
nonesuch(nonesuch const &) = delete;
|
||||||
|
void operator=(nonesuch const &) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
template<class Default, class AlwaysVoid, template<class...> class Op, class... Args>
|
||||||
|
struct detector
|
||||||
|
{
|
||||||
|
using value_t = std::false_type;
|
||||||
|
using type = Default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class Default, template<class...> class Op, class... Args>
|
||||||
|
struct detector<Default, std::void_t<Op<Args...>>, Op, Args...>
|
||||||
|
{
|
||||||
|
using value_t = std::true_type;
|
||||||
|
using type = Op<Args...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
template<template<class...> class Op, class... Args>
|
||||||
|
using is_detected = typename detail::detector<nonesuch, void, Op, Args...>::value_t;
|
||||||
|
|
||||||
|
struct EventMsgType
|
||||||
|
{
|
||||||
|
template<class E>
|
||||||
|
using msgtype_t = decltype(E::msgtype);
|
||||||
|
template<class T>
|
||||||
|
mtx::events::MessageType operator()(const mtx::events::Event<T> &e)
|
||||||
|
{
|
||||||
|
if constexpr (is_detected<msgtype_t, T>::value)
|
||||||
|
return mtx::events::getMessageType(e.content.msgtype);
|
||||||
|
return mtx::events::MessageType::Unknown;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EventRoomName
|
||||||
|
{
|
||||||
|
template<class T>
|
||||||
|
std::string operator()(const T &e)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<mtx::events::StateEvent<mtx::events::state::Name>, T>)
|
||||||
|
return e.content.name;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EventRoomTopic
|
||||||
|
{
|
||||||
|
template<class T>
|
||||||
|
std::string operator()(const T &e)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<mtx::events::StateEvent<mtx::events::state::Topic>, T>)
|
||||||
|
return e.content.topic;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EventBody
|
||||||
|
{
|
||||||
|
template<class C>
|
||||||
|
using body_t = decltype(C::body);
|
||||||
|
template<class T>
|
||||||
|
std::string operator()(const mtx::events::Event<T> &e)
|
||||||
|
{
|
||||||
|
if constexpr (is_detected<body_t, T>::value)
|
||||||
|
return e.content.body;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EventFormattedBody
|
||||||
|
{
|
||||||
|
template<class C>
|
||||||
|
using formatted_body_t = decltype(C::formatted_body);
|
||||||
|
template<class T>
|
||||||
|
std::string operator()(const mtx::events::RoomEvent<T> &e)
|
||||||
|
{
|
||||||
|
if constexpr (is_detected<formatted_body_t, T>::value)
|
||||||
|
return e.content.formatted_body;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EventFile
|
||||||
|
{
|
||||||
|
template<class Content>
|
||||||
|
using file_t = decltype(Content::file);
|
||||||
|
template<class T>
|
||||||
|
std::optional<mtx::crypto::EncryptedFile> operator()(const mtx::events::Event<T> &e)
|
||||||
|
{
|
||||||
|
if constexpr (is_detected<file_t, T>::value)
|
||||||
|
return e.content.file;
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EventUrl
|
||||||
|
{
|
||||||
|
template<class Content>
|
||||||
|
using url_t = decltype(Content::url);
|
||||||
|
template<class T>
|
||||||
|
std::string operator()(const mtx::events::Event<T> &e)
|
||||||
|
{
|
||||||
|
if constexpr (is_detected<url_t, T>::value) {
|
||||||
|
if (auto file = EventFile{}(e))
|
||||||
|
return file->url;
|
||||||
|
return e.content.url;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EventThumbnailUrl
|
||||||
|
{
|
||||||
|
template<class Content>
|
||||||
|
using thumbnail_url_t = decltype(Content::info.thumbnail_url);
|
||||||
|
template<class T>
|
||||||
|
std::string operator()(const mtx::events::Event<T> &e)
|
||||||
|
{
|
||||||
|
if constexpr (is_detected<thumbnail_url_t, T>::value) {
|
||||||
|
return e.content.info.thumbnail_url;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EventFilename
|
||||||
|
{
|
||||||
|
template<class T>
|
||||||
|
std::string operator()(const mtx::events::Event<T> &)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
std::string operator()(const mtx::events::RoomEvent<mtx::events::msg::Audio> &e)
|
||||||
|
{
|
||||||
|
// body may be the original filename
|
||||||
|
return e.content.body;
|
||||||
|
}
|
||||||
|
std::string operator()(const mtx::events::RoomEvent<mtx::events::msg::Video> &e)
|
||||||
|
{
|
||||||
|
// body may be the original filename
|
||||||
|
return e.content.body;
|
||||||
|
}
|
||||||
|
std::string operator()(const mtx::events::RoomEvent<mtx::events::msg::Image> &e)
|
||||||
|
{
|
||||||
|
// body may be the original filename
|
||||||
|
return e.content.body;
|
||||||
|
}
|
||||||
|
std::string operator()(const mtx::events::RoomEvent<mtx::events::msg::File> &e)
|
||||||
|
{
|
||||||
|
// body may be the original filename
|
||||||
|
if (!e.content.filename.empty())
|
||||||
|
return e.content.filename;
|
||||||
|
return e.content.body;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EventMimeType
|
||||||
|
{
|
||||||
|
template<class Content>
|
||||||
|
using mimetype_t = decltype(Content::info.mimetype);
|
||||||
|
template<class T>
|
||||||
|
std::string operator()(const mtx::events::Event<T> &e)
|
||||||
|
{
|
||||||
|
if constexpr (is_detected<mimetype_t, T>::value) {
|
||||||
|
return e.content.info.mimetype;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EventFilesize
|
||||||
|
{
|
||||||
|
template<class Content>
|
||||||
|
using filesize_t = decltype(Content::info.size);
|
||||||
|
template<class T>
|
||||||
|
int64_t operator()(const mtx::events::RoomEvent<T> &e)
|
||||||
|
{
|
||||||
|
if constexpr (is_detected<filesize_t, T>::value) {
|
||||||
|
return e.content.info.size;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EventInReplyTo
|
||||||
|
{
|
||||||
|
template<class Content>
|
||||||
|
using related_ev_id_t = decltype(Content::relates_to.in_reply_to.event_id);
|
||||||
|
template<class T>
|
||||||
|
std::string operator()(const mtx::events::Event<T> &e)
|
||||||
|
{
|
||||||
|
if constexpr (is_detected<related_ev_id_t, T>::value) {
|
||||||
|
return e.content.relates_to.in_reply_to.event_id;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EventMediaHeight
|
||||||
|
{
|
||||||
|
template<class Content>
|
||||||
|
using h_t = decltype(Content::info.h);
|
||||||
|
template<class T>
|
||||||
|
uint64_t operator()(const mtx::events::Event<T> &e)
|
||||||
|
{
|
||||||
|
if constexpr (is_detected<h_t, T>::value) {
|
||||||
|
return e.content.info.h;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EventMediaWidth
|
||||||
|
{
|
||||||
|
template<class Content>
|
||||||
|
using w_t = decltype(Content::info.w);
|
||||||
|
template<class T>
|
||||||
|
uint64_t operator()(const mtx::events::Event<T> &e)
|
||||||
|
{
|
||||||
|
if constexpr (is_detected<w_t, T>::value) {
|
||||||
|
return e.content.info.w;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
double
|
||||||
|
eventPropHeight(const mtx::events::RoomEvent<T> &e)
|
||||||
|
{
|
||||||
|
auto w = eventWidth(e);
|
||||||
|
if (w == 0)
|
||||||
|
w = 1;
|
||||||
|
|
||||||
|
double prop = eventHeight(e) / (double)w;
|
||||||
|
|
||||||
|
return prop > 0 ? prop : 1.;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
mtx::accessors::event_id(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return std::visit([](const auto e) { return e.event_id; }, event);
|
||||||
|
}
|
||||||
|
std::string
|
||||||
|
mtx::accessors::room_id(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return std::visit([](const auto e) { return e.room_id; }, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
mtx::accessors::sender(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return std::visit([](const auto e) { return e.sender; }, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
QDateTime
|
||||||
|
mtx::accessors::origin_server_ts(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return QDateTime::fromMSecsSinceEpoch(
|
||||||
|
std::visit([](const auto e) { return e.origin_server_ts; }, event));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
mtx::accessors::filename(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return std::visit(EventFilename{}, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
mtx::events::MessageType
|
||||||
|
mtx::accessors::msg_type(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return std::visit(EventMsgType{}, event);
|
||||||
|
}
|
||||||
|
std::string
|
||||||
|
mtx::accessors::room_name(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return std::visit(EventRoomName{}, event);
|
||||||
|
}
|
||||||
|
std::string
|
||||||
|
mtx::accessors::room_topic(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return std::visit(EventRoomTopic{}, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
mtx::accessors::body(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return std::visit(EventBody{}, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
mtx::accessors::formatted_body(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return std::visit(EventFormattedBody{}, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
mtx::accessors::formattedBodyWithFallback(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
auto formatted = formatted_body(event);
|
||||||
|
if (!formatted.empty())
|
||||||
|
return QString::fromStdString(formatted);
|
||||||
|
else
|
||||||
|
return QString::fromStdString(body(event)).toHtmlEscaped().replace("\n", "<br>");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<mtx::crypto::EncryptedFile>
|
||||||
|
mtx::accessors::file(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return std::visit(EventFile{}, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
mtx::accessors::url(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return std::visit(EventUrl{}, event);
|
||||||
|
}
|
||||||
|
std::string
|
||||||
|
mtx::accessors::thumbnail_url(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return std::visit(EventThumbnailUrl{}, event);
|
||||||
|
}
|
||||||
|
std::string
|
||||||
|
mtx::accessors::mimetype(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return std::visit(EventMimeType{}, event);
|
||||||
|
}
|
||||||
|
std::string
|
||||||
|
mtx::accessors::in_reply_to_event(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return std::visit(EventInReplyTo{}, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t
|
||||||
|
mtx::accessors::filesize(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return std::visit(EventFilesize{}, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
mtx::accessors::media_height(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return std::visit(EventMediaHeight{}, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
mtx::accessors::media_width(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return std::visit(EventMediaWidth{}, event);
|
||||||
|
}
|
62
src/EventAccessors.h
Normal file
62
src/EventAccessors.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <mtx/events/collections.hpp>
|
||||||
|
|
||||||
|
namespace mtx::accessors {
|
||||||
|
std::string
|
||||||
|
event_id(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
||||||
|
std::string
|
||||||
|
room_id(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
||||||
|
std::string
|
||||||
|
sender(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
||||||
|
QDateTime
|
||||||
|
origin_server_ts(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
||||||
|
std::string
|
||||||
|
filename(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
||||||
|
mtx::events::MessageType
|
||||||
|
msg_type(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
std::string
|
||||||
|
room_name(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
std::string
|
||||||
|
room_topic(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
||||||
|
std::string
|
||||||
|
body(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
||||||
|
std::string
|
||||||
|
formatted_body(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
||||||
|
QString
|
||||||
|
formattedBodyWithFallback(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
||||||
|
std::optional<mtx::crypto::EncryptedFile>
|
||||||
|
file(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
||||||
|
std::string
|
||||||
|
url(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
std::string
|
||||||
|
thumbnail_url(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
std::string
|
||||||
|
mimetype(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
std::string
|
||||||
|
in_reply_to_event(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
||||||
|
int64_t
|
||||||
|
filesize(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
media_height(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
media_width(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
}
|
@ -9,6 +9,7 @@
|
|||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
|
||||||
#include "ChatPage.h"
|
#include "ChatPage.h"
|
||||||
|
#include "EventAccessors.h"
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "MatrixClient.h"
|
#include "MatrixClient.h"
|
||||||
@ -21,364 +22,100 @@
|
|||||||
Q_DECLARE_METATYPE(QModelIndex)
|
Q_DECLARE_METATYPE(QModelIndex)
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
template<class T>
|
struct RoomEventType
|
||||||
QString
|
|
||||||
eventId(const mtx::events::RoomEvent<T> &event)
|
|
||||||
{
|
{
|
||||||
return QString::fromStdString(event.event_id);
|
template<class T>
|
||||||
}
|
qml_mtx_events::EventType operator()(const mtx::events::Event<T> &e)
|
||||||
template<class T>
|
{
|
||||||
QString
|
using mtx::events::EventType;
|
||||||
roomId(const mtx::events::Event<T> &event)
|
switch (e.type) {
|
||||||
{
|
case EventType::RoomKeyRequest:
|
||||||
return QString::fromStdString(event.room_id);
|
return qml_mtx_events::EventType::KeyRequest;
|
||||||
}
|
case EventType::RoomAliases:
|
||||||
template<class T>
|
return qml_mtx_events::EventType::Aliases;
|
||||||
QString
|
case EventType::RoomAvatar:
|
||||||
senderId(const mtx::events::RoomEvent<T> &event)
|
return qml_mtx_events::EventType::Avatar;
|
||||||
{
|
case EventType::RoomCanonicalAlias:
|
||||||
return QString::fromStdString(event.sender);
|
return qml_mtx_events::EventType::CanonicalAlias;
|
||||||
}
|
case EventType::RoomCreate:
|
||||||
|
return qml_mtx_events::EventType::Create;
|
||||||
template<class T>
|
case EventType::RoomEncrypted:
|
||||||
QDateTime
|
return qml_mtx_events::EventType::Encrypted;
|
||||||
eventTimestamp(const mtx::events::RoomEvent<T> &event)
|
case EventType::RoomEncryption:
|
||||||
{
|
return qml_mtx_events::EventType::Encryption;
|
||||||
return QDateTime::fromMSecsSinceEpoch(event.origin_server_ts);
|
case EventType::RoomGuestAccess:
|
||||||
}
|
return qml_mtx_events::EventType::GuestAccess;
|
||||||
|
case EventType::RoomHistoryVisibility:
|
||||||
template<class T>
|
return qml_mtx_events::EventType::HistoryVisibility;
|
||||||
std::string
|
case EventType::RoomJoinRules:
|
||||||
eventMsgType(const mtx::events::Event<T> &)
|
return qml_mtx_events::EventType::JoinRules;
|
||||||
{
|
case EventType::RoomMember:
|
||||||
return "";
|
return qml_mtx_events::EventType::Member;
|
||||||
}
|
case EventType::RoomMessage:
|
||||||
template<class T>
|
return qml_mtx_events::EventType::UnknownMessage;
|
||||||
auto
|
case EventType::RoomName:
|
||||||
eventMsgType(const mtx::events::RoomEvent<T> &e) -> decltype(e.content.msgtype)
|
return qml_mtx_events::EventType::Name;
|
||||||
{
|
case EventType::RoomPowerLevels:
|
||||||
return e.content.msgtype;
|
return qml_mtx_events::EventType::PowerLevels;
|
||||||
}
|
case EventType::RoomTopic:
|
||||||
|
return qml_mtx_events::EventType::Topic;
|
||||||
template<class T>
|
case EventType::RoomTombstone:
|
||||||
QString
|
return qml_mtx_events::EventType::Tombstone;
|
||||||
eventRoomName(const T &)
|
case EventType::RoomRedaction:
|
||||||
{
|
return qml_mtx_events::EventType::Redaction;
|
||||||
return "";
|
case EventType::RoomPinnedEvents:
|
||||||
}
|
return qml_mtx_events::EventType::PinnedEvents;
|
||||||
QString
|
case EventType::Sticker:
|
||||||
eventRoomName(const mtx::events::StateEvent<mtx::events::state::Name> &e)
|
return qml_mtx_events::EventType::Sticker;
|
||||||
{
|
case EventType::Tag:
|
||||||
return QString::fromStdString(e.content.name);
|
return qml_mtx_events::EventType::Tag;
|
||||||
}
|
case EventType::Unsupported:
|
||||||
|
default:
|
||||||
template<class T>
|
return qml_mtx_events::EventType::Unsupported;
|
||||||
QString
|
}
|
||||||
eventRoomTopic(const T &)
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
QString
|
|
||||||
eventRoomTopic(const mtx::events::StateEvent<mtx::events::state::Topic> &e)
|
|
||||||
{
|
|
||||||
return QString::fromStdString(e.content.topic);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
QString
|
|
||||||
eventBody(const mtx::events::Event<T> &)
|
|
||||||
{
|
|
||||||
return QString("");
|
|
||||||
}
|
|
||||||
template<class T>
|
|
||||||
auto
|
|
||||||
eventBody(const mtx::events::RoomEvent<T> &e)
|
|
||||||
-> std::enable_if_t<std::is_same<decltype(e.content.body), std::string>::value, QString>
|
|
||||||
{
|
|
||||||
return QString::fromStdString(e.content.body);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
QString
|
|
||||||
eventFormattedBody(const mtx::events::Event<T> &)
|
|
||||||
{
|
|
||||||
return QString("");
|
|
||||||
}
|
|
||||||
template<class T>
|
|
||||||
auto
|
|
||||||
eventFormattedBody(const mtx::events::RoomEvent<T> &e)
|
|
||||||
-> std::enable_if_t<std::is_same<decltype(e.content.formatted_body), std::string>::value, QString>
|
|
||||||
{
|
|
||||||
auto temp = e.content.formatted_body;
|
|
||||||
if (!temp.empty()) {
|
|
||||||
return QString::fromStdString(temp);
|
|
||||||
} else {
|
|
||||||
return QString::fromStdString(e.content.body).toHtmlEscaped().replace("\n", "<br>");
|
|
||||||
}
|
}
|
||||||
}
|
qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Audio> &)
|
||||||
|
{
|
||||||
template<class T>
|
return qml_mtx_events::EventType::AudioMessage;
|
||||||
std::optional<mtx::crypto::EncryptedFile>
|
|
||||||
eventEncryptionInfo(const mtx::events::Event<T> &)
|
|
||||||
{
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
auto
|
|
||||||
eventEncryptionInfo(const mtx::events::RoomEvent<T> &e) -> std::enable_if_t<
|
|
||||||
std::is_same<decltype(e.content.file), std::optional<mtx::crypto::EncryptedFile>>::value,
|
|
||||||
std::optional<mtx::crypto::EncryptedFile>>
|
|
||||||
{
|
|
||||||
return e.content.file;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
QString
|
|
||||||
eventUrl(const mtx::events::Event<T> &)
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
QString
|
|
||||||
eventUrl(const mtx::events::StateEvent<mtx::events::state::Avatar> &e)
|
|
||||||
{
|
|
||||||
return QString::fromStdString(e.content.url);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
auto
|
|
||||||
eventUrl(const mtx::events::RoomEvent<T> &e)
|
|
||||||
-> std::enable_if_t<std::is_same<decltype(e.content.url), std::string>::value, QString>
|
|
||||||
{
|
|
||||||
if (e.content.file)
|
|
||||||
return QString::fromStdString(e.content.file->url);
|
|
||||||
return QString::fromStdString(e.content.url);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
QString
|
|
||||||
eventThumbnailUrl(const mtx::events::Event<T> &)
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
template<class T>
|
|
||||||
auto
|
|
||||||
eventThumbnailUrl(const mtx::events::RoomEvent<T> &e)
|
|
||||||
-> std::enable_if_t<std::is_same<decltype(e.content.info.thumbnail_url), std::string>::value,
|
|
||||||
QString>
|
|
||||||
{
|
|
||||||
return QString::fromStdString(e.content.info.thumbnail_url);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
QString
|
|
||||||
eventFilename(const mtx::events::Event<T> &)
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
QString
|
|
||||||
eventFilename(const mtx::events::RoomEvent<mtx::events::msg::Audio> &e)
|
|
||||||
{
|
|
||||||
// body may be the original filename
|
|
||||||
return QString::fromStdString(e.content.body);
|
|
||||||
}
|
|
||||||
QString
|
|
||||||
eventFilename(const mtx::events::RoomEvent<mtx::events::msg::Video> &e)
|
|
||||||
{
|
|
||||||
// body may be the original filename
|
|
||||||
return QString::fromStdString(e.content.body);
|
|
||||||
}
|
|
||||||
QString
|
|
||||||
eventFilename(const mtx::events::RoomEvent<mtx::events::msg::Image> &e)
|
|
||||||
{
|
|
||||||
// body may be the original filename
|
|
||||||
return QString::fromStdString(e.content.body);
|
|
||||||
}
|
|
||||||
QString
|
|
||||||
eventFilename(const mtx::events::RoomEvent<mtx::events::msg::File> &e)
|
|
||||||
{
|
|
||||||
// body may be the original filename
|
|
||||||
if (!e.content.filename.empty())
|
|
||||||
return QString::fromStdString(e.content.filename);
|
|
||||||
return QString::fromStdString(e.content.body);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
auto
|
|
||||||
eventFilesize(const mtx::events::RoomEvent<T> &e) -> decltype(e.content.info.size)
|
|
||||||
{
|
|
||||||
return e.content.info.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
int64_t
|
|
||||||
eventFilesize(const mtx::events::Event<T> &)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
QString
|
|
||||||
eventMimeType(const mtx::events::Event<T> &)
|
|
||||||
{
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
template<class T>
|
|
||||||
auto
|
|
||||||
eventMimeType(const mtx::events::RoomEvent<T> &e)
|
|
||||||
-> std::enable_if_t<std::is_same<decltype(e.content.info.mimetype), std::string>::value, QString>
|
|
||||||
{
|
|
||||||
return QString::fromStdString(e.content.info.mimetype);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
QString
|
|
||||||
eventRelatesTo(const mtx::events::Event<T> &)
|
|
||||||
{
|
|
||||||
return QString();
|
|
||||||
}
|
|
||||||
template<class T>
|
|
||||||
auto
|
|
||||||
eventRelatesTo(const mtx::events::RoomEvent<T> &e) -> std::enable_if_t<
|
|
||||||
std::is_same<decltype(e.content.relates_to.in_reply_to.event_id), std::string>::value,
|
|
||||||
QString>
|
|
||||||
{
|
|
||||||
return QString::fromStdString(e.content.relates_to.in_reply_to.event_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
qml_mtx_events::EventType
|
|
||||||
toRoomEventType(const mtx::events::Event<T> &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 operator()(const mtx::events::Event<mtx::events::msg::Emote> &)
|
||||||
qml_mtx_events::EventType
|
{
|
||||||
toRoomEventType(const mtx::events::Event<mtx::events::msg::Audio> &)
|
return qml_mtx_events::EventType::EmoteMessage;
|
||||||
{
|
}
|
||||||
return qml_mtx_events::EventType::AudioMessage;
|
qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::File> &)
|
||||||
}
|
{
|
||||||
qml_mtx_events::EventType
|
return qml_mtx_events::EventType::FileMessage;
|
||||||
toRoomEventType(const mtx::events::Event<mtx::events::msg::Emote> &)
|
}
|
||||||
{
|
qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Image> &)
|
||||||
return qml_mtx_events::EventType::EmoteMessage;
|
{
|
||||||
}
|
return qml_mtx_events::EventType::ImageMessage;
|
||||||
qml_mtx_events::EventType
|
}
|
||||||
toRoomEventType(const mtx::events::Event<mtx::events::msg::File> &)
|
qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Notice> &)
|
||||||
{
|
{
|
||||||
return qml_mtx_events::EventType::FileMessage;
|
return qml_mtx_events::EventType::NoticeMessage;
|
||||||
}
|
}
|
||||||
qml_mtx_events::EventType
|
qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Text> &)
|
||||||
toRoomEventType(const mtx::events::Event<mtx::events::msg::Image> &)
|
{
|
||||||
{
|
return qml_mtx_events::EventType::TextMessage;
|
||||||
return qml_mtx_events::EventType::ImageMessage;
|
}
|
||||||
}
|
qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Video> &)
|
||||||
qml_mtx_events::EventType
|
{
|
||||||
toRoomEventType(const mtx::events::Event<mtx::events::msg::Notice> &)
|
return qml_mtx_events::EventType::VideoMessage;
|
||||||
{
|
}
|
||||||
return qml_mtx_events::EventType::NoticeMessage;
|
|
||||||
}
|
qml_mtx_events::EventType operator()(const mtx::events::Event<mtx::events::msg::Redacted> &)
|
||||||
qml_mtx_events::EventType
|
{
|
||||||
toRoomEventType(const mtx::events::Event<mtx::events::msg::Text> &)
|
return qml_mtx_events::EventType::Redacted;
|
||||||
{
|
}
|
||||||
return qml_mtx_events::EventType::TextMessage;
|
// ::EventType::Type operator()(const Event<mtx::events::msg::Location> &e) { return
|
||||||
}
|
// ::EventType::LocationMessage; }
|
||||||
qml_mtx_events::EventType
|
};
|
||||||
toRoomEventType(const mtx::events::Event<mtx::events::msg::Video> &)
|
|
||||||
{
|
|
||||||
return qml_mtx_events::EventType::VideoMessage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
qml_mtx_events::EventType
|
qml_mtx_events::EventType
|
||||||
toRoomEventType(const mtx::events::Event<mtx::events::msg::Redacted> &)
|
toRoomEventType(const mtx::events::collections::TimelineEvents &event)
|
||||||
{
|
{
|
||||||
return qml_mtx_events::EventType::Redacted;
|
return std::visit(RoomEventType{}, event);
|
||||||
}
|
|
||||||
// ::EventType::Type toRoomEventType(const Event<mtx::events::msg::Location> &e) { return
|
|
||||||
// ::EventType::LocationMessage; }
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
uint64_t
|
|
||||||
eventHeight(const mtx::events::Event<T> &)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
template<class T>
|
|
||||||
auto
|
|
||||||
eventHeight(const mtx::events::RoomEvent<T> &e) -> decltype(e.content.info.h)
|
|
||||||
{
|
|
||||||
return e.content.info.h;
|
|
||||||
}
|
|
||||||
template<class T>
|
|
||||||
uint64_t
|
|
||||||
eventWidth(const mtx::events::Event<T> &)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
template<class T>
|
|
||||||
auto
|
|
||||||
eventWidth(const mtx::events::RoomEvent<T> &e) -> decltype(e.content.info.w)
|
|
||||||
{
|
|
||||||
return e.content.info.w;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
double
|
|
||||||
eventPropHeight(const mtx::events::RoomEvent<T> &e)
|
|
||||||
{
|
|
||||||
auto w = eventWidth(e);
|
|
||||||
if (w == 0)
|
|
||||||
w = 1;
|
|
||||||
|
|
||||||
double prop = eventHeight(e) / (double)w;
|
|
||||||
|
|
||||||
return prop > 0 ? prop : 1.;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObject *parent)
|
TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObject *parent)
|
||||||
@ -477,6 +214,8 @@ TimelineModel::rowCount(const QModelIndex &parent) const
|
|||||||
QVariant
|
QVariant
|
||||||
TimelineModel::data(const QModelIndex &index, int role) const
|
TimelineModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
|
using namespace mtx::accessors;
|
||||||
|
namespace acc = mtx::accessors;
|
||||||
if (index.row() < 0 && index.row() >= (int)eventOrder.size())
|
if (index.row() < 0 && index.row() >= (int)eventOrder.size())
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
@ -491,86 +230,71 @@ TimelineModel::data(const QModelIndex &index, int role) const
|
|||||||
|
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case Section: {
|
case Section: {
|
||||||
QDateTime date =
|
QDateTime date = origin_server_ts(event);
|
||||||
std::visit([](const auto &e) -> QDateTime { return eventTimestamp(e); }, event);
|
|
||||||
date.setTime(QTime());
|
date.setTime(QTime());
|
||||||
|
|
||||||
QString userId =
|
std::string userId = acc::sender(event);
|
||||||
std::visit([](const auto &e) -> QString { return senderId(e); }, event);
|
|
||||||
|
|
||||||
for (int r = index.row() - 1; r > 0; r--) {
|
for (int r = index.row() - 1; r > 0; r--) {
|
||||||
auto tempEv = events.value(eventOrder[r]);
|
auto tempEv = events.value(eventOrder[r]);
|
||||||
QDateTime prevDate = std::visit(
|
QDateTime prevDate = origin_server_ts(tempEv);
|
||||||
[](const auto &e) -> QDateTime { return eventTimestamp(e); }, tempEv);
|
|
||||||
prevDate.setTime(QTime());
|
prevDate.setTime(QTime());
|
||||||
if (prevDate != date)
|
if (prevDate != date)
|
||||||
return QString("%2 %1").arg(date.toMSecsSinceEpoch()).arg(userId);
|
return QString("%2 %1")
|
||||||
|
.arg(date.toMSecsSinceEpoch())
|
||||||
|
.arg(QString::fromStdString(userId));
|
||||||
|
|
||||||
QString prevUserId =
|
std::string prevUserId = acc::sender(tempEv);
|
||||||
std::visit([](const auto &e) -> QString { return senderId(e); }, tempEv);
|
|
||||||
if (userId != prevUserId)
|
if (userId != prevUserId)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return QString("%1").arg(userId);
|
return QString("%1").arg(QString::fromStdString(userId));
|
||||||
}
|
}
|
||||||
case UserId:
|
case UserId:
|
||||||
return QVariant(
|
return QVariant(QString::fromStdString(acc::sender(event)));
|
||||||
std::visit([](const auto &e) -> QString { return senderId(e); }, event));
|
|
||||||
case UserName:
|
case UserName:
|
||||||
return QVariant(displayName(
|
return QVariant(displayName(QString::fromStdString(acc::sender(event))));
|
||||||
std::visit([](const auto &e) -> QString { return senderId(e); }, event)));
|
|
||||||
|
|
||||||
case Timestamp:
|
case Timestamp:
|
||||||
return QVariant(
|
return QVariant(origin_server_ts(event));
|
||||||
std::visit([](const auto &e) -> QDateTime { return eventTimestamp(e); }, event));
|
|
||||||
case Type:
|
case Type:
|
||||||
return QVariant(std::visit(
|
return QVariant(toRoomEventType(event));
|
||||||
[](const auto &e) -> qml_mtx_events::EventType { return toRoomEventType(e); },
|
|
||||||
event));
|
|
||||||
case Body:
|
case Body:
|
||||||
return QVariant(utils::replaceEmoji(
|
return QVariant(utils::replaceEmoji(QString::fromStdString(body(event))));
|
||||||
std::visit([](const auto &e) -> QString { return eventBody(e); }, event)));
|
|
||||||
case FormattedBody:
|
case FormattedBody:
|
||||||
return QVariant(
|
return QVariant(
|
||||||
utils::replaceEmoji(
|
utils::replaceEmoji(utils::linkifyMessage(formattedBodyWithFallback(event)))
|
||||||
utils::linkifyMessage(std::visit(
|
|
||||||
[](const auto &e) -> QString { return eventFormattedBody(e); }, event)))
|
|
||||||
.remove("<mx-reply>")
|
.remove("<mx-reply>")
|
||||||
.remove("</mx-reply>"));
|
.remove("</mx-reply>"));
|
||||||
case Url:
|
case Url:
|
||||||
return QVariant(
|
return QVariant(QString::fromStdString(url(event)));
|
||||||
std::visit([](const auto &e) -> QString { return eventUrl(e); }, event));
|
|
||||||
case ThumbnailUrl:
|
case ThumbnailUrl:
|
||||||
return QVariant(
|
return QVariant(QString::fromStdString(thumbnail_url(event)));
|
||||||
std::visit([](const auto &e) -> QString { return eventThumbnailUrl(e); }, event));
|
|
||||||
case Filename:
|
case Filename:
|
||||||
return QVariant(
|
return QVariant(QString::fromStdString(filename(event)));
|
||||||
std::visit([](const auto &e) -> QString { return eventFilename(e); }, event));
|
|
||||||
case Filesize:
|
case Filesize:
|
||||||
return QVariant(std::visit(
|
return QVariant(utils::humanReadableFileSize(filesize(event)));
|
||||||
[](const auto &e) -> QString {
|
|
||||||
return utils::humanReadableFileSize(eventFilesize(e));
|
|
||||||
},
|
|
||||||
event));
|
|
||||||
case MimeType:
|
case MimeType:
|
||||||
return QVariant(
|
return QVariant(QString::fromStdString(mimetype(event)));
|
||||||
std::visit([](const auto &e) -> QString { return eventMimeType(e); }, event));
|
|
||||||
case Height:
|
case Height:
|
||||||
return QVariant(
|
return QVariant(qulonglong{media_height(event)});
|
||||||
std::visit([](const auto &e) -> qulonglong { return eventHeight(e); }, event));
|
|
||||||
case Width:
|
case Width:
|
||||||
return QVariant(
|
return QVariant(qulonglong{media_width(event)});
|
||||||
std::visit([](const auto &e) -> qulonglong { return eventWidth(e); }, event));
|
case ProportionalHeight: {
|
||||||
case ProportionalHeight:
|
auto w = media_width(event);
|
||||||
return QVariant(
|
if (w == 0)
|
||||||
std::visit([](const auto &e) -> double { return eventPropHeight(e); }, event));
|
w = 1;
|
||||||
|
|
||||||
|
double prop = media_height(event) / (double)w;
|
||||||
|
|
||||||
|
return QVariant(prop > 0 ? prop : 1.);
|
||||||
|
}
|
||||||
case Id:
|
case Id:
|
||||||
return id;
|
return id;
|
||||||
case State:
|
case State:
|
||||||
// only show read receipts for messages not from us
|
// only show read receipts for messages not from us
|
||||||
if (std::visit([](const auto &e) -> QString { return senderId(e); }, event)
|
if (acc::sender(event) != http::client()->user_id().to_string())
|
||||||
.toStdString() != http::client()->user_id().to_string())
|
|
||||||
return qml_mtx_events::Empty;
|
return qml_mtx_events::Empty;
|
||||||
else if (failed.contains(id))
|
else if (failed.contains(id))
|
||||||
return qml_mtx_events::Failed;
|
return qml_mtx_events::Failed;
|
||||||
@ -581,21 +305,15 @@ TimelineModel::data(const QModelIndex &index, int role) const
|
|||||||
else
|
else
|
||||||
return qml_mtx_events::Received;
|
return qml_mtx_events::Received;
|
||||||
case IsEncrypted: {
|
case IsEncrypted: {
|
||||||
auto tempEvent = events[id];
|
|
||||||
return std::holds_alternative<
|
return std::holds_alternative<
|
||||||
mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(tempEvent);
|
mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(events[id]);
|
||||||
}
|
|
||||||
case ReplyTo: {
|
|
||||||
QString evId =
|
|
||||||
std::visit([](const auto &e) -> QString { return eventRelatesTo(e); }, event);
|
|
||||||
return QVariant(evId);
|
|
||||||
}
|
}
|
||||||
|
case ReplyTo:
|
||||||
|
return QVariant(QString::fromStdString(in_reply_to_event(event)));
|
||||||
case RoomName:
|
case RoomName:
|
||||||
return QVariant(
|
return QVariant(QString::fromStdString(room_name(event)));
|
||||||
std::visit([](const auto &e) -> QString { return eventRoomName(e); }, event));
|
|
||||||
case RoomTopic:
|
case RoomTopic:
|
||||||
return QVariant(
|
return QVariant(QString::fromStdString(room_topic(event)));
|
||||||
std::visit([](const auto &e) -> QString { return eventRoomTopic(e); }, event));
|
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
@ -667,7 +385,7 @@ TimelineModel::internalAddEvents(
|
|||||||
{
|
{
|
||||||
std::vector<QString> ids;
|
std::vector<QString> ids;
|
||||||
for (auto e : timeline) {
|
for (auto e : timeline) {
|
||||||
QString id = std::visit([](const auto &e) -> QString { return eventId(e); }, e);
|
QString id = QString::fromStdString(mtx::accessors::event_id(e));
|
||||||
|
|
||||||
if (this->events.contains(id)) {
|
if (this->events.contains(id)) {
|
||||||
this->events.insert(id, e);
|
this->events.insert(id, e);
|
||||||
@ -708,11 +426,7 @@ TimelineModel::internalAddEvents(
|
|||||||
std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(&e)) {
|
std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(&e)) {
|
||||||
e = decryptEvent(*event).event;
|
e = decryptEvent(*event).event;
|
||||||
}
|
}
|
||||||
auto encInfo = std::visit(
|
auto encInfo = mtx::accessors::file(e);
|
||||||
[](const auto &ev) -> std::optional<mtx::crypto::EncryptedFile> {
|
|
||||||
return eventEncryptionInfo(ev);
|
|
||||||
},
|
|
||||||
e);
|
|
||||||
|
|
||||||
if (encInfo)
|
if (encInfo)
|
||||||
emit newEncryptedImage(encInfo.value());
|
emit newEncryptedImage(encInfo.value());
|
||||||
@ -950,25 +664,18 @@ TimelineModel::replyAction(QString id)
|
|||||||
event = decryptEvent(*e).event;
|
event = decryptEvent(*e).event;
|
||||||
}
|
}
|
||||||
|
|
||||||
RelatedInfo related = std::visit(
|
RelatedInfo related = {};
|
||||||
[](const auto &ev) -> RelatedInfo {
|
related.quoted_user = QString::fromStdString(mtx::accessors::sender(event));
|
||||||
RelatedInfo related_ = {};
|
related.related_event = mtx::accessors::event_id(event);
|
||||||
related_.quoted_user = QString::fromStdString(ev.sender);
|
related.type = mtx::accessors::msg_type(event);
|
||||||
related_.related_event = ev.event_id;
|
related.quoted_body = mtx::accessors::formattedBodyWithFallback(event);
|
||||||
return related_;
|
|
||||||
},
|
|
||||||
event);
|
|
||||||
related.type = mtx::events::getMessageType(
|
|
||||||
std::visit([](const auto &e) -> std::string { return eventMsgType(e); }, event));
|
|
||||||
related.quoted_body =
|
|
||||||
std::visit([](const auto &e) -> QString { return eventFormattedBody(e); }, event);
|
|
||||||
related.quoted_body.remove(QRegularExpression(
|
related.quoted_body.remove(QRegularExpression(
|
||||||
"<mx-reply>.*</mx-reply>", QRegularExpression::DotMatchesEverythingOption));
|
"<mx-reply>.*</mx-reply>", QRegularExpression::DotMatchesEverythingOption));
|
||||||
nhlog::ui()->debug("after replacement: {}", related.quoted_body.toStdString());
|
nhlog::ui()->debug("after replacement: {}", related.quoted_body.toStdString());
|
||||||
related.room = room_id_;
|
related.room = room_id_;
|
||||||
|
|
||||||
if (related.quoted_body.isEmpty())
|
// if (related.quoted_body.isEmpty())
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
ChatPage::instance()->messageReply(related);
|
ChatPage::instance()->messageReply(related);
|
||||||
}
|
}
|
||||||
@ -1412,8 +1119,7 @@ TimelineModel::addPendingMessage(mtx::events::collections::TimelineEvents event)
|
|||||||
|
|
||||||
internalAddEvents({event});
|
internalAddEvents({event});
|
||||||
|
|
||||||
QString txn_id_qstr =
|
QString txn_id_qstr = QString::fromStdString(mtx::accessors::event_id(event));
|
||||||
std::visit([](const auto &e) -> QString { return eventId(e); }, event);
|
|
||||||
beginInsertRows(QModelIndex(),
|
beginInsertRows(QModelIndex(),
|
||||||
static_cast<int>(this->eventOrder.size()),
|
static_cast<int>(this->eventOrder.size()),
|
||||||
static_cast<int>(this->eventOrder.size()));
|
static_cast<int>(this->eventOrder.size()));
|
||||||
@ -1436,18 +1142,13 @@ TimelineModel::saveMedia(QString eventId) const
|
|||||||
event = decryptEvent(*e).event;
|
event = decryptEvent(*e).event;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString mxcUrl = std::visit([](const auto &e) -> QString { return eventUrl(e); }, event);
|
QString mxcUrl = QString::fromStdString(mtx::accessors::url(event));
|
||||||
QString originalFilename =
|
QString originalFilename = QString::fromStdString(mtx::accessors::filename(event));
|
||||||
std::visit([](const auto &e) -> QString { return eventFilename(e); }, event);
|
QString mimeType = QString::fromStdString(mtx::accessors::mimetype(event));
|
||||||
QString mimeType =
|
|
||||||
std::visit([](const auto &e) -> QString { return eventMimeType(e); }, event);
|
|
||||||
|
|
||||||
using EncF = std::optional<mtx::crypto::EncryptedFile>;
|
auto encryptionInfo = mtx::accessors::file(event);
|
||||||
EncF encryptionInfo =
|
|
||||||
std::visit([](const auto &e) -> EncF { return eventEncryptionInfo(e); }, event);
|
|
||||||
|
|
||||||
qml_mtx_events::EventType eventType = std::visit(
|
qml_mtx_events::EventType eventType = toRoomEventType(event);
|
||||||
[](const auto &e) -> qml_mtx_events::EventType { return toRoomEventType(e); }, event);
|
|
||||||
|
|
||||||
QString dialogTitle;
|
QString dialogTitle;
|
||||||
if (eventType == qml_mtx_events::EventType::ImageMessage) {
|
if (eventType == qml_mtx_events::EventType::ImageMessage) {
|
||||||
@ -1513,13 +1214,11 @@ TimelineModel::cacheMedia(QString eventId)
|
|||||||
event = decryptEvent(*e).event;
|
event = decryptEvent(*e).event;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString mxcUrl = std::visit([](const auto &e) -> QString { return eventUrl(e); }, event);
|
QString mxcUrl = QString::fromStdString(mtx::accessors::url(event));
|
||||||
QString mimeType =
|
QString originalFilename = QString::fromStdString(mtx::accessors::filename(event));
|
||||||
std::visit([](const auto &e) -> QString { return eventMimeType(e); }, event);
|
QString mimeType = QString::fromStdString(mtx::accessors::mimetype(event));
|
||||||
|
|
||||||
using EncF = std::optional<mtx::crypto::EncryptedFile>;
|
auto encryptionInfo = mtx::accessors::file(event);
|
||||||
EncF encryptionInfo =
|
|
||||||
std::visit([](const auto &e) -> EncF { return eventEncryptionInfo(e); }, event);
|
|
||||||
|
|
||||||
// If the message is a link to a non mxcUrl, don't download it
|
// If the message is a link to a non mxcUrl, don't download it
|
||||||
if (!mxcUrl.startsWith("mxc://")) {
|
if (!mxcUrl.startsWith("mxc://")) {
|
||||||
|
Loading…
Reference in New Issue
Block a user