summary refs log tree commit diff
path: root/src/timeline/TimelineModel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/timeline/TimelineModel.cpp')
-rw-r--r--src/timeline/TimelineModel.cpp235
1 files changed, 157 insertions, 78 deletions
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); }