From f462eb84dcd57764d0f639e3da6890b0ce67b373 Mon Sep 17 00:00:00 2001 From: Nicolas Werner Date: Thu, 20 Mar 2025 21:52:32 +0100 Subject: [PATCH] Ban, unban, kick or redact by replying --- man/nheko.1.adoc | 8 ++++---- src/ChatPage.cpp | 35 ++++++++++++++++++----------------- src/CommandCompleter.cpp | 12 ++++++++---- src/timeline/InputBar.cpp | 38 ++++++++++++++++++++++++++++++++------ 4 files changed, 62 insertions(+), 31 deletions(-) diff --git a/man/nheko.1.adoc b/man/nheko.1.adoc index ff316308..586295bb 100644 --- a/man/nheko.1.adoc +++ b/man/nheko.1.adoc @@ -198,19 +198,19 @@ Leave the current room. _reason_ is optional. Invite a user into the current room. _reason_ is optional. */kick* __ _[reason]_:: -Kick a user from the current room. _reason_ is optional. +Kick a user from the current room. _reason_ is optional. You can alternatively kick the user you are replying to by leaving out the _username_. */ban* __ _[reason]_:: -Ban a user from the current room. _reason_ is optional. +Ban a user from the current room. _reason_ is optional. You can alternatively ban the user you are replying to by leaving out the _username_. */unban* __ _[reason]_:: -Unban a user. _reason_ is optional. +Unban a user. _reason_ is optional. You can alternatively unban the user you are replying to by leaving out the _username_. */redact* __ _[reason]_:: Redacts all visible messages of the specified user. You will run into rate limits quickly. */redact* __ _[reason]_:: -Redacts a specific event. +Redacts a specific event. You can alternatively redact the event you are replying to by specifying neither an _eventid_ nor _username_. */roomnick* __:: Change your nickname in a single room. diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp index 3c663b94..f9870bb9 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp @@ -1084,14 +1084,14 @@ void ChatPage::kickUser(const QString &room, QString userid, QString reason) { bool confirmed; - reason = - QInputDialog::getText(nullptr, - tr("Reason for the kick"), - tr("Enter reason for kicking %1 (%2) or hit enter for no reason:") - .arg(cache::displayName(room, userid), userid), - QLineEdit::Normal, - reason, - &confirmed); + reason = QInputDialog::getText( + nullptr, + tr("Reason for the kick"), + tr("Enter reason for kicking %1 (%2) or hit enter for no reason:") + .arg(cache::displayName(room, userid).toHtmlEscaped(), userid.toHtmlEscaped()), + QLineEdit::Normal, + reason, + &confirmed); if (!confirmed) { return; } @@ -1113,14 +1113,14 @@ void ChatPage::banUser(const QString &room, QString userid, QString reason) { bool confirmed; - reason = - QInputDialog::getText(nullptr, - tr("Reason for the ban"), - tr("Enter reason for banning %1 (%2) or hit enter for no reason:") - .arg(cache::displayName(room, userid), userid), - QLineEdit::Normal, - reason, - &confirmed); + reason = QInputDialog::getText( + nullptr, + tr("Reason for the ban"), + tr("Enter reason for banning %1 (%2) or hit enter for no reason:") + .arg(cache::displayName(room, userid).toHtmlEscaped(), userid.toHtmlEscaped()), + QLineEdit::Normal, + reason, + &confirmed); if (!confirmed) { return; } @@ -1144,7 +1144,8 @@ ChatPage::unbanUser(const QString &room, QString userid, QString reason) if (QMessageBox::question(nullptr, tr("Confirm unban"), tr("Do you really want to unban %1 (%2)?") - .arg(cache::displayName(room, userid), userid)) != QMessageBox::Yes) + .arg(cache::displayName(room, userid).toHtmlEscaped(), + userid.toHtmlEscaped())) != QMessageBox::Yes) return; http::client()->unban_user( diff --git a/src/CommandCompleter.cpp b/src/CommandCompleter.cpp index dcb9ba9b..9ee12e5b 100644 --- a/src/CommandCompleter.cpp +++ b/src/CommandCompleter.cpp @@ -207,13 +207,17 @@ CommandCompleter::data(const QModelIndex &index, int role) const case Invite: return tr("Invite a user into the current room. Reason is optional."); case Kick: - return tr("Kick a user from the current room. Reason is optional."); + return tr("Kick a user from the current room. Reason is optional. If user is left " + "out, will try to kick the sender you are replying to."); case Ban: - return tr("Ban a user from the current room. Reason is optional."); + return tr("Ban a user from the current room. Reason is optional. If user is left " + "out, will try to ban the sender you are replying to."); case Unban: - return tr("Unban a user in the current room. Reason is optional."); + return tr("Unban a user in the current room. Reason is optional. If user is left " + "out, will try to unban the sender you are replying to."); case Redact: - return tr("Redact an event or all locally cached messages of a user."); + return tr("Redact an event by event id or that you are replying to or all locally " + "cached messages of a user."); case Roomnick: return tr("Change your displayname in this room."); case Shrug: diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp index 1e587d6d..c8ea0b5d 100644 --- a/src/timeline/InputBar.cpp +++ b/src/timeline/InputBar.cpp @@ -901,19 +901,45 @@ InputBar::command(const QString &command, QString args) ChatPage::instance()->inviteUser( room->roomId(), args.section(' ', 0, 0), args.section(' ', 1, -1)); } else if (command == QLatin1String("kick")) { - ChatPage::instance()->kickUser( - room->roomId(), args.section(' ', 0, 0), args.section(' ', 1, -1)); + if (args.startsWith('@')) { + ChatPage::instance()->kickUser( + room->roomId(), args.section(' ', 0, 0), args.section(' ', 1, -1)); + } else if (auto reply = room->reply(); !reply.isEmpty()) { + auto replySender = + room->dataById(room->reply(), TimelineModel::Roles::UserId, "").toString(); + if (!replySender.isEmpty()) { + ChatPage::instance()->kickUser(room->roomId(), replySender, args); + } + } } else if (command == QLatin1String("ban")) { - ChatPage::instance()->banUser( - room->roomId(), args.section(' ', 0, 0), args.section(' ', 1, -1)); + if (args.startsWith('@')) { + ChatPage::instance()->banUser( + room->roomId(), args.section(' ', 0, 0), args.section(' ', 1, -1)); + } else if (auto reply = room->reply(); !reply.isEmpty()) { + auto replySender = + room->dataById(room->reply(), TimelineModel::Roles::UserId, "").toString(); + if (!replySender.isEmpty()) { + ChatPage::instance()->banUser(room->roomId(), replySender, args); + } + } } else if (command == QLatin1String("unban")) { - ChatPage::instance()->unbanUser( - room->roomId(), args.section(' ', 0, 0), args.section(' ', 1, -1)); + if (args.startsWith('@')) { + ChatPage::instance()->unbanUser( + room->roomId(), args.section(' ', 0, 0), args.section(' ', 1, -1)); + } else if (auto reply = room->reply(); !reply.isEmpty()) { + auto replySender = + room->dataById(room->reply(), TimelineModel::Roles::UserId, "").toString(); + if (!replySender.isEmpty()) { + ChatPage::instance()->unbanUser(room->roomId(), replySender, args); + } + } } else if (command == QLatin1String("redact")) { if (args.startsWith('@')) { room->redactAllFromUser(args.section(' ', 0, 0), args.section(' ', 1, -1)); } else if (args.startsWith('$')) { room->redactEvent(args.section(' ', 0, 0), args.section(' ', 1, -1)); + } else if (auto reply = room->reply(); !reply.isEmpty()) { + room->redactEvent(reply, args); } } else if (command == QLatin1String("roomnick")) { mtx::events::state::Member member;