summary refs log tree commit diff
path: root/src/timeline/TimelineModel.cpp
diff options
context:
space:
mode:
authorCH Chethan Reddy <40890937+Chethan2k1@users.noreply.github.com>2020-08-09 08:35:15 +0530
committerCH Chethan Reddy <40890937+Chethan2k1@users.noreply.github.com>2020-08-09 08:35:15 +0530
commit2e20049b3695d0aa7ca09db079bcc39c0485d098 (patch)
tree664dfdabdd940f217fac4d55c55e9f47358036ee /src/timeline/TimelineModel.cpp
parentAdd Room Verification Messages (diff)
downloadnheko-2e20049b3695d0aa7ca09db079bcc39c0485d098.tar.xz
[WIP] Room-Verification Messages
Diffstat (limited to 'src/timeline/TimelineModel.cpp')
-rw-r--r--src/timeline/TimelineModel.cpp333
1 files changed, 85 insertions, 248 deletions
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index adf207ac..809fe382 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -186,12 +186,11 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
   , room_id_(room_id)
   , manager_(manager)
 {
-        connect(
-          this,
-          &TimelineModel::redactionFailed,
-          this,
-          [](const QString &msg) { emit ChatPage::instance()->showNotification(msg); },
-          Qt::QueuedConnection);
+        connect(this,
+                &TimelineModel::redactionFailed,
+                this,
+                [](const QString &msg) { emit ChatPage::instance()->showNotification(msg); },
+                Qt::QueuedConnection);
 
         connect(this,
                 &TimelineModel::newMessageToSend,
@@ -200,17 +199,17 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
                 Qt::QueuedConnection);
         connect(this, &TimelineModel::addPendingMessageToStore, &events, &EventStore::addPending);
 
-        connect(
-          &events,
-          &EventStore::dataChanged,
-          this,
-          [this](int from, int to) {
-                  nhlog::ui()->debug(
-                    "data changed {} to {}", events.size() - to - 1, events.size() - from - 1);
-                  emit dataChanged(index(events.size() - to - 1, 0),
-                                   index(events.size() - from - 1, 0));
-          },
-          Qt::QueuedConnection);
+        connect(&events,
+                &EventStore::dataChanged,
+                this,
+                [this](int from, int to) {
+                        nhlog::ui()->debug("data changed {} to {}",
+                                           events.size() - to - 1,
+                                           events.size() - from - 1);
+                        emit dataChanged(index(events.size() - to - 1, 0),
+                                         index(events.size() - from - 1, 0));
+                },
+                Qt::QueuedConnection);
 
         connect(&events, &EventStore::beginInsertRows, this, [this](int from, int to) {
                 int first = events.size() - to;
@@ -232,6 +231,12 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
         connect(&events, &EventStore::newEncryptedImage, this, &TimelineModel::newEncryptedImage);
         connect(
           &events, &EventStore::fetchedMore, this, [this]() { setPaginationInProgress(false); });
+        connect(&events,
+                &EventStore::startDMVerification,
+                this,
+                [this](mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> msg) {
+                        ChatPage::instance()->recievedRoomDeviceVerificationRequest(msg, this);
+                });
 }
 
 QHash<int, QByteArray>
@@ -613,187 +618,6 @@ TimelineModel::updateLastMessage()
         }
 }
 
