mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 11:00:48 +03:00
Merge pull request #611 from balsoft/allow-edits-of-pending-messages
Allow editing unsent messages
This commit is contained in:
commit
57a9a1d0e1
4 changed files with 88 additions and 7 deletions
|
@ -1681,6 +1681,27 @@ Cache::storeEvent(const std::string &room_id,
|
|||
txn.commit();
|
||||
}
|
||||
|
||||
void
|
||||
Cache::replaceEvent(const std::string &room_id,
|
||||
const std::string &event_id,
|
||||
const mtx::events::collections::TimelineEvent &event)
|
||||
{
|
||||
auto txn = lmdb::txn::begin(env_);
|
||||
auto eventsDb = getEventsDb(txn, room_id);
|
||||
auto relationsDb = getRelationsDb(txn, room_id);
|
||||
auto event_json = mtx::accessors::serialize_event(event.data).dump();
|
||||
|
||||
{
|
||||
eventsDb.del(txn, event_id);
|
||||
eventsDb.put(txn, event_id, event_json);
|
||||
for (auto relation : mtx::accessors::relations(event.data).relations) {
|
||||
relationsDb.put(txn, relation.event_id, event_id);
|
||||
}
|
||||
}
|
||||
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
std::vector<std::string>
|
||||
Cache::relatedEvents(const std::string &room_id, const std::string &event_id)
|
||||
{
|
||||
|
|
|
@ -184,6 +184,9 @@ public:
|
|||
void storeEvent(const std::string &room_id,
|
||||
const std::string &event_id,
|
||||
const mtx::events::collections::TimelineEvent &event);
|
||||
void replaceEvent(const std::string &room_id,
|
||||
const std::string &event_id,
|
||||
const mtx::events::collections::TimelineEvent &event);
|
||||
std::vector<std::string> relatedEvents(const std::string &room_id,
|
||||
const std::string &event_id);
|
||||
|
||||
|
|
|
@ -185,6 +185,48 @@ EventStore::EventStore(std::string room_id, QObject *)
|
|||
[this](std::string txn_id, std::string event_id) {
|
||||
nhlog::ui()->debug("sent {}", txn_id);
|
||||
|
||||
// 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 (auto related_event_id : cache::client()->relatedEvents(room_id_, txn_id)) {
|
||||
if (cache::client()->getEvent(room_id_, related_event_id)) {
|
||||
auto related_event =
|
||||
cache::client()->getEvent(room_id_, related_event_id).value();
|
||||
auto relations = mtx::accessors::relations(related_event.data);
|
||||
|
||||
// Replace the blockquote in fallback reply
|
||||
auto related_text =
|
||||
std::get_if<mtx::events::RoomEvent<mtx::events::msg::Text>>(
|
||||
&related_event.data);
|
||||
if (related_text && relations.reply_to() == txn_id) {
|
||||
size_t index =
|
||||
related_text->content.formatted_body.find(txn_id);
|
||||
if (index != std::string::npos) {
|
||||
related_text->content.formatted_body.replace(
|
||||
index, event_id.length(), event_id);
|
||||
}
|
||||
}
|
||||
|
||||
for (mtx::common::Relation &rel : relations.relations) {
|
||||
if (rel.event_id == txn_id)
|
||||
rel.event_id = event_id;
|
||||
}
|
||||
|
||||
mtx::accessors::set_relations(related_event.data, relations);
|
||||
|
||||
cache::client()->replaceEvent(
|
||||
room_id_, related_event_id, related_event);
|
||||
|
||||
auto idx = idToIndex(related_event_id);
|
||||
|
||||
events_by_id_.remove({room_id_, related_event_id});
|
||||
events_.remove({room_id_, toInternalIdx(*idx)});
|
||||
}
|
||||
}
|
||||
|
||||
http::client()->read_event(
|
||||
room_id_, event_id, [this, event_id](mtx::http::RequestErr err) {
|
||||
if (err) {
|
||||
|
@ -193,6 +235,11 @@ EventStore::EventStore(std::string room_id, QObject *)
|
|||
}
|
||||
});
|
||||
|
||||
auto idx = idToIndex(event_id);
|
||||
|
||||
if (idx)
|
||||
emit dataChanged(*idx, *idx);
|
||||
|
||||
cache::client()->removePendingStatus(room_id_, txn_id);
|
||||
this->current_txn = "";
|
||||
this->current_txn_error_count = 0;
|
||||
|
|
|
@ -375,6 +375,21 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
|
|||
connect(&events, &EventStore::updateFlowEventId, this, [this](std::string event_id) {
|
||||
this->updateFlowEventId(event_id);
|
||||
});
|
||||
// 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](std::string txn_id, 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_);
|
||||
}
|
||||
});
|
||||
|
||||
showEventTimer.callOnTimeout(this, &TimelineModel::scrollTimerEvent);
|
||||
}
|
||||
|
@ -568,10 +583,8 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
|
|||
case IsEdited:
|
||||
return QVariant(relations(event).replaces().has_value());
|
||||
case IsEditable:
|
||||
return QVariant(!is_state_event(event) &&
|
||||
mtx::accessors::sender(event) ==
|
||||
http::client()->user_id().to_string() &&
|
||||
!event_id(event).empty() && event_id(event).front() == '$');
|
||||
return QVariant(!is_state_event(event) && mtx::accessors::sender(event) ==
|
||||
http::client()->user_id().to_string());
|
||||
case IsEncrypted: {
|
||||
auto id = event_id(event);
|
||||
auto encrypted_event = events.get(id, "", false);
|
||||
|
@ -1796,9 +1809,6 @@ TimelineModel::formatMemberEvent(QString id)
|
|||
void
|
||||
TimelineModel::setEdit(QString newEdit)
|
||||
{
|
||||
if (edit_.startsWith('m'))
|
||||
return;
|
||||
|
||||
if (newEdit.isEmpty()) {
|
||||
resetEdit();
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue