diff --git a/CHANGELOG.md b/CHANGELOG.md index a51a4ba3b..0e725ef54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ - Minor: Mod list, VIP list, and Users joined/parted messages are now searchable. (#3426) - Minor: Add search to emote popup. (#3404, #3527) - Minor: Messages can now be highlighted by subscriber or founder badges. (#3445) +- Minor: User timeout buttons can now be triggered using hotkeys. (#3483) - Minor: Add workaround for multipart emoji as described in [the RFC](https://mm2pl.github.io/emoji_rfc.pdf). (#3469) - Minor: Add feedback when using the whisper command `/w` incorrectly. (#3439) - Minor: Add feedback when writing a non-command message in the `/whispers` split. (#3439) diff --git a/src/controllers/hotkeys/ActionNames.hpp b/src/controllers/hotkeys/ActionNames.hpp index fc7f7ce70..88d52e0f8 100644 --- a/src/controllers/hotkeys/ActionNames.hpp +++ b/src/controllers/hotkeys/ActionNames.hpp @@ -44,6 +44,10 @@ inline const std::map actionNames{ 1, }}, {"search", ActionDefinition{"Focus search box"}}, + {"execModeratorAction", + ActionDefinition{ + "Usercard: execute moderation action", + "", 1}}, }}, {HotkeyCategory::Split, { diff --git a/src/widgets/dialogs/UserInfoPopup.cpp b/src/widgets/dialogs/UserInfoPopup.cpp index 3be2951b8..0e8c4a3e3 100644 --- a/src/widgets/dialogs/UserInfoPopup.cpp +++ b/src/widgets/dialogs/UserInfoPopup.cpp @@ -174,6 +174,58 @@ UserInfoPopup::UserInfoPopup(bool closeAutomatically, QWidget *parent) } return ""; }}, + {"execModeratorAction", + [this](std::vector arguments) -> QString { + if (arguments.empty()) + { + return "execModeratorAction action needs an argument, which " + "moderation action to execute, see description in the " + "editor"; + } + auto target = arguments.at(0); + QString msg; + + // these can't have /timeout/ buttons because they are not timeouts + if (target == "ban") + { + msg = QString("/ban %1").arg(this->userName_); + } + else if (target == "unban") + { + msg = QString("/unban %1").arg(this->userName_); + } + else + { + // find and execute timeout button #TARGET + + bool ok; + int buttonNum = target.toInt(&ok); + if (!ok) + { + return QString("Invalid argument for execModeratorAction: " + "%1. Use " + "\"ban\", \"unban\" or the number of the " + "timeout " + "button to execute") + .arg(target); + } + + const auto &timeoutButtons = + getSettings()->timeoutButtons.getValue(); + if (timeoutButtons.size() < buttonNum || 0 >= buttonNum) + { + return QString("Invalid argument for execModeratorAction: " + "%1. Integer out of usable range: [1, %2]") + .arg(buttonNum, timeoutButtons.size() - 1); + } + const auto &button = timeoutButtons.at(buttonNum - 1); + msg = QString("/timeout %1 %2") + .arg(this->userName_) + .arg(calculateTimeoutDuration(button)); + } + this->channel_->sendMessage(msg); + return ""; + }}, // these actions make no sense in the context of a usercard, so they aren't implemented {"reject", nullptr},