-std::vector<QString>
-TimelineModel::internalAddEvents(
-  const std::vector<mtx::events::collections::TimelineEvents> &timeline)
-{
-        std::vector<QString> ids;
-        for (auto e : timeline) {
-                QString id = QString::fromStdString(mtx::accessors::event_id(e));
-
-                if (this->events.contains(id)) {
-                        this->events.insert(id, e);
-                        int idx = idToIndex(id);
-                        emit dataChanged(index(idx, 0), index(idx, 0));
-                        continue;
-                }
-
-                QString txid = QString::fromStdString(mtx::accessors::transaction_id(e));
-                if (this->pending.removeOne(txid)) {
-                        this->events.insert(id, e);
-                        this->events.remove(txid);
-                        int idx = idToIndex(txid);
-                        if (idx < 0) {
-                                nhlog::ui()->warn("Received index out of range");
-                                continue;
-                        }
-                        eventOrder[idx] = id;
-                        emit dataChanged(index(idx, 0), index(idx, 0));
-                        continue;
-                }
-
-                if (auto redaction =
-                      std::get_if<mtx::events::RedactionEvent<mtx::events::msg::Redaction>>(&e)) {
-                        QString redacts = QString::fromStdString(redaction->redacts);
-                        auto redacted   = std::find(eventOrder.begin(), eventOrder.end(), redacts);
-
-                        auto event = events.value(redacts);
-                        if (auto reaction =
-                              std::get_if<mtx::events::RoomEvent<mtx::events::msg::Reaction>>(
-                                &event)) {
-                                QString reactedTo =
-                                  QString::fromStdString(reaction->content.relates_to.event_id);
-                                reactions[reactedTo].removeReaction(*reaction);
-                                int idx = idToIndex(reactedTo);
-                                if (idx >= 0)
-                                        emit dataChanged(index(idx, 0), index(idx, 0));
-                        }
-
-                        if (redacted != eventOrder.end()) {
-                                auto redactedEvent = std::visit(
-                                  [](const auto &ev)
-                                    -> mtx::events::RoomEvent<mtx::events::msg::Redacted> {
-                                          mtx::events::RoomEvent<mtx::events::msg::Redacted>
-                                            replacement                = {};
-                                          replacement.event_id         = ev.event_id;
-                                          replacement.room_id          = ev.room_id;
-                                          replacement.sender           = ev.sender;
-                                          replacement.origin_server_ts = ev.origin_server_ts;
-                                          replacement.type             = ev.type;
-                                          return replacement;
-                                  },
-                                  e);
-                                events.insert(redacts, redactedEvent);
-
-                                int row = (int)std::distance(eventOrder.begin(), redacted);
-                                emit dataChanged(index(row, 0), index(row, 0));
-                        }
-
-                        continue; // don't insert redaction into timeline
-                }
-
-                if (auto reaction =
-                      std::get_if<mtx::events::RoomEvent<mtx::events::msg::Reaction>>(&e)) {
-                        QString reactedTo =
-                          QString::fromStdString(reaction->content.relates_to.event_id);
-                        events.insert(id, e);
-
-                        // remove local echo
-                        if (!txid.isEmpty()) {
-                                auto rCopy     = *reaction;
-                                rCopy.event_id = txid.toStdString();
-                                reactions[reactedTo].removeReaction(rCopy);
-                        }
-
-                        reactions[reactedTo].addReaction(room_id_.toStdString(), *reaction);
-                        int idx = idToIndex(reactedTo);
-                        if (idx >= 0)
-                                emit dataChanged(index(idx, 0), index(idx, 0));
-                        continue; // don't insert reaction into timeline
-                }
-
-                if (auto event =
-                      std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(&e)) {
-                        auto e_      = decryptEvent(*event).event;
-                        auto encInfo = mtx::accessors::file(e_);
-
-                        if (encInfo)
-                                emit newEncryptedImage(encInfo.value());
-
-                        if (auto msg = std::get_if<
-                              mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest>>(
-                              &e_)) {
-                                last_verification_request_event = *msg;
-                        }
-
-                        if (auto msg = std::get_if<
-                              mtx::events::RoomEvent<mtx::events::msg::KeyVerificationCancel>>(
-                              &e_)) {
-                                last_verification_cancel_event = *msg;
-                                ChatPage::instance()->recievedDeviceVerificationCancel(
-                                  msg->content);
-                        }
-
-                        if (auto msg = std::get_if<
-                              mtx::events::RoomEvent<mtx::events::msg::KeyVerificationAccept>>(
-                              &e_)) {
-                                ChatPage::instance()->recievedDeviceVerificationAccept(
-                                  msg->content);
-                        }
-
-                        if (auto msg = std::get_if<
-                              mtx::events::RoomEvent<mtx::events::msg::KeyVerificationKey>>(&e_)) {
-                                ChatPage::instance()->recievedDeviceVerificationKey(msg->content);
-                        }
-
-                        if (auto msg = std::get_if<
-                              mtx::events::RoomEvent<mtx::events::msg::KeyVerificationMac>>(&e_)) {
-                                ChatPage::instance()->recievedDeviceVerificationMac(msg->content);
-                        }
-
-                        if (auto msg = std::get_if<
-                              mtx::events::RoomEvent<mtx::events::msg::KeyVerificationReady>>(
-                              &e_)) {
-                                ChatPage::instance()->recievedDeviceVerificationReady(msg->content);
-                        }
-
-                        if (auto msg = std::get_if<
-                              mtx::events::RoomEvent<mtx::events::msg::KeyVerificationDone>>(&e_)) {
-                                ChatPage::instance()->recievedDeviceVerificationDone(msg->content);
-                        }
-
-                        if (auto msg = std::get_if<
-                              mtx::events::RoomEvent<mtx::events::msg::KeyVerificationStart>>(
-                              &e_)) {
-                                ChatPage::instance()->recievedDeviceVerificationStart(msg->content,
-                                                                                      msg->sender);
-                        }
-                }
-
-                this->events.insert(id, e);
-                ids.push_back(id);
-
-                auto replyTo  = mtx::accessors::in_reply_to_event(e);
-                auto qReplyTo = QString::fromStdString(replyTo);
-                if (!replyTo.empty() && !events.contains(qReplyTo)) {
-                        http::client()->get_event(
-                          this->room_id_.toStdString(),
-                          replyTo,
-                          [this, id, replyTo](
-                            const mtx::events::collections::TimelineEvents &timeline,
-                            mtx::http::RequestErr err) {
-                                  if (err) {
-                                          nhlog::net()->error(
-                                            "Failed to retrieve event with id {}, which was "
-                                            "requested to show the replyTo for event {}",
-                                            replyTo,
-                                            id.toStdString());
-                                          return;
-                                  }
-                                  emit eventFetched(id, timeline);
-                          });
-                }
-        }
-
-        if (last_verification_request_event.origin_server_ts >
-            last_verification_cancel_event.origin_server_ts) {
-                ChatPage::instance()->recievedRoomDeviceVerificationRequest(
-                  last_verification_request_event, this);
-        }
-
-        return ids;
-}
-
 void
 TimelineModel::setCurrentIndex(int index)
 {
@@ -979,15 +803,18 @@ TimelineModel::markEventsAsRead(const std::vector<QString> &event_ids)
         }
 }
 
