Show warning when invalid command is entered

Fixes #1363

Please note that this doesn't prompt when you try to send a message with a bad command.
pull/1388/head
Loren Burkholder 2 years ago
parent 9043087c80
commit b6ef00b5ee
  1. 2
      resources/qml/MessageInput.qml
  2. 12
      resources/qml/MessageInputWarning.qml
  3. 19
      resources/qml/TimelineView.qml
  4. 2
      resources/res.qrc
  5. 2
      src/CompletionProxyModel.h
  6. 2
      src/timeline/InputBar.cpp
  7. 60
      src/ui/NhekoGlobalObject.cpp
  8. 3
      src/ui/NhekoGlobalObject.h

@ -13,6 +13,8 @@ import im.nheko 1.0
Rectangle {
id: inputBar
readonly property string text: messageInput.text
color: Nheko.colors.window
Layout.fillWidth: true
Layout.preferredHeight: row.implicitHeight

@ -8,14 +8,20 @@ import QtQuick.Layouts 1.2
import im.nheko 1.0
Item {
implicitHeight: warningRect.visible ? warningDisplay.implicitHeight + 2 * Nheko.paddingSmall : 0
id: warningRoot
required property string text
required property bool isVisible
implicitHeight: isVisible ? warningDisplay.implicitHeight + 2 * Nheko.paddingSmall : 0
height: implicitHeight
Layout.fillWidth: true
Layout.margins: isVisible ? Nheko.paddingSmall : 0
Rectangle {
id: warningRect
visible: (room && room.permissions.canPingRoom() && room.input.containsAtRoom)
visible: warningRoot.isVisible
// TODO: Qt.alpha() would make more sense but it wasn't working...
color: Qt.rgba(Nheko.theme.error.r, Nheko.theme.error.g, Nheko.theme.error.b, 0.3)
border.width: 1
@ -31,7 +37,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Nheko.paddingSmall
color: Nheko.colors.text
text: qsTr("You are about to notify the whole room")
text: warningRoot.text
textFormat: Text.PlainText
}

@ -153,13 +153,30 @@ Item {
UploadBox {
}
NotificationWarning {
MessageInputWarning {
text: qsTr("You are about to notify the whole room")
isVisible: (room && room.permissions.canPingRoom() && room.input.containsAtRoom)
}
MessageInputWarning {
text: qsTr("The command /%1 is not recognized and will be sent as part of your message").arg(Nheko.getCommandFromText(input.text))
isVisible: {
if (!input.text)
return false;
let command = Nheko.getCommandFromText(input.text);
if (Nheko.isInvalidCommand(command) && ("/" + command !== input.text))
return true;
else
return false;
}
}
ReplyPopup {
}
MessageInput {
id: input
}
}

@ -123,7 +123,7 @@
<file>qml/ForwardCompleter.qml</file>
<file>qml/SelfVerificationCheck.qml</file>
<file>qml/TypingIndicator.qml</file>
<file>qml/NotificationWarning.qml</file>
<file>qml/MessageInputWarning.qml</file>
<file>qml/components/AdaptiveLayout.qml</file>
<file>qml/components/AdaptiveLayoutElement.qml</file>
<file>qml/components/AvatarListTile.qml</file>

@ -184,6 +184,8 @@ public slots:
void setSearchString(const QString &s);
QString searchString() const { return searchString_; }
bool hasCompletion() const { return rowCount() > 0; }
signals:
void newSearchString(QString);

@ -846,6 +846,8 @@ 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 {
message("/" + command + " " + args);
}
}

@ -190,3 +190,63 @@ 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);
}

@ -72,6 +72,9 @@ 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();

Loading…
Cancel
Save