summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorDeepBlueV7.X <nicolas.werner@hotmail.de>2023-03-10 00:17:06 +0000
committerGitHub <noreply@github.com>2023-03-10 00:17:06 +0000
commit7d8ccd4ce8b22149aefe79b4f12109fe1fdae52c (patch)
treebef44b2d1e2b6aedeeb909666486ed3ac33071b8 /src
parentMerge pull request #1394 from Nheko-Reborn/uiTweaks (diff)
parentHandle incomplete commands better (diff)
downloadnheko-7d8ccd4ce8b22149aefe79b4f12109fe1fdae52c.tar.xz
Merge pull request #1388 from Nheko-Reborn/command
Warn if an invalid command is entered
Diffstat (limited to 'src')
-rw-r--r--src/timeline/InputBar.cpp114
-rw-r--r--src/timeline/InputBar.h24
2 files changed, 112 insertions, 26 deletions
diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp

index 7d964bb5..b27128e0 100644 --- a/src/timeline/InputBar.cpp +++ b/src/timeline/InputBar.cpp
@@ -224,8 +224,9 @@ InputBar::insertMimeData(const QMimeData *md) } void -InputBar::updateAtRoom(const QString &t) +InputBar::updateTextContentProperties(const QString &t) { + // check for @room bool roomMention = false; if (t.size() > 4) { @@ -249,6 +250,61 @@ InputBar::updateAtRoom(const QString &t) this->containsAtRoom_ = roomMention; emit containsAtRoomChanged(); } + + // check for invalid commands + auto commandName = getCommandAndArgs(t).first; + static const QSet<QString> validCommands{QStringLiteral("me"), + QStringLiteral("react"), + QStringLiteral("join"), + QStringLiteral("knock"), + QStringLiteral("part"), + QStringLiteral("leave"), + QStringLiteral("invite"), + QStringLiteral("kick"), + QStringLiteral("ban"), + QStringLiteral("unban"), + QStringLiteral("redact"), + QStringLiteral("roomnick"), + QStringLiteral("shrug"), + QStringLiteral("fliptable"), + QStringLiteral("unfliptable"), + QStringLiteral("sovietflip"), + QStringLiteral("clear-timeline"), + QStringLiteral("reset-state"), + QStringLiteral("rotate-megolm-session"), + QStringLiteral("md"), + QStringLiteral("cmark"), + QStringLiteral("plain"), + QStringLiteral("rainbow"), + QStringLiteral("rainbowme"), + QStringLiteral("notice"), + QStringLiteral("rainbownotice"), + QStringLiteral("confetti"), + QStringLiteral("rainbowconfetti"), + QStringLiteral("goto"), + QStringLiteral("converttodm"), + QStringLiteral("converttoroom")}; + bool hasInvalidCommand = !commandName.isNull() && !validCommands.contains(commandName); + bool hasIncompleteCommand = hasInvalidCommand && '/' + commandName == t; + + bool signalsChanged{false}; + if (containsInvalidCommand_ != hasInvalidCommand) { + containsInvalidCommand_ = hasInvalidCommand; + signalsChanged = true; + } + if (containsIncompleteCommand_ != hasIncompleteCommand) { + containsIncompleteCommand_ = hasIncompleteCommand; + signalsChanged = true; + } + if (currentCommand_ != commandName) { + currentCommand_ = commandName; + signalsChanged = true; + } + if (signalsChanged) { + emit currentCommandChanged(); + emit containsInvalidCommandChanged(); + emit containsIncompleteCommandChanged(); + } } void @@ -263,7 +319,7 @@ InputBar::setText(const QString &newText) if (history_.size() == INPUT_HISTORY_SIZE) history_.pop_back(); - updateAtRoom(QLatin1String("")); + updateTextContentProperties(QLatin1String("")); emit textChanged(newText); } void @@ -284,7 +340,7 @@ InputBar::updateState(int selectionStart_, history_.front() = text_; history_index_ = 0; - updateAtRoom(text_); + updateTextContentProperties(text_); // disabled, as it moves the cursor to the end // emit textChanged(text_); } @@ -312,7 +368,7 @@ InputBar::previousText() else if (text().isEmpty()) history_index_--; - updateAtRoom(text()); + updateTextContentProperties(text()); return text(); } @@ -323,7 +379,7 @@ InputBar::nextText() if (history_index_ >= INPUT_HISTORY_SIZE) history_index_ = 0; - updateAtRoom(text()); + updateTextContentProperties(text()); return text(); } @@ -341,20 +397,12 @@ InputBar::send() auto wasEdit = !room->edit().isEmpty(); - if (text().startsWith('/')) { - int command_end = text().indexOf(QRegularExpression(QStringLiteral("\\s"))); - if (command_end == -1) - command_end = text().size(); - auto name = text().mid(1, command_end - 1); - auto args = text().mid(command_end + 1); - if (name.isEmpty() || name == QLatin1String("/")) { - message(args); - } else { - command(name, args); - } - } else { + auto [commandName, args] = getCommandAndArgs(); + updateTextContentProperties(text()); + if (containsIncompleteCommand_) + return; + if (commandName.isEmpty() || !command(commandName, args)) message(text()); - } if (!wasEdit) { history_.push_front(QLatin1String("")); @@ -716,6 +764,24 @@ InputBar::video(const QString &filename, room->sendMessageEvent(video, mtx::events::EventType::RoomMessage); } +QPair<QString, QString> +InputBar::getCommandAndArgs(const QString &currentText) const +{ + if (!currentText.startsWith('/')) + return {{}, currentText}; + + int command_end = currentText.indexOf(QRegularExpression(QStringLiteral("\\s"))); + if (command_end == -1) + command_end = currentText.size(); + auto name = currentText.mid(1, command_end - 1); + auto args = currentText.mid(command_end + 1); + if (name.isEmpty() || name == QLatin1String("/")) { + return {{}, currentText}; + } else { + return {name, args}; + } +} + void InputBar::sticker(CombinedImagePackModel *model, int row) { @@ -741,7 +807,7 @@ InputBar::sticker(CombinedImagePackModel *model, int row) room->sendMessageEvent(sticker, mtx::events::EventType::Sticker); } -void +bool InputBar::command(const QString &command, QString args) { if (command == QLatin1String("me")) { @@ -829,16 +895,16 @@ InputBar::command(const QString &command, QString args) // 1 - Going directly to a given event ID if (args[0] == '$') { room->showEvent(args); - return; + return true; } // 2 - Going directly to a given message index if (args[0] >= '0' && args[0] <= '9') { room->showEvent(args); - return; + return true; } // 3 - Matrix URI handler, as if you clicked the URI if (ChatPage::instance()->handleMatrixUri(args)) { - return; + return true; } nhlog::net()->error("Could not resolve goto: {}", args.toStdString()); } else if (command == QLatin1String("converttodm")) { @@ -846,7 +912,11 @@ InputBar::command(const QString &command, QString args) cache::getMembers(this->room->roomId().toStdString(), 0, -1)); } else if (command == QLatin1String("converttoroom")) { utils::removeDirectFromRoom(this->room->roomId()); + } else { + return false; } + + return true; } MediaUpload::MediaUpload(std::unique_ptr<QIODevice> source_, diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h
index 80ad7f47..acafd964 100644 --- a/src/timeline/InputBar.h +++ b/src/timeline/InputBar.h
@@ -173,6 +173,11 @@ class InputBar final : public QObject Q_OBJECT Q_PROPERTY(bool uploading READ uploading NOTIFY uploadingChanged) Q_PROPERTY(bool containsAtRoom READ containsAtRoom NOTIFY containsAtRoomChanged) + Q_PROPERTY( + bool containsInvalidCommand READ containsInvalidCommand NOTIFY containsInvalidCommandChanged) + Q_PROPERTY(bool containsIncompleteCommand READ containsIncompleteCommand NOTIFY + containsIncompleteCommandChanged) + Q_PROPERTY(QString currentCommand READ currentCommand NOTIFY currentCommandChanged) Q_PROPERTY(QString text READ text NOTIFY textChanged) Q_PROPERTY(QVariantList uploads READ uploads NOTIFY uploadsChanged) @@ -198,6 +203,9 @@ public slots: void setText(const QString &newText); [[nodiscard]] bool containsAtRoom() const { return containsAtRoom_; } + bool containsInvalidCommand() const { return containsInvalidCommand_; } + bool containsIncompleteCommand() const { return containsIncompleteCommand_; } + QString currentCommand() const { return currentCommand_; } void send(); bool tryPasteAttachment(bool fromMouse); @@ -225,13 +233,16 @@ signals: void textChanged(QString newText); void uploadingChanged(bool value); void containsAtRoomChanged(); + void containsInvalidCommandChanged(); + void containsIncompleteCommandChanged(); + void currentCommandChanged(); void uploadsChanged(); private: void emote(const QString &body, bool rainbowify); void notice(const QString &body, bool rainbowify); void confetti(const QString &body, bool rainbowify); - void command(const QString &name, QString args); + bool command(const QString &name, QString args); void image(const QString &filename, const std::optional<mtx::crypto::EncryptedFile> &file, const QString &url, @@ -267,6 +278,8 @@ private: const QSize &thumbnailDimensions, const QString &blurhash); + QPair<QString, QString> getCommandAndArgs() const { return getCommandAndArgs(text()); } + QPair<QString, QString> getCommandAndArgs(const QString &currentText) const; mtx::common::Relations generateRelations() const; void startUploadFromPath(const QString &path); @@ -280,7 +293,7 @@ private: } } - void updateAtRoom(const QString &t); + void updateTextContentProperties(const QString &t); QTimer typingRefresh_; QTimer typingTimeout_; @@ -288,8 +301,11 @@ private: std::deque<QString> history_; std::size_t history_index_ = 0; int selectionStart = 0, selectionEnd = 0, cursorPosition = 0; - bool uploading_ = false; - bool containsAtRoom_ = false; + bool uploading_ = false; + bool containsAtRoom_ = false; + bool containsInvalidCommand_ = false; + bool containsIncompleteCommand_ = false; + QString currentCommand_; using UploadHandle = std::unique_ptr<MediaUpload, DeleteLaterDeleter>; std::vector<UploadHandle> unconfirmedUploads;