mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-21 22:24:07 +01:00
Feature: execute commands on chat messages using the context menu (#3738)
This commit is contained in:
parent
7d9c3c65da
commit
4239666934
8 changed files with 103 additions and 9 deletions
|
@ -15,6 +15,7 @@
|
|||
- Minor: Prevent user from entering incorrect characters in Live Notifications channels list. (#3715, #3730)
|
||||
- Minor: Fixed automod caught message notice appearing twice for mods. (#3717)
|
||||
- Minor: Added `/requests` command. Usage: `/requests [channel]`. Opens the channel points requests queue for the provided channel or the current channel if no input is provided. (#3746)
|
||||
- Minor: Added ability to execute commands on chat messages using the message context menu. (#3738)
|
||||
- Bugfix: Fixed live notifications for usernames containing uppercase characters. (#3646)
|
||||
- Bugfix: Fixed live notifications not getting updated for closed streams going offline. (#3678)
|
||||
- Bugfix: Fixed certain settings dialogs appearing behind the main window, when `Always on top` was used. (#3679)
|
||||
|
|
|
@ -15,11 +15,14 @@ Command::Command(const QString &_text)
|
|||
|
||||
this->name = _text.mid(0, index).trimmed();
|
||||
this->func = _text.mid(index + 1).trimmed();
|
||||
this->showInMsgContextMenu = false;
|
||||
}
|
||||
|
||||
Command::Command(const QString &_name, const QString &_func)
|
||||
Command::Command(const QString &_name, const QString &_func,
|
||||
bool _showInMsgContextMenu)
|
||||
: name(_name.trimmed())
|
||||
, func(_func.trimmed())
|
||||
, showInMsgContextMenu(_showInMsgContextMenu)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -10,10 +10,12 @@ namespace chatterino {
|
|||
struct Command {
|
||||
QString name;
|
||||
QString func;
|
||||
bool showInMsgContextMenu;
|
||||
|
||||
Command() = default;
|
||||
explicit Command(const QString &text);
|
||||
Command(const QString &name, const QString &func);
|
||||
Command(const QString &name, const QString &func,
|
||||
bool showInMsgContextMenu = false);
|
||||
|
||||
QString toString() const;
|
||||
};
|
||||
|
@ -31,6 +33,8 @@ struct Serialize<chatterino::Command> {
|
|||
|
||||
chatterino::rj::set(ret, "name", value.name, a);
|
||||
chatterino::rj::set(ret, "func", value.func, a);
|
||||
chatterino::rj::set(ret, "showInMsgContextMenu",
|
||||
value.showInMsgContextMenu, a);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -59,6 +63,15 @@ struct Deserialize<chatterino::Command> {
|
|||
PAJLADA_REPORT_ERROR(error);
|
||||
return command;
|
||||
}
|
||||
if (!chatterino::rj::getSafe(value, "showInMsgContextMenu",
|
||||
command.showInMsgContextMenu))
|
||||
{
|
||||
command.showInMsgContextMenu = false;
|
||||
|
||||
PAJLADA_REPORT_ERROR(error);
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
return command;
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace chatterino {
|
|||
|
||||
// commandmodel
|
||||
CommandModel::CommandModel(QObject *parent)
|
||||
: SignalVectorModel<Command>(2, parent)
|
||||
: SignalVectorModel<Command>(Column::COUNT, parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -14,16 +14,21 @@ CommandModel::CommandModel(QObject *parent)
|
|||
Command CommandModel::getItemFromRow(std::vector<QStandardItem *> &row,
|
||||
const Command &original)
|
||||
{
|
||||
return Command(row[0]->data(Qt::EditRole).toString(),
|
||||
row[1]->data(Qt::EditRole).toString());
|
||||
return Command(row[Column::Trigger]->data(Qt::EditRole).toString(),
|
||||
row[Column::CommandFunc]->data(Qt::EditRole).toString(),
|
||||
row[Column::ShowInMessageContextMenu]
|
||||
->data(Qt::CheckStateRole)
|
||||
.toBool());
|
||||
}
|
||||
|
||||
// turns a row in the model into a vector item
|
||||
void CommandModel::getRowFromItem(const Command &item,
|
||||
std::vector<QStandardItem *> &row)
|
||||
{
|
||||
setStringItem(row[0], item.name);
|
||||
setStringItem(row[1], item.func);
|
||||
setStringItem(row[Column::Trigger], item.name);
|
||||
setStringItem(row[Column::CommandFunc], item.func);
|
||||
setBoolItem(row[Column::ShowInMessageContextMenu],
|
||||
item.showInMsgContextMenu);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
|
|
@ -13,6 +13,13 @@ class CommandModel : public SignalVectorModel<Command>
|
|||
{
|
||||
explicit CommandModel(QObject *parent);
|
||||
|
||||
enum Column {
|
||||
Trigger = 0,
|
||||
CommandFunc = 1,
|
||||
ShowInMessageContextMenu = 2,
|
||||
COUNT,
|
||||
};
|
||||
|
||||
protected:
|
||||
// turn a vector item into a model row
|
||||
virtual Command getItemFromRow(std::vector<QStandardItem *> &row,
|
||||
|
|
|
@ -1885,6 +1885,10 @@ void ChannelView::addContextMenuItems(
|
|||
// Add hidden options (e.g. copy message ID) if the user held down Shift
|
||||
this->addHiddenContextMenuItems(hoveredElement, layout, event, *menu);
|
||||
|
||||
// Add executable command options
|
||||
this->addCommandExecutionContextMenuItems(hoveredElement, layout, event,
|
||||
*menu);
|
||||
|
||||
menu->popup(QCursor::pos());
|
||||
menu->raise();
|
||||
}
|
||||
|
@ -2081,6 +2085,62 @@ void ChannelView::addHiddenContextMenuItems(
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelView::addCommandExecutionContextMenuItems(
|
||||
const MessageLayoutElement * /*hoveredElement*/, MessageLayoutPtr layout,
|
||||
QMouseEvent * /*event*/, QMenu &menu)
|
||||
{
|
||||
/* Get commands to be displayed in context menu;
|
||||
* only those that had the showInMsgContextMenu check box marked in the Commands page */
|
||||
std::vector<Command> cmds;
|
||||
for (auto &cmd : getApp()->commands->items)
|
||||
{
|
||||
if (cmd.showInMsgContextMenu)
|
||||
{
|
||||
cmds.push_back(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
if (cmds.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
menu.addSeparator();
|
||||
auto executeAction = menu.addAction("Execute command");
|
||||
auto cmdMenu = new QMenu;
|
||||
executeAction->setMenu(cmdMenu);
|
||||
|
||||
for (auto &cmd : cmds)
|
||||
{
|
||||
QString inputText = this->selection_.isEmpty()
|
||||
? layout->getMessage()->messageText
|
||||
: this->getSelectedText();
|
||||
|
||||
inputText.push_front(cmd.name + " ");
|
||||
|
||||
cmdMenu->addAction(cmd.name, [this, inputText] {
|
||||
ChannelPtr channel;
|
||||
|
||||
/* Search popups and user message history's underlyingChannels aren't of type TwitchChannel, but
|
||||
* we would still like to execute commands from them. Use their source channel instead if applicable. */
|
||||
if (this->hasSourceChannel())
|
||||
{
|
||||
channel = this->sourceChannel();
|
||||
}
|
||||
else
|
||||
{
|
||||
channel = this->underlyingChannel_;
|
||||
}
|
||||
|
||||
QString value =
|
||||
getApp()->commands->execCommand(inputText, channel, false);
|
||||
|
||||
channel->sendMessage(value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelView::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() != Qt::LeftButton)
|
||||
|
|
|
@ -184,6 +184,10 @@ private:
|
|||
void addHiddenContextMenuItems(const MessageLayoutElement *hoveredElement,
|
||||
MessageLayoutPtr layout, QMouseEvent *event,
|
||||
QMenu &menu);
|
||||
void addCommandExecutionContextMenuItems(
|
||||
const MessageLayoutElement *hoveredElement, MessageLayoutPtr layout,
|
||||
QMouseEvent *event, QMenu &menu);
|
||||
|
||||
int getLayoutWidth() const;
|
||||
void updatePauses();
|
||||
void unpaused();
|
||||
|
|
|
@ -44,8 +44,9 @@ CommandPage::CommandPage()
|
|||
layout.emplace<EditableModelView>(app->commands->createModel(nullptr))
|
||||
.getElement();
|
||||
|
||||
view->setTitles({"Trigger", "Command"});
|
||||
view->getTableView()->horizontalHeader()->setStretchLastSection(true);
|
||||
view->setTitles({"Trigger", "Command", "Show In\nMessage Menu"});
|
||||
view->getTableView()->horizontalHeader()->setSectionResizeMode(
|
||||
1, QHeaderView::Stretch);
|
||||
view->addButtonPressed.connect([] {
|
||||
getApp()->commands->items.append(
|
||||
Command{"/command", "I made a new command HeyGuys"});
|
||||
|
|
Loading…
Reference in a new issue