diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp
index 5184ba94..6c882cd4 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,54 @@ InputBar::updateAtRoom(const QString &t)
this->containsAtRoom_ = roomMention;
emit containsAtRoomChanged();
}
+
+ // check for invalid commands
+ auto commandName = getCommandAndArgs().first;
+ bool hasInvalidCommand{};
+ if (!commandName.isNull() && '/' + commandName != text()) {
+ static const QStringList 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")};
+ hasInvalidCommand = !validCommands.contains(commandName);
+ } else
+ hasInvalidCommand = false;
+
+ if (containsInvalidCommand_ != hasInvalidCommand) {
+ containsInvalidCommand_ = hasInvalidCommand;
+ emit containsInvalidCommandChanged();
+ }
+ if (currentCommand_ != commandName) {
+ currentCommand_ = commandName;
+ emit currentCommandChanged();
+ }
}
void
@@ -263,7 +312,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 +333,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 +361,7 @@ InputBar::previousText()
else if (text().isEmpty())
history_index_--;
- updateAtRoom(text());
+ updateTextContentProperties(text());
return text();
}
@@ -323,7 +372,7 @@ InputBar::nextText()
if (history_index_ >= INPUT_HISTORY_SIZE)
history_index_ = 0;
- updateAtRoom(text());
+ updateTextContentProperties(text());
return text();
}
@@ -341,20 +390,11 @@ 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();
+ if (commandName.isNull())
message(text());
- }
+ else
+ command(commandName, args);
if (!wasEdit) {
history_.push_front(QLatin1String(""));
@@ -716,6 +756,24 @@ InputBar::video(const QString &filename,
room->sendMessageEvent(video, mtx::events::EventType::RoomMessage);
}
+QPair<QString, QString>
+InputBar::getCommandAndArgs() const
+{
+ if (!text().startsWith('/'))
+ return {{}, text()};
+
+ 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("/")) {
+ return {{}, text()};
+ } else {
+ return {name, args};
+ }
+}
+
void
InputBar::sticker(CombinedImagePackModel *model, int row)
{
diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h
index 80ad7f47..7385d272 100644
--- a/src/timeline/InputBar.h
+++ b/src/timeline/InputBar.h
@@ -173,6 +173,9 @@ 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(QString currentCommand READ currentCommand NOTIFY currentCommandChanged)
Q_PROPERTY(QString text READ text NOTIFY textChanged)
Q_PROPERTY(QVariantList uploads READ uploads NOTIFY uploadsChanged)
@@ -198,6 +201,8 @@ public slots:
void setText(const QString &newText);
[[nodiscard]] bool containsAtRoom() const { return containsAtRoom_; }
+ bool containsInvalidCommand() const { return containsInvalidCommand_; }
+ QString currentCommand() const { return currentCommand_; }
void send();
bool tryPasteAttachment(bool fromMouse);
@@ -225,6 +230,8 @@ signals:
void textChanged(QString newText);
void uploadingChanged(bool value);
void containsAtRoomChanged();
+ void containsInvalidCommandChanged();
+ void currentCommandChanged();
void uploadsChanged();
private:
@@ -267,6 +274,7 @@ private:
const QSize &thumbnailDimensions,
const QString &blurhash);
+ QPair<QString, QString> getCommandAndArgs() const;
mtx::common::Relations generateRelations() const;
void startUploadFromPath(const QString &path);
@@ -280,7 +288,7 @@ private:
}
}
- void updateAtRoom(const QString &t);
+ void updateTextContentProperties(const QString &t);
QTimer typingRefresh_;
QTimer typingTimeout_;
@@ -288,8 +296,10 @@ 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;
+ QString currentCommand_;
using UploadHandle = std::unique_ptr<MediaUpload, DeleteLaterDeleter>;
std::vector<UploadHandle> unconfirmedUploads;
diff --git a/src/ui/NhekoGlobalObject.cpp b/src/ui/NhekoGlobalObject.cpp
index 3cb6a8a8..a6f9abe7 100644
--- a/src/ui/NhekoGlobalObject.cpp
+++ b/src/ui/NhekoGlobalObject.cpp
@@ -190,63 +190,3 @@ Nheko::setWindowRole([[maybe_unused]] QWindow *win, [[maybe_unused]] QString new
QXcbWindowFunctions::setWmWindowRole(win, newRole.toUtf8());
#endif
}
-
-QString
-Nheko::getCommandFromText(const QString &text)
-{
- if (text.startsWith('/')) {
- int command_end = text.indexOf(QRegularExpression(QStringLiteral("\\s")));
- if (command_end == -1)
- command_end = text.size();
- auto command = text.mid(1, command_end - 1);
- if (command.isEmpty() || command == QLatin1String("/"))
- return {};
- else {
- return command;
- }
- } else
- return {};
-}
-
-bool
-Nheko::isInvalidCommand(QString command) const
-{
- if (command.size() <= 0)
- return false;
-
- static const QStringList 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")};
-
- if (!command.startsWith('/'))
- command.prepend('/');
- return !validCommands.contains(command);
-}
diff --git a/src/ui/NhekoGlobalObject.h b/src/ui/NhekoGlobalObject.h
index 1ea2c109..b7a7a637 100644
--- a/src/ui/NhekoGlobalObject.h
+++ b/src/ui/NhekoGlobalObject.h
@@ -72,9 +72,6 @@ public:
Q_INVOKABLE void setTransientParent(QWindow *window, QWindow *parentWindow) const;
Q_INVOKABLE void setWindowRole(QWindow *win, QString newRole) const;
- Q_INVOKABLE QString getCommandFromText(const QString &text);
- Q_INVOKABLE bool isInvalidCommand(QString command) const;
-
public slots:
void updateUserProfile();
|