summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--man/nheko.1.adoc8
-rw-r--r--resources/qml/TimelineView.qml10
-rw-r--r--src/CommandCompleter.cpp12
-rw-r--r--src/CommandCompleter.h2
-rw-r--r--src/timeline/InputBar.cpp26
-rw-r--r--src/timeline/InputBar.h2
-rw-r--r--src/timeline/RoomlistModel.h2
-rw-r--r--src/ui/UserProfile.cpp17
-rw-r--r--src/ui/UserProfile.h2
9 files changed, 80 insertions, 1 deletions
diff --git a/man/nheko.1.adoc b/man/nheko.1.adoc
index cc4b8f74..5bd5d622 100644
--- a/man/nheko.1.adoc
+++ b/man/nheko.1.adoc
@@ -229,6 +229,14 @@ Inserts `┯━┯╭( º _ º╭)`
 */sovietflip*::
 Inserts `ノ┬─┬ノ ︵ ( \\o°o)\\`
 
+=== User management
+
+*/ignore* _<username>_::
+Ignore a user, invites from them are also rejected.
+
+*/unignore* _<username>_::
+Stops ignoring a user.
+
 === Advanced
 
 */clear-timeline*::
diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml
index f66df94f..0a255491 100644
--- a/resources/qml/TimelineView.qml
+++ b/resources/qml/TimelineView.qml
@@ -279,6 +279,16 @@ Item {
         }
         FlatButton {
             Layout.alignment: Qt.AlignHCenter
+            text: qsTr("decline invite and ignore user")
+            visible: roomPreview && roomPreview.isInvite
+
+            onClicked: {
+                var inviter = TimelineManager.getGlobalUserProfile(roomPreview.inviterUserId)
+                inviter.ignored = true
+            }
+        }
+        FlatButton {
+            Layout.alignment: Qt.AlignHCenter
             text: qsTr("leave")
             visible: !!room
 
diff --git a/src/CommandCompleter.cpp b/src/CommandCompleter.cpp
index 8123b8e6..ee666559 100644
--- a/src/CommandCompleter.cpp
+++ b/src/CommandCompleter.cpp
@@ -97,6 +97,10 @@ CommandCompleter::data(const QModelIndex &index, int role) const
                 return QStringLiteral("/converttodm");
             case ConvertToRoom:
                 return QStringLiteral("/converttoroom");
+            case Ignore:
+                return QStringLiteral("/ignore");
+            case Unignore:
+                return QStringLiteral("/unignore");
             default:
                 return {};
             }
@@ -170,6 +174,10 @@ CommandCompleter::data(const QModelIndex &index, int role) const
                 return QStringLiteral("/converttodm");
             case ConvertToRoom:
                 return QStringLiteral("/converttoroom");
+            case Ignore:
+                return QStringLiteral("/ignore <@userid>");
+            case Unignore:
+                return QStringLiteral("/unignore <@userid>");
             default:
                 return {};
             }
@@ -243,6 +251,10 @@ CommandCompleter::data(const QModelIndex &index, int role) const
                 return tr("Convert this room to a direct chat.");
             case ConvertToRoom:
                 return tr("Convert this direct chat into a room.");
+            case Ignore:
+                return tr("Ignore a user.");
+            case Unignore:
+                return tr("Stop ignoring a user.");
             default:
                 return {};
             }
diff --git a/src/CommandCompleter.h b/src/CommandCompleter.h
index 4f27fe29..35ce2b36 100644
--- a/src/CommandCompleter.h
+++ b/src/CommandCompleter.h
@@ -51,6 +51,8 @@ public:
         Goto,
         ConvertToDm,
         ConvertToRoom,
+        Ignore,
+        Unignore,
         COUNT,
     };
 
diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp
index d37e403f..03ae5658 100644
--- a/src/timeline/InputBar.cpp
+++ b/src/timeline/InputBar.cpp
@@ -30,6 +30,7 @@
 #include "ChatPage.h"
 #include "EventAccessors.h"
 #include "Logging.h"
+#include "MainWindow.h"
 #include "MatrixClient.h"
 #include "TimelineModel.h"
 #include "TimelineViewManager.h"
@@ -239,7 +240,9 @@ InputBar::updateTextContentProperties(const QString &t)
                                              QStringLiteral("msgtype"),
                                              QStringLiteral("goto"),
                                              QStringLiteral("converttodm"),
