diff --git a/src/encryption/Olm.cpp b/src/encryption/Olm.cpp
index 5de18fa3f0d272465c34f8dbfed540f5fdc874b5..e6426658cd7f2929a9cacf444c3ab9baf73594c1 100644
--- a/src/encryption/Olm.cpp
+++ b/src/encryption/Olm.cpp
@@ -470,6 +470,30 @@ handle_pre_key_olm_message(const std::string &sender,
     return plaintext;
 }
 
+mtx::events::msg::Encrypted
+encrypt_group_message_with_session(mtx::crypto::OutboundGroupSessionPtr &session,
+                                   const std::string &device_id,
+                                   nlohmann::json body)
+{
+    using namespace mtx::events;
+
+    // relations shouldn't be encrypted...
+    mtx::common::Relations relations = mtx::common::parse_relations(body["content"]);
+
+    auto payload = olm::client()->encrypt_group_message(session.get(), body.dump());
+
+    // Prepare the m.room.encrypted event.
+    msg::Encrypted data;
+    data.ciphertext = std::string((char *)payload.data(), payload.size());
+    data.sender_key = olm::client()->identity_keys().curve25519;
+    data.session_id = mtx::crypto::session_id(session.get());
+    data.device_id  = device_id;
+    data.algorithm  = MEGOLM_ALGO;
+    data.relations  = relations;
+
+    return data;
+}
+
 mtx::events::msg::Encrypted
 encrypt_group_message(const std::string &room_id, const std::string &device_id, nlohmann::json body)
 {
@@ -631,19 +655,7 @@ encrypt_group_message(const std::string &room_id, const std::string &device_id,
     if (!sendSessionTo.empty())
         olm::send_encrypted_to_device_messages(sendSessionTo, megolm_payload);
 
-    // relations shouldn't be encrypted...
-    mtx::common::Relations relations = mtx::common::parse_relations(body["content"]);
-
-    auto payload = olm::client()->encrypt_group_message(session.get(), body.dump());
-
-    // Prepare the m.room.encrypted event.
-    msg::Encrypted data;
-    data.ciphertext = std::string((char *)payload.data(), payload.size());
-    data.sender_key = olm::client()->identity_keys().curve25519;
-    data.session_id = mtx::crypto::session_id(session.get());
-    data.device_id  = device_id;
-    data.algorithm  = MEGOLM_ALGO;
-    data.relations  = relations;
+    auto data = encrypt_group_message_with_session(session, device_id, body);
 
     group_session_data.message_index = olm_outbound_group_session_message_index(session.get());
     nhlog::crypto()->debug("next message_index {}", group_session_data.message_index);
diff --git a/src/encryption/Olm.h b/src/encryption/Olm.h
index a6822b6808f63428c6622f24876b71d709886bd7..9d99bcf404b018d778c1782eb878fe1dfc44486b 100644
--- a/src/encryption/Olm.h
+++ b/src/encryption/Olm.h
@@ -79,6 +79,11 @@ handle_pre_key_olm_message(const std::string &sender,
                            const std::string &sender_key,
                            const mtx::events::msg::OlmCipherContent &content);
 
+mtx::events::msg::Encrypted
+encrypt_group_message_with_session(mtx::crypto::OutboundGroupSessionPtr &session,
+                                   const std::string &device_id,
+                                   nlohmann::json body);
+
 mtx::events::msg::Encrypted
 encrypt_group_message(const std::string &room_id,
                       const std::string &device_id,
diff --git a/src/timeline/EventStore.cpp b/src/timeline/EventStore.cpp
index f7d15b6178fe96ecf886cbc9cb59a50238cf1f54..4151356f9dd4dda1fe2a182e384d5608bdfe5a57 100644
--- a/src/timeline/EventStore.cpp
+++ b/src/timeline/EventStore.cpp
@@ -184,11 +184,21 @@ EventStore::EventStore(std::string room_id, QObject *)
           // Replace the event_id in pending edits/replies/redactions with the actual
           // event_id of this event. This allows one to edit and reply to events that are
           // currently pending.
-
-          // FIXME (introduced by balsoft): this doesn't work for encrypted events, but
-          // allegedly it's hard to fix so I'll leave my first contribution at that
           for (const auto &pending_event_id : cache::client()->pendingEvents(room_id_)) {
               if (auto pending_event = cache::client()->getEvent(room_id_, pending_event_id)) {
+                  bool was_encrypted = false;
+                  mtx::events::EncryptedEvent<mtx::events::msg::Encrypted> original_encrypted;
+                  if (auto encrypted =
+                        std::get_if<mtx::events::EncryptedEvent<mtx::events::msg::Encrypted>>(
+                          &pending_event->data)) {
+                      auto d_event = decryptEvent({room_id_, encrypted->event_id}, *encrypted);
+                      if (d_event->event) {
+                          was_encrypted       = true;
+                          original_encrypted  = *encrypted;
+                          pending_event->data = *d_event->event;
+                      }
+                  }
+
                   auto relations = mtx::accessors::relations(pending_event->data);
 
                   // Replace the blockquote in fallback reply
@@ -202,13 +212,49 @@ EventStore::EventStore(std::string room_id, QObject *)
                       }
                   }
 
+                  bool replaced_txn = false;
                   for (mtx::common::Relation &rel : relations.relations) {
-                      if (rel.event_id == txn_id)
+                      if (rel.event_id == txn_id) {
                           rel.event_id = event_id;
+                          replaced_txn = true;
+                      }
                   }
 
+                  if (!replaced_txn)
+                      continue;
+
                   mtx::accessors::set_relations(pending_event->data, std::move(relations));
 
+                  // reencrypt. This is a bit of a hack and might make people able to read the
+                  // message, that were in the room at the time of sending the last pending message.
+                  // That window is pretty small though, so it should be good enough. We also just
+                  // fail, if there was no session. But there SHOULD always be one. Let's wait until
+                  // I am proven wrong :3
+                  if (was_encrypted) {
+                      auto session = cache::getOutboundMegolmSession(room_id_);
+                      if (!session.session)
+                          continue;
+
+                      std::visit(
+                        [&pending_event, &original_encrypted, &session, this](auto &msg) {
+                            json doc = {{"type", mtx::events::to_string(msg.type)},
+                                        {"content", json(msg.content)},
+                                        {"room_id", room_id_}};
+
+                            auto data = olm::encrypt_group_message_with_session(
+                              session.session, http::client()->device_id(), doc);
+
+                            session.data.message_index =
+                              olm_outbound_group_session_message_index(session.session.get());
+                            cache::updateOutboundMegolmSession(
+                              room_id_, session.data, session.session);
+
+                            original_encrypted.content = data;
+                            pending_event->data        = original_encrypted;
+                        },
+                        pending_event->data);
+                  }
+
                   cache::client()->replaceEvent(room_id_, pending_event_id, *pending_event);
 
                   auto idx = idToIndex(pending_event_id);
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index 7892c2e4d5cf3bd323e9292ffa890f984c84f99f..a8b6cf6f8340563fd12bfa31c9c88f8d5f9c70f2 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -423,19 +423,22 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
 
     // When a message is sent, check if the current edit/reply relates to that message,
     // and update the event_id so that it points to the sent message and not the pending one.
-    connect(&events,
-            &EventStore::messageSent,
-            this,
-            [this](const std::string &txn_id, const std::string &event_id) {
-                if (edit_.toStdString() == txn_id) {
-                    edit_ = QString::fromStdString(event_id);
-                    emit editChanged(edit_);
-                }
-                if (reply_.toStdString() == txn_id) {
-                    reply_ = QString::fromStdString(event_id);
-                    emit replyChanged(reply_);
-                }
-            });
+    connect(
+      &events,
+      &EventStore::messageSent,
+      this,
+      [this](const std::string &txn_id, const std::string &event_id) {
+          if (edit_.toStdString() == txn_id) {
+              edit_ = QString::fromStdString(event_id);
+              emit editChanged(edit_);
+          }
+          nhlog::net()->debug("reply {}\ntxn {}\nev {}", reply_.toStdString(), txn_id, event_id);
+          if (reply_.toStdString() == txn_id) {
+              reply_ = QString::fromStdString(event_id);
+              emit replyChanged(reply_);
+          }
+      },
+      Qt::QueuedConnection);
 
     connect(
       manager_, &TimelineViewManager::initialSyncChanged, &events, &EventStore::enableKeyRequests);