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* __:: +Ignore a user, invites from them are also rejected. + +*/unignore* __:: +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 @@ -277,6 +277,16 @@ Item { onClicked: Rooms.declineInvite(roomPreview.roomid) } + 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") diff --git a/src/CommandCompleter.cpp b/src/CommandCompleter.cpp index e1b91a8c..ee666559 100644 --- a/src/CommandCompleter.cpp +++ b/src/CommandCompleter.cpp @@ -99,6 +99,8 @@ CommandCompleter::data(const QModelIndex &index, int role) const return QStringLiteral("/converttoroom"); case Ignore: return QStringLiteral("/ignore"); + case Unignore: + return QStringLiteral("/unignore"); default: return {}; } @@ -174,6 +176,8 @@ CommandCompleter::data(const QModelIndex &index, int role) const return QStringLiteral("/converttoroom"); case Ignore: return QStringLiteral("/ignore <@userid>"); + case Unignore: + return QStringLiteral("/unignore <@userid>"); default: return {}; } @@ -248,7 +252,9 @@ CommandCompleter::data(const QModelIndex &index, int role) const case ConvertToRoom: return tr("Convert this direct chat into a room."); case Ignore: - return tr("Ignores a user."); + 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 325ebc6d..35ce2b36 100644 --- a/src/CommandCompleter.h +++ b/src/CommandCompleter.h @@ -52,6 +52,7 @@ public: ConvertToDm, ConvertToRoom, Ignore, + Unignore, COUNT, }; diff --git a/src/timeline/InputBar.cpp b/src/timeline/InputBar.cpp index ca320d04..e93f2795 100644 --- a/src/timeline/InputBar.cpp +++ b/src/timeline/InputBar.cpp @@ -241,7 +241,8 @@ InputBar::updateTextContentProperties(const QString &t) QStringLiteral("goto"), QStringLiteral("converttodm"), QStringLiteral("converttoroom"), - QStringLiteral("ignore")}; + QStringLiteral("ignore"), + QStringLiteral("unignore")}; bool hasInvalidCommand = !commandName.isNull() && !validCommands.contains(commandName); bool hasIncompleteCommand = hasInvalidCommand && '/' + commandName == t; @@ -940,15 +941,9 @@ InputBar::command(const QString &command, QString args) } else if (command == QLatin1String("converttoroom")) { utils::removeDirectFromRoom(this->room->roomId()); } else if (command == QLatin1String("ignore")) { - QSharedPointer user( - new UserProfile(QString(), args, TimelineViewManager::instance())); - connect(user.get(), &UserProfile::failedToFetchProfile, [args] { - MainWindow::instance()->showNotification(tr("Failed to fetch user %1").arg(args)); - }); - connect(user.get(), &UserProfile::globalUsernameRetrieved, [user](const QString &user_id) { - Q_UNUSED(user_id) - user->setIgnored(true); - }); + this->setArgIgnored(args, true); + } else if (command == QLatin1String("unignore")) { + this->setArgIgnored(args, false); } else { return false; } @@ -956,6 +951,23 @@ InputBar::command(const QString &command, QString args) return true; } +void +InputBar::setArgIgnored(const QString &user, const bool ignored) +{ + QSharedPointer profile( + new UserProfile(QString(), user, TimelineViewManager::instance())); + connect(profile.get(), &UserProfile::failedToFetchProfile, [user] { + MainWindow::instance()->showNotification(tr("Failed to fetch user %1").arg(user)); + }); + + connect(profile.get(), + &UserProfile::globalUsernameRetrieved, + [profile, ignored](const QString &user_id) { + Q_UNUSED(user_id) + profile->setIgnored(ignored); + }); +} + MediaUpload::MediaUpload(std::unique_ptr source_, const QString &mimetype, const QString &originalFilename, diff --git a/src/timeline/InputBar.h b/src/timeline/InputBar.h index b15377fc..cbde0e07 100644 --- a/src/timeline/InputBar.h +++ b/src/timeline/InputBar.h @@ -283,6 +283,8 @@ private: void updateTextContentProperties(const QString &t); + void setArgIgnored(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 5c63deb2..ffb69aa4 100644 --- a/src/ui/UserProfile.cpp +++ b/src/ui/UserProfile.cpp @@ -278,6 +278,14 @@ UserProfile::setIgnored(bool ignore) .arg(userid, QString::fromStdString(e->matrix_error.error))); } }); + + if (ignore) { + const QHash invites = cache::invites(); + + for (auto room = invites.keyBegin(), end = invites.keyEnd(); room != end; room++) { + FilteredRoomlistModel::instance()->declineInvite(*room); + } + } } void