diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index dc5eb8cc..aea2645a 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -160,6 +160,26 @@ struct RoomEventType
{
return qml_mtx_events::EventType::Redacted;
}
+ qml_mtx_events::EventType operator()(
+ const mtx::events::Event<mtx::events::msg::CallInvite> &)
+ {
+ return qml_mtx_events::EventType::CallInvite;
+ }
+ qml_mtx_events::EventType operator()(
+ const mtx::events::Event<mtx::events::msg::CallAnswer> &)
+ {
+ return qml_mtx_events::EventType::CallAnswer;
+ }
+ qml_mtx_events::EventType operator()(
+ const mtx::events::Event<mtx::events::msg::CallHangUp> &)
+ {
+ return qml_mtx_events::EventType::CallHangUp;
+ }
+ qml_mtx_events::EventType operator()(
+ const mtx::events::Event<mtx::events::msg::CallCandidates> &)
+ {
+ return qml_mtx_events::EventType::CallCandidates;
+ }
// ::EventType::Type operator()(const Event<mtx::events::msg::Location> &e) { return
// ::EventType::LocationMessage; }
};
@@ -271,6 +291,7 @@ TimelineModel::roleNames() const
{RoomId, "roomId"},
{RoomName, "roomName"},
{RoomTopic, "roomTopic"},
+ {CallType, "callType"},
{Dump, "dump"},
};
}
@@ -422,6 +443,8 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
return QVariant(QString::fromStdString(room_name(event)));
case RoomTopic:
return QVariant(QString::fromStdString(room_topic(event)));
+ case CallType:
+ return QVariant(QString::fromStdString(call_type(event)));
case Dump: {
QVariantMap m;
auto names = roleNames();
@@ -452,6 +475,7 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
m.insert(names[ReplyTo], data(event, static_cast<int>(ReplyTo)));
m.insert(names[RoomName], data(event, static_cast<int>(RoomName)));
m.insert(names[RoomTopic], data(event, static_cast<int>(RoomTopic)));
+ m.insert(names[CallType], data(event, static_cast<int>(CallType)));
return QVariant(m);
}
@@ -548,8 +572,32 @@ TimelineModel::addEvents(const mtx::responses::Timeline &timeline)
events.handleSync(timeline);
- if (!timeline.events.empty())
- updateLastMessage();
+ using namespace mtx::events;
+ for (auto e : timeline.events) {
+ if (auto encryptedEvent = std::get_if<EncryptedEvent<msg::Encrypted>>(&e)) {
+ MegolmSessionIndex index;
+ index.room_id = room_id_.toStdString();
+ index.session_id = encryptedEvent->content.session_id;
+ index.sender_key = encryptedEvent->content.sender_key;
+
+ auto result = olm::decryptEvent(index, *encryptedEvent);
+ if (result.event)
+ e = result.event.value();
+ }
+
+ if (std::holds_alternative<RoomEvent<msg::CallCandidates>>(e) ||
+ std::holds_alternative<RoomEvent<msg::CallInvite>>(e) ||
+ std::holds_alternative<RoomEvent<msg::CallAnswer>>(e) ||
+ std::holds_alternative<RoomEvent<msg::CallHangUp>>(e))
+ std::visit(
+ [this](auto &event) {
+ event.room_id = room_id_.toStdString();
+ if (event.sender != http::client()->user_id().to_string())
+ emit newCallEvent(event);
+ },
+ e);
+ }
+ updateLastMessage();
}
template<typename T>
@@ -574,6 +622,23 @@ isMessage(const mtx::events::EncryptedEvent<T> &)
return true;
}
+auto
+isMessage(const mtx::events::RoomEvent<mtx::events::msg::CallInvite> &)
+{
+ return true;
+}
+
+auto
+isMessage(const mtx::events::RoomEvent<mtx::events::msg::CallAnswer> &)
+{
+ return true;
+}
+auto
+isMessage(const mtx::events::RoomEvent<mtx::events::msg::CallHangUp> &)
+{
+ return true;
+}
+
// Workaround. We also want to see a room at the top, if we just joined it
auto
isYourJoin(const mtx::events::StateEvent<mtx::events::state::Member> &e)
@@ -806,15 +871,16 @@ TimelineModel::markEventsAsRead(const std::vector<QString> &event_ids)
template<typename T>
void
-TimelineModel::sendEncryptedMessage(mtx::events::RoomEvent<T> msg)
+TimelineModel::sendEncryptedMessage(mtx::events::RoomEvent<T> msg, mtx::events::EventType eventType)
{
const auto room_id = room_id_.toStdString();
using namespace mtx::events;
using namespace mtx::identifiers;
- json doc = {
- {"type", to_string(msg.type)}, {"content", json(msg.content)}, {"room_id", room_id}};
+ json doc = {{"type", mtx::events::to_string(eventType)},
+ {"content", msg.content},
+ {"room_id", room_id}};
try {
// Check if we have already an outbound megolm session then we can use.
@@ -1093,69 +1159,115 @@ struct SendMessageVisitor
: model_(model)
{}
- void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &msg)
+ template<typename T, mtx::events::EventType Event>
+ void sendRoomEvent(mtx::events::RoomEvent<T> msg)
{
- model_->sendEncryptedMessage(msg);
+ if (cache::isRoomEncrypted(model_->room_id_.toStdString())) {
+ auto encInfo = mtx::accessors::file(msg);
+ if (encInfo)
+ emit model_->newEncryptedImage(encInfo.value());
+
+ model_->sendEncryptedMessage(msg, Event);
+ } else {
+ msg.type = Event;
+ emit model_->addPendingMessageToStore(msg);
+ }
}
- void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationReady> &msg)
+
+ // Do-nothing operator for all unhandled events
+ template<typename T>
+ void operator()(const mtx::events::Event<T> &)
+ {}
+
+ // Operator for m.room.message events that contain a msgtype in their content
+ template<typename T,
+ std::enable_if_t<std::is_same<decltype(T::msgtype), std::string>::value, int> = 0>
+ void operator()(mtx::events::RoomEvent<T> msg)
{
- model_->sendEncryptedMessage(msg);
+ sendRoomEvent<T, mtx::events::EventType::RoomMessage>(msg);
}
- void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationStart> &msg)
+
+ // Special operator for reactions, which are a type of m.room.message, but need to be
+ // handled distinctly for their differences from normal room messages. Specifically,
+ // reactions need to have the relation outside of ciphertext, or synapse / the homeserver
+ // cannot handle it correctly. See the MSC for more details:
+ // https://github.com/matrix-org/matrix-doc/blob/matthew/msc1849/proposals/1849-aggregations.md#end-to-end-encryption
+ void operator()(mtx::events::RoomEvent<mtx::events::msg::Reaction> msg)
{
- model_->sendEncryptedMessage(msg);
+ msg.type = mtx::events::EventType::Reaction;
+ emit model_->addPendingMessageToStore(msg);
}
- void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationAccept> &msg)
+
+ void operator()(const mtx::events::RoomEvent<mtx::events::msg::CallInvite> &event)
{
- model_->sendEncryptedMessage(msg);
+ sendRoomEvent<mtx::events::msg::CallInvite, mtx::events::EventType::CallInvite>(
+ event);
}
- void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationMac> &msg)
+
+ void operator()(const mtx::events::RoomEvent<mtx::events::msg::CallCandidates> &event)
{
- model_->sendEncryptedMessage(msg);
+ sendRoomEvent<mtx::events::msg::CallCandidates,
+ mtx::events::EventType::CallCandidates>(event);
}
- void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationKey> &msg)
+
+ void operator()(const mtx::events::RoomEvent<mtx::events::msg::CallAnswer> &event)
{
- model_->sendEncryptedMessage(msg);
+ sendRoomEvent<mtx::events::msg::CallAnswer, mtx::events::EventType::CallAnswer>(
+ event);
}
- void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationDone> &msg)
+
+ void operator()(const mtx::events::RoomEvent<mtx::events::msg::CallHangUp> &event)
{
- model_->sendEncryptedMessage(msg);
+ sendRoomEvent<mtx::events::msg::CallHangUp, mtx::events::EventType::CallHangUp>(
+ event);
}
- void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationCancel> &msg)
+
+ void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &msg)
{
- model_->sendEncryptedMessage(msg);
+ sendRoomEvent<mtx::events::msg::KeyVerificationRequest,
+ mtx::events::EventType::RoomMessage>(msg);
}
- // Do-nothing operator for all unhandled events
- template<typename T>
- void operator()(const mtx::events::Event<T> &)
- {}
- // Operator for m.room.message events that contain a msgtype in their content
- template<typename T,
- std::enable_if_t<std::is_same<decltype(T::msgtype), std::string>::value, int> = 0>
- void operator()(const mtx::events::RoomEvent<T> &msg)
+ void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationReady> &msg)
+ {
+ sendRoomEvent<mtx::events::msg::KeyVerificationReady,
+ mtx::events::EventType::KeyVerificationReady>(msg);
+ }
+ void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationStart> &msg)
{
- if (cache::isRoomEncrypted(model_->room_id_.toStdString())) {
- auto encInfo = mtx::accessors::file(msg);
- if (encInfo)
- emit model_->newEncryptedImage(encInfo.value());
+ sendRoomEvent<mtx::events::msg::KeyVerificationStart,
+ mtx::events::EventType::KeyVerificationStart>(msg);
+ }
- model_->sendEncryptedMessage(msg);
- } else {
- emit model_->addPendingMessageToStore(msg);
- }
+ void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationAccept> &msg)
+ {
+ sendRoomEvent<mtx::events::msg::KeyVerificationAccept,
+ mtx::events::EventType::KeyVerificationAccept>(msg);
}
- // Special operator for reactions, which are a type of m.room.message, but need to be
- // handled distinctly for their differences from normal room messages. Specifically,
- // reactions need to have the relation outside of ciphertext, or synapse / the homeserver
- // cannot handle it correctly. See the MSC for more details:
- // https://github.com/matrix-org/matrix-doc/blob/matthew/msc1849/proposals/1849-aggregations.md#end-to-end-encryption
- void operator()(mtx::events::RoomEvent<mtx::events::msg::Reaction> msg)
+ void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationMac> &msg)
{
- msg.type = mtx::events::EventType::Reaction;
- emit model_->addPendingMessageToStore(msg);
+ sendRoomEvent<mtx::events::msg::KeyVerificationMac,
+ mtx::events::EventType::KeyVerificationMac>(msg);
+ }
+
+ void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationKey> &msg)
+ {
+ sendRoomEvent<mtx::events::msg::KeyVerificationKey,
+ mtx::events::EventType::KeyVerificationKey>(msg);
+ }
+
+ void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationDone> &msg)
+ {
+ sendRoomEvent<mtx::events::msg::KeyVerificationDone,
+ mtx::events::EventType::KeyVerificationDone>(msg);
+ }
+
+ void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationCancel> &msg)
+ {
+ sendRoomEvent<mtx::events::msg::KeyVerificationCancel,
+ mtx::events::EventType::KeyVerificationCancel>(msg);
}
TimelineModel *model_;
@@ -1173,39 +1285,6 @@ TimelineModel::addPendingMessage(mtx::events::collections::TimelineEvents event)
},
event);
- if (std::get_if<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationReady>>(&event)) {
- std::visit(
- [](auto &msg) { msg.type = mtx::events::EventType::KeyVerificationReady; },
- event);
- }
- if (std::get_if<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationStart>>(&event)) {
- std::visit(
- [](auto &msg) { msg.type = mtx::events::EventType::KeyVerificationStart; },
- event);
- }
- if (std::get_if<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationKey>>(&event)) {
- std::visit([](auto &msg) { msg.type = mtx::events::EventType::KeyVerificationKey; },
- event);
- }
- if (std::get_if<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationMac>>(&event)) {
- std::visit([](auto &msg) { msg.type = mtx::events::EventType::KeyVerificationMac; },
- event);
- }
- if (std::get_if<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationDone>>(&event)) {
- std::visit(
- [](auto &msg) { msg.type = mtx::events::EventType::KeyVerificationDone; }, event);
- }
- if (std::get_if<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationCancel>>(&event)) {
- std::visit(
- [](auto &msg) { msg.type = mtx::events::EventType::KeyVerificationCancel; },
- event);
- }
- if (std::get_if<mtx::events::RoomEvent<mtx::events::msg::KeyVerificationAccept>>(&event)) {
- std::visit(
- [](auto &msg) { msg.type = mtx::events::EventType::KeyVerificationAccept; },
- event);
- }
-
std::visit(SendMessageVisitor{this}, event);
}
|