mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-29 14:18:49 +03:00
Allow editing unsent messages
As of 0db4d71ec2
(Prevent edits of
unsent messages), messages that are edits of (or replies to) unsent
messages were not allowed. This change was made because otherwise
the edits were discarded due to use of txnid rather than mxid in the
"m.relates_to" object. Remove this restriction and fix the issue by
replacing txnid with mxid in all related events when the message is
sent (and we obtain mxid from the server).
This commit is contained in:
parent
9e2b5a1061
commit
9f798e76ed
4 changed files with 67 additions and 7 deletions
|
@ -1681,6 +1681,27 @@ Cache::storeEvent(const std::string &room_id,
|
||||||
txn.commit();
|
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>
|
std::vector<std::string>
|
||||||
Cache::relatedEvents(const std::string &room_id, const std::string &event_id)
|
Cache::relatedEvents(const std::string &room_id, const std::string &event_id)
|
||||||
{
|
{
|
||||||
|
|
|
@ -184,6 +184,9 @@ public:
|
||||||
void storeEvent(const std::string &room_id,
|
void storeEvent(const std::string &room_id,
|
||||||
const std::string &event_id,
|
const std::string &event_id,
|
||||||
const mtx::events::collections::TimelineEvent &event);
|
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,
|
std::vector<std::string> relatedEvents(const std::string &room_id,
|
||||||
const std::string &event_id);
|
const std::string &event_id);
|
||||||
|
|
||||||
|
|
|
@ -185,6 +185,33 @@ EventStore::EventStore(std::string room_id, QObject *)
|
||||||
[this](std::string txn_id, std::string event_id) {
|
[this](std::string txn_id, std::string event_id) {
|
||||||
nhlog::ui()->debug("sent {}", txn_id);
|
nhlog::ui()->debug("sent {}", txn_id);
|
||||||
|
|
||||||
|
// Replace the event_id in pending edits/replies/redactions with the actual
|
||||||
|
// event_id of this event
|
||||||
|
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);
|
||||||
|
|
||||||
|
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 id = idToIndex(event_id);
|
||||||
|
|
||||||
|
events_by_id_.remove({room_id_, related_event_id});
|
||||||
|
events_.remove({room_id_, toInternalIdx(*id)});
|
||||||
|
|
||||||
|
emit dataChanged(*id, *id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
http::client()->read_event(
|
http::client()->read_event(
|
||||||
room_id_, event_id, [this, event_id](mtx::http::RequestErr err) {
|
room_id_, event_id, [this, event_id](mtx::http::RequestErr err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -193,6 +220,11 @@ EventStore::EventStore(std::string room_id, QObject *)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
auto id = idToIndex(event_id);
|
||||||
|
|
||||||
|
if (id)
|
||||||
|
emit dataChanged(id.value(), id.value());
|
||||||
|
|
||||||
cache::client()->removePendingStatus(room_id_, txn_id);
|
cache::client()->removePendingStatus(room_id_, txn_id);
|
||||||
this->current_txn = "";
|
this->current_txn = "";
|
||||||
this->current_txn_error_count = 0;
|
this->current_txn_error_count = 0;
|
||||||
|
|
|
@ -375,6 +375,15 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
|
||||||
connect(&events, &EventStore::updateFlowEventId, this, [this](std::string event_id) {
|
connect(&events, &EventStore::updateFlowEventId, this, [this](std::string event_id) {
|
||||||
this->updateFlowEventId(event_id);
|
this->updateFlowEventId(event_id);
|
||||||
});
|
});
|
||||||
|
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_);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
showEventTimer.callOnTimeout(this, &TimelineModel::scrollTimerEvent);
|
showEventTimer.callOnTimeout(this, &TimelineModel::scrollTimerEvent);
|
||||||
}
|
}
|
||||||
|
@ -568,10 +577,8 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
|
||||||
case IsEdited:
|
case IsEdited:
|
||||||
return QVariant(relations(event).replaces().has_value());
|
return QVariant(relations(event).replaces().has_value());
|
||||||
case IsEditable:
|
case IsEditable:
|
||||||
return QVariant(!is_state_event(event) &&
|
return QVariant(!is_state_event(event) && mtx::accessors::sender(event) ==
|
||||||
mtx::accessors::sender(event) ==
|
http::client()->user_id().to_string());
|
||||||
http::client()->user_id().to_string() &&
|
|
||||||
!event_id(event).empty() && event_id(event).front() == '$');
|
|
||||||
case IsEncrypted: {
|
case IsEncrypted: {
|
||||||
auto id = event_id(event);
|
auto id = event_id(event);
|
||||||
auto encrypted_event = events.get(id, "", false);
|
auto encrypted_event = events.get(id, "", false);
|
||||||
|
@ -1796,9 +1803,6 @@ TimelineModel::formatMemberEvent(QString id)
|
||||||
void
|
void
|
||||||
TimelineModel::setEdit(QString newEdit)
|
TimelineModel::setEdit(QString newEdit)
|
||||||
{
|
{
|
||||||
if (edit_.startsWith('m'))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (newEdit.isEmpty()) {
|
if (newEdit.isEmpty()) {
|
||||||
resetEdit();
|
resetEdit();
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in a new issue