-                                             QStringLiteral("converttoroom")};
+                                             QStringLiteral("converttoroom"),
+                                             QStringLiteral("ignore"),
+                                             QStringLiteral("unignore")};
     bool hasInvalidCommand    = !commandName.isNull() && !validCommands.contains(commandName);
     bool hasIncompleteCommand = hasInvalidCommand && '/' + commandName == t;
 
@@ -937,6 +940,10 @@ 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 if (command == QLatin1String("ignore")) {
+        this->toggleIgnore(args, true);
+    } else if (command == QLatin1String("unignore")) {
+        this->toggleIgnore(args, false);
     } else {
         return false;
     }
@@ -944,6 +951,23 @@ InputBar::command(const QString &command, QString args)
     return true;
 }
 
+void
+InputBar::toggleIgnore(const QString &user, const bool ignored)
+{
+    UserProfile *profile = new UserProfile(QString(), user, TimelineViewManager::instance());
+    connect(profile, &UserProfile::failedToFetchProfile, [user, profile] {
+        MainWindow::instance()->showNotification(tr("Failed to fetch user %1").arg(user));
+        profile->deleteLater();
+    });
+
+    connect(
+      profile, &UserProfile::globalUsernameRetrieved, [profile, ignored](const QString &user_id) {
+          Q_UNUSED(user_id)
+          profile->setIgnored(ignored);
+          profile->deleteLater();
+      });
+}
+
 MediaUpload::MediaUpload(std::unique_ptr<QIODevice> source_,
                          const QString &mimetype,
                          const QString &originalFilename,
diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h
index b15377fc..fbf08343 100644
--- a/src/timeline/InputBar.h
+++ b/src/timeline/InputBar.h
@@ -283,6 +283,8 @@ private:
 
     void updateTextContentProperties(const QString &t);
 
+    void toggleIgnore(const QString &user, const bool ignored);
+
     QTimer typingRefresh_;
     QTimer typingTimeout_;
     TimelineModel *room;
diff --git a/src/timeline/RoomlistModel.h b/src/timeline/RoomlistModel.h
index 34bf3f9a..2294864f 100644
--- a/src/timeline/RoomlistModel.h
+++ b/src/timeline/RoomlistModel.h
@@ -197,6 +197,8 @@ public:
         return instance_;
     }
 
+    static FilteredRoomlistModel *instance() { return instance_; }
+
     bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
     bool filterAcceptsRow(int sourceRow, const QModelIndex &) const override;
 
diff --git a/src/ui/UserProfile.cpp b/src/ui/UserProfile.cpp
index 338f3658..c7254e23 100644
--- a/src/ui/UserProfile.cpp
+++ b/src/ui/UserProfile.cpp
@@ -278,6 +278,17 @@ UserProfile::setIgnored(bool ignore)
                 .arg(userid, QString::fromStdString(e->matrix_error.error)));
         }
     });
+
+    if (ignore) {
+        const QHash<QString, RoomInfo> invites = cache::invites();
+        FilteredRoomlistModel *room_model      = FilteredRoomlistModel::instance();
+
+        for (auto room = invites.keyBegin(), end = invites.keyEnd(); room != end; room++) {
+            if (room_model->getRoomPreviewById(*room).inviterUserId() == userid) {
+                room_model->declineInvite(*room);
+            }
+        }
+    }
 }
 
 void
@@ -592,12 +603,18 @@ UserProfile::getGlobalProfileData()
                 emit avatarUrlChanged();
             });
 
+    connect(profProx.get(),
+            &UserProfileFetchProxy::failedToFetchProfile,
+            this,
+            &UserProfile::failedToFetchProfile);
+
     http::client()->get_profile(userid_.toStdString(),
                                 [prox = std::move(profProx), user = userid_.toStdString()](
                                   const mtx::responses::Profile &res, mtx::http::RequestErr err) {
                                     if (err) {
                                         nhlog::net()->warn("failed to retrieve profile info for {}",
                                                            user);
+                                        emit prox->failedToFetchProfile();
                                         return;
                                     }
 
diff --git a/src/ui/UserProfile.h b/src/ui/UserProfile.h
index bc5b6a35..64dbf99c 100644
--- a/src/ui/UserProfile.h
+++ b/src/ui/UserProfile.h
@@ -45,6 +45,7 @@ public:
 
 signals:
     void profileFetched(mtx::responses::Profile);
+    void failedToFetchProfile();
 };
 
 class DeviceInfo
@@ -205,6 +206,7 @@ signals:
     void globalUsernameRetrieved(const QString &globalUser);
     void devicesChanged();
     void ignoredChanged();
+    void failedToFetchProfile();
 
     // internal
     void verificationStatiChanged();