+template<typename T>
 void
-TimelineModel::sendEncryptedMessage(const std::string txn_id, nlohmann::json content)
+TimelineModel::sendEncryptedMessage(mtx::events::RoomEvent<T> msg)
 {
         const auto room_id = room_id_.toStdString();
 
         using namespace mtx::events;
         using namespace mtx::identifiers;
 
-        json doc = {{"type", "m.room.message"}, {"content", content}, {"room_id", room_id}};
+        json doc = {
+          {"type", to_string(msg.type)}, {"content", json(msg.content)}, {"room_id", room_id}};
+        std::cout << doc.dump(2) << std::endl;
 
         try {
                 // Check if we have already an outbound megolm session then we can use.
@@ -995,7 +822,7 @@ TimelineModel::sendEncryptedMessage(const std::string txn_id, nlohmann::json con
                         mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> event;
                         event.content =
                           olm::encrypt_group_message(room_id, http::client()->device_id(), doc);
-                        event.event_id         = txn_id;
+                        event.event_id         = msg.event_id;
                         event.room_id          = room_id;
                         event.sender           = http::client()->user_id().to_string();
                         event.type             = mtx::events::EventType::RoomEncrypted;
@@ -1030,25 +857,26 @@ TimelineModel::sendEncryptedMessage(const std::string txn_id, nlohmann::json con
                 const auto members = cache::roomMembers(room_id);
                 nhlog::ui()->info("retrieved {} members for {}", members.size(), room_id);
 
-                auto keeper = std::make_shared<StateKeeper>([room_id, doc, txn_id, this]() {
-                        try {
-                                mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> event;
-                                event.content = olm::encrypt_group_message(
-                                  room_id, http::client()->device_id(), doc);
-                                event.event_id         = txn_id;
-                                event.room_id          = room_id;
-                                event.sender           = http::client()->user_id().to_string();
-                                event.type             = mtx::events::EventType::RoomEncrypted;
-                                event.origin_server_ts = QDateTime::currentMSecsSinceEpoch();
-
-                                emit this->addPendingMessageToStore(event);
-                        } catch (const lmdb::error &e) {
-                                nhlog::db()->critical("failed to save megolm outbound session: {}",
-                                                      e.what());
-                                emit ChatPage::instance()->showNotification(
-                                  tr("Failed to encrypt event, sending aborted!"));
-                        }
-                });
+                auto keeper =
+                  std::make_shared<StateKeeper>([room_id, doc, txn_id = msg.event_id, this]() {
+                          try {
+                                  mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> event;
+                                  event.content = olm::encrypt_group_message(
+                                    room_id, http::client()->device_id(), doc);
+                                  event.event_id         = txn_id;
+                                  event.room_id          = room_id;
+                                  event.sender           = http::client()->user_id().to_string();
+                                  event.type             = mtx::events::EventType::RoomEncrypted;
+                                  event.origin_server_ts = QDateTime::currentMSecsSinceEpoch();
+
+                                  emit this->addPendingMessageToStore(event);
+                          } catch (const lmdb::error &e) {
+                                  nhlog::db()->critical(
+                                    "failed to save megolm outbound session: {}", e.what());
+                                  emit ChatPage::instance()->showNotification(
+                                    tr("Failed to encrypt event, sending aborted!"));
+                          }
+                  });
 
                 mtx::requests::QueryKeys req;
                 for (const auto &member : members)
@@ -1056,7 +884,7 @@ TimelineModel::sendEncryptedMessage(const std::string txn_id, nlohmann::json con
 
                 http::client()->query_keys(
                   req,
-                  [keeper = std::move(keeper), megolm_payload, txn_id, this](
+                  [keeper = std::move(keeper), megolm_payload, txn_id = msg.event_id, this](
                     const mtx::responses::QueryKeys &res, mtx::http::RequestErr err) {
                           if (err) {
                                   nhlog::net()->warn("failed to query device keys: {} {}",
@@ -1265,6 +1093,40 @@ struct SendMessageVisitor
           : model_(model)
         {}
 
+        void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationRequest> &msg)
+        {
+                emit model_->updateFlowEventId(msg.event_id);
+                model_->sendEncryptedMessage(msg);
+        }
+        void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationReady> &msg)
+        {
+                model_->sendEncryptedMessage(msg);
+        }
+        void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationStart> &msg)
+        {
+                model_->sendEncryptedMessage(msg);
+        }
+        void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationAccept> &msg)
+        {
+                model_->sendEncryptedMessage(msg);
+        }
+        void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationMac> &msg)
+        {
+                model_->sendEncryptedMessage(msg);
+        }
+        void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationKey> &msg)
+        {
+                model_->sendEncryptedMessage(msg);
+        }
+        void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationDone> &msg)
+        {
+                model_->sendEncryptedMessage(msg);
+        }
+        void operator()(const mtx::events::RoomEvent<mtx::events::msg::KeyVerificationCancel> &msg)
+        {
+                model_->sendEncryptedMessage(msg);
+        }
+
         // Do-nothing operator for all unhandled events
         template<typename T>
         void operator()(const mtx::events::Event<T> &)
@@ -1280,7 +1142,7 @@ struct SendMessageVisitor
                         if (encInfo)
                                 emit model_->newEncryptedImage(encInfo.value());
 
-                        model_->sendEncryptedMessage(msg.event_id, nlohmann::json(msg.content));
+                        model_->sendEncryptedMessage(msg);
                 } else {
                         emit model_->addPendingMessageToStore(msg);
                 }
@@ -1301,20 +1163,6 @@ struct SendMessageVisitor
 };
 
 void
-TimelineModel::processOnePendingMessage()
-{
-        if (pending.isEmpty())
-                return;
-
-        QString txn_id_qstr = pending.first();
-
-        auto event = events.value(txn_id_qstr);
-        std::cout << "Inside the process one pending message" << std::endl;
-        std::cout << std::visit([](auto &e) { return json(e); }, event).dump(2) << std::endl;
-        std::visit(SendMessageVisitor{txn_id_qstr, this}, event);
-}
-
-void
 TimelineModel::addPendingMessage(mtx::events::collections::TimelineEvents event)
 {
         std::visit(
@@ -1359,18 +1207,7 @@ TimelineModel::addPendingMessage(mtx::events::collections::TimelineEvents event)
                   event);
         }
 
-        internalAddEvents({event});
-
-        QString txn_id_qstr = QString::fromStdString(mtx::accessors::event_id(event));
-        pending.push_back(txn_id_qstr);
-        if (!std::get_if<mtx::events::RoomEvent<mtx::events::msg::Reaction>>(&event)) {
-                beginInsertRows(QModelIndex(), 0, 0);
-                this->eventOrder.insert(this->eventOrder.begin(), txn_id_qstr);
-                endInsertRows();
-        }
-        updateLastMessage();
-
-        emit nextPendingMessage();
+        std::visit(SendMessageVisitor{this}, event);
 }
 
 bool