mirror of
https://github.com/Nheko-Reborn/nheko.git
synced 2024-11-22 11:00:48 +03:00
Display edits correctly
This commit is contained in:
parent
faeaf9dc6b
commit
00fd4eecec
8 changed files with 99 additions and 12 deletions
|
@ -356,7 +356,7 @@ if(USE_BUNDLED_MTXCLIENT)
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
MatrixClient
|
MatrixClient
|
||||||
GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git
|
GIT_REPOSITORY https://github.com/Nheko-Reborn/mtxclient.git
|
||||||
GIT_TAG 70fa15de3ec84cf0c0ab6250f2e5e62f34a6d05b
|
GIT_TAG 31e300546eb63ea25b0b879fb255beee6022da03
|
||||||
)
|
)
|
||||||
set(BUILD_LIB_EXAMPLES OFF CACHE INTERNAL "")
|
set(BUILD_LIB_EXAMPLES OFF CACHE INTERNAL "")
|
||||||
set(BUILD_LIB_TESTS OFF CACHE INTERNAL "")
|
set(BUILD_LIB_TESTS OFF CACHE INTERNAL "")
|
||||||
|
|
|
@ -220,7 +220,7 @@
|
||||||
"name": "mtxclient",
|
"name": "mtxclient",
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
"commit": "70fa15de3ec84cf0c0ab6250f2e5e62f34a6d05b",
|
"commit": "31e300546eb63ea25b0b879fb255beee6022da03",
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/Nheko-Reborn/mtxclient.git"
|
"url": "https://github.com/Nheko-Reborn/mtxclient.git"
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,20 @@ Item {
|
||||||
width: 16
|
width: 16
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImageButton {
|
||||||
|
id: editButton
|
||||||
|
|
||||||
|
visible: (Settings.buttonsInTimeline && model.isEditable) || model.isEdited
|
||||||
|
Layout.alignment: Qt.AlignRight | Qt.AlignTop
|
||||||
|
Layout.preferredHeight: 16
|
||||||
|
width: 16
|
||||||
|
hoverEnabled: true
|
||||||
|
image: ":/icons/icons/ui/edit.png"
|
||||||
|
ToolTip.visible: hovered
|
||||||
|
ToolTip.text: model.isEditable ? qsTr("Edit") : qsTr("Edited")
|
||||||
|
onClicked: if (model.isEditable) chat.model.editAction(model.id)
|
||||||
|
}
|
||||||
|
|
||||||
EmojiButton {
|
EmojiButton {
|
||||||
id: reactButton
|
id: reactButton
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,20 @@ struct detector<Default, std::void_t<Op<Args...>>, Op, Args...>
|
||||||
template<template<class...> class Op, class... Args>
|
template<template<class...> class Op, class... Args>
|
||||||
using is_detected = typename detail::detector<nonesuch, void, Op, Args...>::value_t;
|
using is_detected = typename detail::detector<nonesuch, void, Op, Args...>::value_t;
|
||||||
|
|
||||||
|
struct IsStateEvent
|
||||||
|
{
|
||||||
|
template<class T>
|
||||||
|
bool operator()(const mtx::events::StateEvent<T> &)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
template<class T>
|
||||||
|
bool operator()(const mtx::events::Event<T> &)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct EventMsgType
|
struct EventMsgType
|
||||||
{
|
{
|
||||||
template<class E>
|
template<class E>
|
||||||
|
@ -476,3 +490,9 @@ mtx::accessors::serialize_event(const mtx::events::collections::TimelineEvents &
|
||||||
{
|
{
|
||||||
return std::visit([](const auto &e) { return nlohmann::json(e); }, event);
|
return std::visit([](const auto &e) { return nlohmann::json(e); }, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
mtx::accessors::is_state_event(const mtx::events::collections::TimelineEvents &event)
|
||||||
|
{
|
||||||
|
return std::visit(IsStateEvent{}, event);
|
||||||
|
}
|
||||||
|
|
|
@ -17,6 +17,9 @@ room_id(const mtx::events::collections::TimelineEvents &event);
|
||||||
std::string
|
std::string
|
||||||
sender(const mtx::events::collections::TimelineEvents &event);
|
sender(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
||||||
|
bool
|
||||||
|
is_state_event(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
||||||
QDateTime
|
QDateTime
|
||||||
origin_server_ts(const mtx::events::collections::TimelineEvents &event);
|
origin_server_ts(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
||||||
|
|
|
@ -774,15 +774,17 @@ EventStore::get(std::string_view id, std::string_view related_to, bool decrypt,
|
||||||
if (id.empty())
|
if (id.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
std::string id_ = std::string(id);
|
IdIndex index{room_id_, std::string(id)};
|
||||||
if (resolve_edits) {
|
if (resolve_edits) {
|
||||||
auto edits_ = edits(id_);
|
auto edits_ = edits(index.id);
|
||||||
if (!edits_.empty())
|
if (!edits_.empty()) {
|
||||||
id_ = mtx::accessors::event_id(edits_.back());
|
index.id = mtx::accessors::event_id(edits_.back());
|
||||||
|
auto event_ptr =
|
||||||
|
new mtx::events::collections::TimelineEvents(std::move(edits_.back()));
|
||||||
|
events_by_id_.insert(index, event_ptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IdIndex index{room_id_, id_};
|
|
||||||
|
|
||||||
auto event_ptr = events_by_id_.object(index);
|
auto event_ptr = events_by_id_.object(index);
|
||||||
if (!event_ptr) {
|
if (!event_ptr) {
|
||||||
auto event = cache::client()->getEvent(room_id_, index.id);
|
auto event = cache::client()->getEvent(room_id_, index.id);
|
||||||
|
|
|
@ -288,6 +288,8 @@ TimelineModel::roleNames() const
|
||||||
{ProportionalHeight, "proportionalHeight"},
|
{ProportionalHeight, "proportionalHeight"},
|
||||||
{Id, "id"},
|
{Id, "id"},
|
||||||
{State, "state"},
|
{State, "state"},
|
||||||
|
{IsEdited, "isEdited"},
|
||||||
|
{IsEditable, "isEditable"},
|
||||||
{IsEncrypted, "isEncrypted"},
|
{IsEncrypted, "isEncrypted"},
|
||||||
{IsRoomEncrypted, "isRoomEncrypted"},
|
{IsRoomEncrypted, "isRoomEncrypted"},
|
||||||
{ReplyTo, "replyTo"},
|
{ReplyTo, "replyTo"},
|
||||||
|
@ -409,8 +411,12 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
|
||||||
|
|
||||||
return QVariant(prop > 0 ? prop : 1.);
|
return QVariant(prop > 0 ? prop : 1.);
|
||||||
}
|
}
|
||||||
case Id:
|
case Id: {
|
||||||
return QVariant(QString::fromStdString(event_id(event)));
|
if (auto replaces = relations(event).replaces())
|
||||||
|
return QVariant(QString::fromStdString(replaces.value()));
|
||||||
|
else
|
||||||
|
return QVariant(QString::fromStdString(event_id(event)));
|
||||||
|
}
|
||||||
case State: {
|
case State: {
|
||||||
auto id = QString::fromStdString(event_id(event));
|
auto id = QString::fromStdString(event_id(event));
|
||||||
auto containsOthers = [](const auto &vec) {
|
auto containsOthers = [](const auto &vec) {
|
||||||
|
@ -430,6 +436,11 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
|
||||||
else
|
else
|
||||||
return qml_mtx_events::Received;
|
return qml_mtx_events::Received;
|
||||||
}
|
}
|
||||||
|
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());
|
||||||
case IsEncrypted: {
|
case IsEncrypted: {
|
||||||
auto id = event_id(event);
|
auto id = event_id(event);
|
||||||
auto encrypted_event = events.get(id, id, false);
|
auto encrypted_event = events.get(id, id, false);
|
||||||
|
@ -444,7 +455,7 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
|
||||||
case ReplyTo:
|
case ReplyTo:
|
||||||
return QVariant(QString::fromStdString(relations(event).reply_to().value_or("")));
|
return QVariant(QString::fromStdString(relations(event).reply_to().value_or("")));
|
||||||
case Reactions: {
|
case Reactions: {
|
||||||
auto id = event_id(event);
|
auto id = relations(event).replaces().value_or(event_id(event));
|
||||||
return QVariant::fromValue(events.reactions(id));
|
return QVariant::fromValue(events.reactions(id));
|
||||||
}
|
}
|
||||||
case RoomId:
|
case RoomId:
|
||||||
|
@ -813,6 +824,12 @@ TimelineModel::replyAction(QString id)
|
||||||
setReply(id);
|
setReply(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineModel::editAction(QString id)
|
||||||
|
{
|
||||||
|
setEdit(id);
|
||||||
|
}
|
||||||
|
|
||||||
RelatedInfo
|
RelatedInfo
|
||||||
TimelineModel::relatedInfo(QString id)
|
TimelineModel::relatedInfo(QString id)
|
||||||
{
|
{
|
||||||
|
@ -1501,6 +1518,22 @@ TimelineModel::formatMemberEvent(QString id)
|
||||||
return rendered;
|
return rendered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TimelineModel::setEdit(QString newEdit)
|
||||||
|
{
|
||||||
|
if (edit_ != newEdit) {
|
||||||
|
edit_ = newEdit;
|
||||||
|
emit editChanged(edit_);
|
||||||
|
|
||||||
|
auto ev = events.get(newEdit.toStdString(), "");
|
||||||
|
if (ev) {
|
||||||
|
setReply(QString::fromStdString(
|
||||||
|
mtx::accessors::relations(*ev).reply_to().value_or("")));
|
||||||
|
// input()->setText(mtx::accessors::body(*ev));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QString
|
QString
|
||||||
TimelineModel::roomName() const
|
TimelineModel::roomName() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -145,6 +145,7 @@ class TimelineModel : public QAbstractListModel
|
||||||
Q_PROPERTY(std::vector<QString> typingUsers READ typingUsers WRITE updateTypingUsers NOTIFY
|
Q_PROPERTY(std::vector<QString> typingUsers READ typingUsers WRITE updateTypingUsers NOTIFY
|
||||||
typingUsersChanged)
|
typingUsersChanged)
|
||||||
Q_PROPERTY(QString reply READ reply WRITE setReply NOTIFY replyChanged RESET resetReply)
|
Q_PROPERTY(QString reply READ reply WRITE setReply NOTIFY replyChanged RESET resetReply)
|
||||||
|
Q_PROPERTY(QString edit READ edit WRITE setEdit NOTIFY editChanged RESET resetEdit)
|
||||||
Q_PROPERTY(
|
Q_PROPERTY(
|
||||||
bool paginationInProgress READ paginationInProgress NOTIFY paginationInProgressChanged)
|
bool paginationInProgress READ paginationInProgress NOTIFY paginationInProgressChanged)
|
||||||
Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged)
|
Q_PROPERTY(QString roomName READ roomName NOTIFY roomNameChanged)
|
||||||
|
@ -181,6 +182,8 @@ public:
|
||||||
ProportionalHeight,
|
ProportionalHeight,
|
||||||
Id,
|
Id,
|
||||||
State,
|
State,
|
||||||
|
IsEdited,
|
||||||
|
IsEditable,
|
||||||
IsEncrypted,
|
IsEncrypted,
|
||||||
IsRoomEncrypted,
|
IsRoomEncrypted,
|
||||||
ReplyTo,
|
ReplyTo,
|
||||||
|
@ -213,6 +216,7 @@ public:
|
||||||
Q_INVOKABLE void viewRawMessage(QString id) const;
|
Q_INVOKABLE void viewRawMessage(QString id) const;
|
||||||
Q_INVOKABLE void viewDecryptedRawMessage(QString id) const;
|
Q_INVOKABLE void viewDecryptedRawMessage(QString id) const;
|
||||||
Q_INVOKABLE void openUserProfile(QString userid, bool global = false);
|
Q_INVOKABLE void openUserProfile(QString userid, bool global = false);
|
||||||
|
Q_INVOKABLE void editAction(QString id);
|
||||||
Q_INVOKABLE void replyAction(QString id);
|
Q_INVOKABLE void replyAction(QString id);
|
||||||
Q_INVOKABLE void readReceiptsAction(QString id) const;
|
Q_INVOKABLE void readReceiptsAction(QString id) const;
|
||||||
Q_INVOKABLE void redactEvent(QString id);
|
Q_INVOKABLE void redactEvent(QString id);
|
||||||
|
@ -268,6 +272,16 @@ public slots:
|
||||||
emit replyChanged(reply_);
|
emit replyChanged(reply_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
QString edit() const { return edit_; }
|
||||||
|
void setEdit(QString newEdit);
|
||||||
|
void resetEdit()
|
||||||
|
{
|
||||||
|
if (!edit_.isEmpty()) {
|
||||||
|
edit_ = "";
|
||||||
|
emit editChanged(edit_);
|
||||||
|
resetReply();
|
||||||
|
}
|
||||||
|
}
|
||||||
void setDecryptDescription(bool decrypt) { decryptDescription = decrypt; }
|
void setDecryptDescription(bool decrypt) { decryptDescription = decrypt; }
|
||||||
void clearTimeline() { events.clearTimeline(); }
|
void clearTimeline() { events.clearTimeline(); }
|
||||||
void receivedSessionKey(const std::string &session_key)
|
void receivedSessionKey(const std::string &session_key)
|
||||||
|
@ -292,6 +306,7 @@ signals:
|
||||||
void newEncryptedImage(mtx::crypto::EncryptedFile encryptionInfo);
|
void newEncryptedImage(mtx::crypto::EncryptedFile encryptionInfo);
|
||||||
void typingUsersChanged(std::vector<QString> users);
|
void typingUsersChanged(std::vector<QString> users);
|
||||||
void replyChanged(QString reply);
|
void replyChanged(QString reply);
|
||||||
|
void editChanged(QString reply);
|
||||||
void paginationInProgressChanged(const bool);
|
void paginationInProgressChanged(const bool);
|
||||||
void newCallEvent(const mtx::events::collections::TimelineEvents &event);
|
void newCallEvent(const mtx::events::collections::TimelineEvents &event);
|
||||||
|
|
||||||
|
@ -322,7 +337,7 @@ private:
|
||||||
bool m_paginationInProgress = false;
|
bool m_paginationInProgress = false;
|
||||||
|
|
||||||
QString currentId;
|
QString currentId;
|
||||||
QString reply_;
|
QString reply_, edit_;
|
||||||
std::vector<QString> typingUsers_;
|
std::vector<QString> typingUsers_;
|
||||||
|
|
||||||
TimelineViewManager *manager_;
|
TimelineViewManager *manager_;
|
||||||
|
|
Loading…
Reference in a new issue