Compare commits

...

8 Commits

Author SHA1 Message Date
Joshua Goins
2bb55eece7 Don't flag invite notifications as persistent
These really don't need to be persistent, as they even stick around
when NeoChat is closed. This also spams the user's notification system
usually, if they get lots of invitations at once which don't go away
automatically.

(cherry picked from commit 51197d7c1a)
2024-07-25 16:38:13 -04:00
Joshua Goins
2877e40647 Hint that the user can auto-reject invitations on the invite page
This should help make the new setting more discoverable.

(cherry picked from commit 2a2a2e0c05)
2024-07-25 16:38:13 -04:00
Joshua Goins
768ec242fa Allow blocking invites from people you don't share a room with
Matrix currently has a significant moderation loophole, thanks to
invites. Right now, anyone can invite anyone to a room - and clients
like NeoChat will gladly display these rooms to them and even give you
a notification.

However, this creates a pretty easy attack since room names and avatars
are arbitrary and this is a known vector of harassment in the Matrix
community. There's currently no tools to block this server-side, so
let's try to improve the situation where we can.

This adds a new setting to the Security page, wherein it allows you to
block invites from people you don't share a room with. This prevents the
notification from appearing and NeoChat will attempt to leave the room
immediately.

Since this depends on MSC 2666 - a currently unstable feature - the
server may not support it and NeoChat will disable the setting in this
case.

(cherry picked from commit 07fee30cc0)
2024-07-25 16:38:13 -04:00
Joshua Goins
194751627f Don't display notifications for invite rooms
Sometimes a ghost notification will appear, this is sometimes a stray
m.room.invite notification we didn't handle or some other event. Let's
outright reject all notifications from Invite-type rooms to prevent this
from happening altogether.

(cherry picked from commit 83c6ce0ace)
2024-07-25 16:38:13 -04:00
l10n daemon script
bc701c51d9 GIT_SILENT Sync po/docbooks with svn 2024-07-25 03:13:15 +00:00
l10n daemon script
35939b4af4 GIT_SILENT Sync po/docbooks with svn 2024-07-23 03:14:18 +00:00
l10n daemon script
a178b8b6ca SVN_SILENT made messages (.desktop file) - always resolve ours
In case of conflict in i18n, keep the version of the branch "ours"
To resolve a particular conflict, "git checkout --ours path/to/file.desktop"
2024-07-23 03:04:52 +00:00
Albert Astals Cid
a6994318de GIT_SILENT Upgrade release service version to 24.07.80. 2024-07-21 12:25:07 +02:00
15 changed files with 154 additions and 224 deletions

View File

@@ -9,7 +9,7 @@ cmake_minimum_required(VERSION 3.16)
# KDE Applications version, managed by release script.
set(RELEASE_SERVICE_VERSION_MAJOR "24")
set(RELEASE_SERVICE_VERSION_MINOR "07")
set(RELEASE_SERVICE_VERSION_MICRO "70")
set(RELEASE_SERVICE_VERSION_MICRO "80")
set(RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
project(NeoChat VERSION ${RELEASE_SERVICE_VERSION})

View File

@@ -5467,175 +5467,3 @@ msgstr "Mostra"
#, kde-format
msgid "Quit"
msgstr "Surt"
#~ msgid "Settings"
#~ msgstr "Configuració"
#~ msgid "Room Settings"
#~ msgstr "Configuració de la sala"
#~ msgid "Valid server entered"
#~ msgstr "S'ha introduït un servidor vàlid"
#~ msgid "Enter server url e.g. kde.org"
#~ msgstr "Introduïu l'URL del servidor (p. ex. kde.org)"
#~ msgid "Configure"
#~ msgstr "Configura"
#~ msgctxt "@button"
#~ msgid "Space settings"
#~ msgstr "Configuració dels espais"
#~ msgctxt "@action:button"
#~ msgid "Configure"
#~ msgstr "Configura"
#~ msgctxt "@title:window"
#~ msgid "About NeoChat"
#~ msgstr "Quant al NeoChat"
#~ msgctxt "@title:window"
#~ msgid "About KDE"
#~ msgstr "Quant a KDE"
#~ msgid "Spell Checking"
#~ msgstr "Verificació ortogràfica"
#~ msgctxt "@title"
#~ msgid "Spellchecking"
#~ msgstr "Verificació ortogràfica"
#~ msgid "Enable automatic spell checking"
#~ msgstr "Activa la verificació ortogràfica automàtica"
#~ msgid "Ignore uppercase words"
#~ msgstr "Ignora les paraules en majúscules"
#~ msgid "Ignore hyphenated words"
#~ msgstr "Ignora les paraules amb guió"
#~ msgid "Detect language automatically"
#~ msgstr "Detecta automàticament l'idioma"
#~ msgid "Selected default language:"
#~ msgstr "Idioma predeterminat seleccionat:"
#~ msgid "None"
#~ msgstr "Cap"
#~ msgid "Additional spell checking languages"
#~ msgstr "Idiomes addicionals de verificació ortogràfica"
#~ msgid ""
#~ "%1 will provide spell checking and suggestions for the languages listed "
#~ "here when autodetection is enabled."
#~ msgstr ""
#~ "%1 proporcionarà la verificació ortogràfica i suggeriments per als "
#~ "idiomes llistats aquí si s'ha activat la detecció automàtica."
#~ msgid "Open Personal Dictionary"
#~ msgstr "Obre un diccionari personal"
#~ msgctxt "@title:window"
#~ msgid "Spell checking languages"
#~ msgstr "Idiomes de verificació ortogràfica"
#~ msgid "Default Language"
#~ msgstr "Idioma predeterminat"
#~ msgid "Spell checking dictionary"
#~ msgstr "Diccionari de verificació ortogràfica"
#~ msgid "Add a new word to your personal dictionary…"
#~ msgstr "Afegeix una paraula nova al vostre diccionari personal…"
#~ msgctxt "@action:button"
#~ msgid "Add word"
#~ msgstr "Afegeix una paraula"
#~ msgctxt "@action:button"
#~ msgid "Delete word"
#~ msgstr "Suprimeix la paraula"
#~ msgctxt "menu"
#~ msgid "Matrix FAQ"
#~ msgstr "PMF del Matrix"
#~ msgctxt "@action:button"
#~ msgid "Remove this account"
#~ msgstr "Elimina aquest compte"
#~ msgid "Options"
#~ msgstr "Opcions"
#~ msgid "Make room favorite"
#~ msgstr "Fes preferida la sala"
#~ msgid "Member (0)"
#~ msgstr "Membre (0)"
#~ msgctxt "@title:window"
#~ msgid "Account editor"
#~ msgstr "Editor de comptes"
#~ msgctxt "@title"
#~ msgid "Deactivate Account"
#~ msgstr "Desactiva el compte"
#~ msgctxt "@title"
#~ msgid "Warning"
#~ msgstr "Avís"
#~ msgid "Show fancy effects in chat"
#~ msgstr "Mostra efectes sofisticats al xat"
#~ msgctxt "number of room members"
#~ msgid " members"
#~ msgstr " membres"
#~ msgctxt "@button"
#~ msgid "Add new child"
#~ msgstr "Afegeix un fill nou"
#~ msgid "Log in to an existing account"
#~ msgstr "Inicia la sessió amb un compte existent"
#~ msgid "Open in New Window"
#~ msgstr "Obre en una finestra nova"
#~ msgid "Room not found"
#~ msgstr "No s'ha trobat la sala"
#~ msgid ""
#~ "There's no room %1 in the room list. Check the spelling and the account."
#~ msgstr ""
#~ "No hi ha cap sala %1 a la llista de sales. Comproveu l'ortografia i el "
#~ "compte."
#~ msgid "No application for the link"
#~ msgstr "No hi ha cap aplicació per a l'enllaç"
#~ msgid "Your operating system could not find an application for the link."
#~ msgstr ""
#~ "El sistema operatiu no ha pogut trobar cap aplicació per a l'enllaç."
#~ msgid "Could not open URL"
#~ msgstr "No s'ha pogut obrir l'URL"
#~ msgid "Coach: %1, Seat: %2"
#~ msgstr "Cotxe: %1, Seient: %2"
#~ msgctxt "<start time> - <end time>"
#~ msgid "%1 - %2"
#~ msgstr "%1 - %2"
#~ msgctxt "<username> is not a known user"
#~ msgid "%1 is not a known user."
#~ msgstr "%1 no és un usuari conegut."
#~ msgid "Show m.room.member events"
#~ msgstr "Mostra els esdeveniments de «m.room.member»"
#~ msgid "Show room account data"
#~ msgstr "Mostra les dades de comptatge de la sala"

View File

@@ -7,7 +7,7 @@ msgstr ""
"Project-Id-Version: neochat\n"
"Report-Msgid-Bugs-To: https://bugs.kde.org\n"
"POT-Creation-Date: 2024-07-21 00:39+0000\n"
"PO-Revision-Date: 2024-06-24 22:41+0200\n"
"PO-Revision-Date: 2024-07-07 13:40+0200\n"
"Last-Translator: Vincenzo Reale <smart2128vr@gmail.com>\n"
"Language-Team: Italian <kde-i18n-it@kde.org>\n"
"Language: it\n"
@@ -15,7 +15,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Lokalize 24.05.1\n"
"X-Generator: Lokalize 24.05.2\n"
#: src/chatbar/AttachDialog.qml:29
#, kde-format
@@ -1740,11 +1740,10 @@ msgstr[0] "1 utente: "
msgstr[1] "%1 utenti: "
#: src/models/readmarkermodel.cpp:115
#, fuzzy, kde-format
#| msgid "Unknown event"
#, kde-format
msgctxt "A member who is not in the room has been requested."
msgid "unknown member"
msgstr "Evento sconosciuto"
msgstr "membro sconosciuto"
#: src/models/readmarkermodel.cpp:117
#, kde-format
@@ -1899,11 +1898,10 @@ msgid "Open Key Backup"
msgstr "Apri backup chiave"
#: src/qml/AccountMenu.qml:66
#, fuzzy, kde-format
#| msgid "Verify device"
#, kde-format
msgctxt "@action:inmenu"
msgid "Verify this Device"
msgstr "Verifica il dispositivo"
msgstr "Verifica questo dispositivo"
#: src/qml/AccountMenu.qml:72 src/settings/AccountsPage.qml:88
#, kde-format
@@ -2187,8 +2185,7 @@ msgid "Off"
msgstr "Spento"
#: src/qml/ContextMenu.qml:111
#, fuzzy, kde-format
#| msgid "Room Settings"
#, kde-format
msgctxt "@action:inmenu"
msgid "Room Settings"
msgstr "Impostazioni della stanza"
@@ -2209,8 +2206,7 @@ msgid "Add to Favourites"
msgstr "Aggiungi ai preferiti"
#: src/qml/ContextMenu.qml:187
#, fuzzy, kde-format
#| msgid "Room Settings"
#, kde-format
msgctxt "@action:button"
msgid "Room Settings"
msgstr "Impostazioni della stanza"
@@ -3067,8 +3063,7 @@ msgid "Insert link"
msgstr "Inserisci collegamento"
#: src/qml/QuickSwitcher.qml:29
#, fuzzy, kde-format
#| msgid "No rooms found"
#, kde-format
msgctxt "Placeholder message"
msgid "No room found"
msgstr "Nessuna stanza trovata"
@@ -3158,8 +3153,7 @@ msgid "Configure room"
msgstr "Configura la stanza"
#: src/qml/RoomDrawer.qml:104 src/qml/RoomDrawerPage.qml:45
#, fuzzy, kde-format
#| msgid "Room settings"
#, kde-format
msgctxt "@action:button"
msgid "Room settings"
msgstr "Impostazioni della stanza"
@@ -3204,11 +3198,10 @@ msgid "Search"
msgstr "Cerca"
#: src/qml/RoomInformation.qml:95
#, fuzzy, kde-format
#| msgid "Verify device"
#, kde-format
msgctxt "@action:button"
msgid "Verify user"
msgstr "Verifica il dispositivo"
msgstr "Verifica l'utente"
#: src/qml/RoomInformation.qml:106
#, kde-format
@@ -3426,10 +3419,9 @@ msgid "This server cannot be resolved or has already been added"
msgstr "Questo server non può essere risolto o è già stato aggiunto"
#: src/qml/ServerComboBox.qml:152
#, fuzzy, kde-format
#| msgid "Server URL"
#, kde-format
msgid "Server URL:"
msgstr "URL del server"
msgstr "URL del server:"
#: src/qml/ShareAction.qml:23
#, kde-format
@@ -4694,11 +4686,10 @@ msgstr "Informazioni su Neochat"
#: src/settings/NeoChatSettingsView.qml:99
#: src/settings/NeoChatSettingsView.qml:106
#, fuzzy, kde-format
#| msgid "About KDE"
#, kde-format
msgctxt "@title:group"
msgid "About"
msgstr "Informazioni su KDE"
msgstr "Informazioni"
#: src/settings/NeoChatSettingsView.qml:103
#, kde-format
@@ -5156,15 +5147,13 @@ msgstr ""
"in cui sono entrati nella stanza virtuale."
#: src/settings/RoomSettingsView.qml:28
#, fuzzy, kde-format
#| msgid "Space Settings"
#, kde-format
msgctxt "@title:window"
msgid "Space Settings"
msgstr "Impostazioni degli spazi"
#: src/settings/RoomSettingsView.qml:30
#, fuzzy, kde-format
#| msgid "Room Settings"
#, kde-format
msgctxt "@title:window"
msgid "Room Settings"
msgstr "Impostazioni della stanza"

View File

@@ -14,8 +14,8 @@ msgstr ""
"X-Crowdin-Project: kdeorg\n"
"X-Crowdin-Project-ID: 269464\n"
"X-Crowdin-Language: zh-CN\n"
"X-Crowdin-File: /kf6-trunk/messages/neochat/neochat.pot\n"
"X-Crowdin-File-ID: 44721\n"
"X-Crowdin-File: /kf6-stable/messages/neochat/neochat.pot\n"
"X-Crowdin-File-ID: 49732\n"
#: src/chatbar/AttachDialog.qml:29
#, kde-format

View File

@@ -134,6 +134,8 @@ add_library(neochat STATIC
jobs/neochatdeletedevicejob.h
jobs/neochatchangepasswordjob.cpp
jobs/neochatchangepasswordjob.h
jobs/neochatgetcommonroomsjob.cpp
jobs/neochatgetcommonroomsjob.h
mediasizehelper.cpp
mediasizehelper.h
eventhandler.cpp

View File

@@ -0,0 +1,14 @@
// SPDX-FileCopyrightText: 2024 Joshua Goins <josh@redstrate.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "neochatgetcommonroomsjob.h"
using namespace Quotient;
NeochatGetCommonRoomsJob::NeochatGetCommonRoomsJob(const QString &userId)
: BaseJob(HttpVerb::Get,
QStringLiteral("GetCommonRoomsJob"),
QStringLiteral("/_matrix/client/unstable/uk.half-shot.msc2666/user/mutual_rooms").toLatin1(),
QUrlQuery({{QStringLiteral("user_id"), userId}}))
{
}

View File

@@ -0,0 +1,14 @@
// SPDX-FileCopyrightText: 2024 Joshua Goins <josh@redstrate.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <Quotient/jobs/basejob.h>
#include <Quotient/omittable.h>
// TODO: Upstream to libQuotient
class NeochatGetCommonRoomsJob : public Quotient::BaseJob
{
public:
explicit NeochatGetCommonRoomsJob(const QString &userId);
};

View File

@@ -255,7 +255,7 @@ Action=Popup
Name=Share
Name[ar]=شارك
Name[ca]=Compartició
Name[ca@valencia]=Compartició
Name[ca@valencia]=Compartiu
Name[cs]=Sdílet
Name[en_GB]=Share
Name[eo]=Kundividi

View File

@@ -187,5 +187,11 @@
<default>false</default>
</entry>
</group>
<group name="Security">
<entry name="RejectUnknownInvites" type="bool">
<label>Reject unknown invites</label>
<default>false</default>
</entry>
</group>
</kcfg>

View File

@@ -25,6 +25,7 @@
#include <Quotient/csapi/content-repo.h>
#include <Quotient/csapi/profile.h>
#include <Quotient/csapi/versions.h>
#include <Quotient/database.h>
#include <Quotient/jobs/downloadfilejob.h>
#include <Quotient/qt_connection_util.h>
@@ -132,6 +133,21 @@ void NeoChatConnection::connectSignals()
Q_EMIT homeNotificationsChanged();
Q_EMIT homeHaveHighlightNotificationsChanged();
});
// Fetch unstable features
// TODO: Expose unstableFeatures() in libQuotient
connect(
this,
&Connection::connected,
this,
[this] {
auto job = callApi<GetVersionsJob>(BackgroundRequest);
connect(job, &GetVersionsJob::success, this, [this, job] {
m_canCheckMutualRooms = job->unstableFeatures().contains("uk.half-shot.msc2666.query_mutual_rooms"_ls);
Q_EMIT canCheckMutualRoomsChanged();
});
},
Qt::SingleShotConnection);
}
int NeoChatConnection::badgeNotificationCount() const
@@ -200,6 +216,11 @@ QVariantList NeoChatConnection::getSupportedRoomVersions() const
return supportedRoomVersions;
}
bool NeoChatConnection::canCheckMutualRooms() const
{
return m_canCheckMutualRooms;
}
void NeoChatConnection::changePassword(const QString &currentPassword, const QString &newPassword)
{
auto job = callApi<NeochatChangePasswordJob>(newPassword, false);

View File

@@ -79,6 +79,11 @@ class NeoChatConnection : public Quotient::Connection
*/
Q_PROPERTY(bool isOnline READ isOnline WRITE setIsOnline NOTIFY isOnlineChanged)
/**
* @brief Whether the server supports querying a user's mutual rooms.
*/
Q_PROPERTY(bool canCheckMutualRooms READ canCheckMutualRooms NOTIFY canCheckMutualRoomsChanged)
public:
/**
* @brief Defines the status after an attempt to change the password on an account.
@@ -95,6 +100,7 @@ public:
Q_INVOKABLE void logout(bool serverSideLogout);
Q_INVOKABLE QVariantList getSupportedRoomVersions() const;
bool canCheckMutualRooms() const;
/**
* @brief Change the password for an account.
@@ -196,6 +202,7 @@ Q_SIGNALS:
void passwordStatus(NeoChatConnection::PasswordStatus status);
void userConsentRequired(QUrl url);
void badgeNotificationCountChanged(NeoChatConnection *connection, int count);
void canCheckMutualRoomsChanged();
private:
bool m_isOnline = true;
@@ -208,4 +215,6 @@ private:
int m_badgeNotificationCount = 0;
QHash<QUrl, LinkPreviewer *> m_linkPreviewers;
bool m_canCheckMutualRooms = false;
};

View File

@@ -41,6 +41,7 @@
#include "events/joinrulesevent.h"
#include "events/pollevent.h"
#include "filetransferpseudojob.h"
#include "jobs/neochatgetcommonroomsjob.h"
#include "neochatconfig.h"
#include "notificationsmanager.h"
#include "roomlastmessageprovider.h"
@@ -129,14 +130,38 @@ NeoChatRoom::NeoChatRoom(Connection *connection, QString roomId, JoinState joinS
return;
}
auto roomMemberEvent = currentState().get<RoomMemberEvent>(localMember().id());
QImage avatar_image;
if (roomMemberEvent && !member(roomMemberEvent->senderId()).avatarUrl().isEmpty()) {
avatar_image = memberAvatar(roomMemberEvent->senderId()).get(this->connection(), 128, [] {});
auto showNotification = [this, roomMemberEvent] {
QImage avatar_image;
if (roomMemberEvent && !member(roomMemberEvent->senderId()).avatarUrl().isEmpty()) {
avatar_image = memberAvatar(roomMemberEvent->senderId()).get(this->connection(), 128, [] {});
} else {
qWarning() << "using this room's avatar";
avatar_image = avatar(128);
}
NotificationsManager::instance().postInviteNotification(this,
displayName(),
member(roomMemberEvent->senderId()).htmlSafeDisplayName(),
avatar_image);
};
if (NeoChatConfig::rejectUnknownInvites()) {
auto job = this->connection()->callApi<NeochatGetCommonRoomsJob>(roomMemberEvent->senderId());
connect(job, &BaseJob::result, this, [this, job, roomMemberEvent, showNotification] {
QJsonObject replyData = job->jsonData();
if (replyData.contains(QStringLiteral("joined"))) {
const bool inAnyOfOurRooms = !replyData[QStringLiteral("joined")].toArray().isEmpty();
if (inAnyOfOurRooms) {
showNotification();
} else {
leaveRoom();
}
}
});
} else {
qWarning() << "using this room's avatar";
avatar_image = avatar(128);
showNotification();
}
NotificationsManager::instance().postInviteNotification(this, displayName(), member(roomMemberEvent->senderId()).htmlSafeDisplayName(), avatar_image);
},
Qt::SingleShotConnection);
connect(this, &Room::changed, this, [this] {
@@ -1313,7 +1338,6 @@ void NeoChatRoom::setPushNotificationState(PushNotificationState::State state)
m_currentPushNotificationState = state;
Q_EMIT pushNotificationStateChanged(m_currentPushNotificationState);
}
void NeoChatRoom::updatePushNotificationState(QString type)

View File

@@ -110,6 +110,12 @@ void NotificationsManager::processNotificationJob(QPointer<NeoChatConnection> co
}
auto sender = room->member(notification["event"_ls]["sender"_ls].toString());
// Don't display notifications for events in invited rooms
// This should prevent empty notifications from appearing when they shouldn't
if (room->joinState() == JoinState::Invite) {
continue;
}
QString body;
if (notification["event"_ls]["type"_ls].toString() == "org.matrix.msc3381.poll.start"_ls) {
body = notification["event"_ls]["content"_ls]["org.matrix.msc3381.poll.start"_ls]["question"_ls]["body"_ls].toString();
@@ -243,7 +249,6 @@ void NotificationsManager::postInviteNotification(NeoChatRoom *rawRoom, const QS
notification->setText(i18n("%1 invited you to a room", sender));
notification->setTitle(title);
notification->setPixmap(createNotificationImage(icon, nullptr));
notification->setFlags(KNotification::Persistent);
auto defaultAction = notification->addDefaultAction(i18n("Open this invitation in NeoChat"));
connect(defaultAction, &KNotificationAction::activated, this, [notification, room]() {
if (!room) {

View File

@@ -15,7 +15,10 @@ Kirigami.PlaceholderMessage {
required property NeoChatRoom currentRoom
text: i18n("Accept this invitation?")
explanation: root.currentRoom.connection.canCheckMutualRooms ? i18n("You can reject invitations from unknown users under Security settings.") : ""
RowLayout {
Layout.alignment: Qt.AlignHCenter
QQC2.Button {
Layout.alignment: Qt.AlignHCenter
text: i18nc("@action:button The thing being rejected is an invitation to chat", "Reject and ignore user")

View File

@@ -16,6 +16,32 @@ FormCard.FormCardPage {
title: i18nc("@title", "Security")
FormCard.FormHeader {
title: i18nc("@title:group", "Invitations")
}
FormCard.FormCard {
FormCard.FormCheckDelegate {
text: i18nc("@option:check", "Reject invitations from unknown users")
description: connection.canCheckMutualRooms ? i18n("If enabled, NeoChat will reject invitations from from users you don't share a room with.") : i18n("Your server does not support this setting.")
checked: Config.rejectUnknownInvites
enabled: !Config.isRejectUnknownInvitesImmutable && connection.canCheckMutualRooms
onToggled: {
Config.rejectUnknownInvites = checked;
Config.save();
}
}
}
FormCard.FormHeader {
title: i18nc("@title:group", "Ignored Users")
}
FormCard.FormCard {
FormCard.FormButtonDelegate {
text: i18nc("@action:button", "Manage ignored users")
onClicked: root.ApplicationWindow.window.pageStack.push(ignoredUsersDialogComponent, {}, {
title: i18nc("@title:window", "Ignored Users")
});
}
}
FormCard.FormHeader {
title: i18nc("@title", "Keys")
}
@@ -33,17 +59,6 @@ FormCard.FormCardPage {
description: i18n("Device id")
}
}
FormCard.FormHeader {
title: i18nc("@title:group", "Ignored Users")
}
FormCard.FormCard {
FormCard.FormButtonDelegate {
text: i18nc("@action:button", "Manage ignored users")
onClicked: pageStack.pushDialogLayer(ignoredUsersDialogComponent, {}, {
title: i18nc("@title:window", "Ignored Users")
});
}
}
Component {
id: ignoredUsersDialogComponent