mirror of
https://github.com/KDE/latte-dock.git
synced 2024-12-28 03:21:38 +03:00
smarter badges identifier for activation shortcuts
--with this commit now Latte is able to identify what are the global shortcuts used for each activation entry and also to not show at all any badge for activation entries that are disabled from the user BUG: 397128
This commit is contained in:
parent
1b47a3749e
commit
9a69323293
@ -28,14 +28,15 @@
|
|||||||
|
|
||||||
#include <QtDBus/QtDBus>
|
#include <QtDBus/QtDBus>
|
||||||
|
|
||||||
|
#include <KDirWatch>
|
||||||
#include <KActivities/Consumer>
|
#include <KActivities/Consumer>
|
||||||
|
|
||||||
|
#define GLOBALSHORTCUTSCONFIG "kglobalshortcutsrc"
|
||||||
|
#define KWINMETAFORWARDTOLATTESTRING "org.kde.lattedock,/Latte,org.kde.LatteDock,activateLauncherMenu"
|
||||||
|
#define KWINMETAFORWARDTOPLASMASTRING "org.kde.plasmashell,/PlasmaShell,org.kde.PlasmaShell,activateLauncherMenu"
|
||||||
|
|
||||||
namespace Latte {
|
namespace Latte {
|
||||||
|
|
||||||
const QString UniversalSettings::KWinMetaForwardToLatteString = "org.kde.lattedock,/Latte,org.kde.LatteDock,activateLauncherMenu";
|
|
||||||
const QString UniversalSettings::KWinMetaForwardToPlasmaString = "org.kde.plasmashell,/PlasmaShell,org.kde.PlasmaShell,activateLauncherMenu";
|
|
||||||
|
|
||||||
|
|
||||||
UniversalSettings::UniversalSettings(KSharedConfig::Ptr config, QObject *parent)
|
UniversalSettings::UniversalSettings(KSharedConfig::Ptr config, QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
m_config(config),
|
m_config(config),
|
||||||
@ -65,6 +66,74 @@ UniversalSettings::~UniversalSettings()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UniversalSettings::initGlobalShortcutsWatcher()
|
||||||
|
{
|
||||||
|
const QString globalShortcutsFilePath = QDir::homePath() + "/.config/" + GLOBALSHORTCUTSCONFIG;
|
||||||
|
m_shortcutsConfigPtr = KSharedConfig::openConfig(globalShortcutsFilePath);
|
||||||
|
|
||||||
|
KDirWatch::self()->addFile(globalShortcutsFilePath);
|
||||||
|
|
||||||
|
QObject::connect(KDirWatch::self(), &KDirWatch::dirty, this, &UniversalSettings::shortcutsFileChanged, Qt::QueuedConnection);
|
||||||
|
QObject::connect(KDirWatch::self(), &KDirWatch::created, this, &UniversalSettings::shortcutsFileChanged, Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UniversalSettings::shortcutsFileChanged(const QString &file)
|
||||||
|
{
|
||||||
|
if (!file.endsWith(GLOBALSHORTCUTSCONFIG)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shortcutsConfigPtr->reparseConfiguration();
|
||||||
|
parseGlobalShortcuts();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UniversalSettings::parseGlobalShortcuts()
|
||||||
|
{
|
||||||
|
KConfigGroup latteGroup = KConfigGroup(m_shortcutsConfigPtr, "lattedock");
|
||||||
|
|
||||||
|
//! make sure that latte dock records in global shortcuts where found correctly
|
||||||
|
bool recordsExist{true};
|
||||||
|
|
||||||
|
if (!latteGroup.exists()) {
|
||||||
|
recordsExist = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recordsExist) {
|
||||||
|
for (int i = 1; i <= 19; ++i) {
|
||||||
|
QString entry = "activate entry " + QString::number(i);
|
||||||
|
|
||||||
|
if (!latteGroup.hasKey(entry)) {
|
||||||
|
recordsExist = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recordsExist) {
|
||||||
|
m_badgesForActivate.clear();
|
||||||
|
|
||||||
|
for (int i = 1; i <= 19; ++i) {
|
||||||
|
QString entry = "activate entry " + QString::number(i);
|
||||||
|
QStringList records = latteGroup.readEntry(entry, QStringList());
|
||||||
|
|
||||||
|
QString badge;
|
||||||
|
|
||||||
|
if (records[0] != "none") {
|
||||||
|
QStringList modifiers = records[0].split("+");
|
||||||
|
|
||||||
|
if (modifiers.count() >= 1) {
|
||||||
|
badge = modifiers[modifiers.count() - 1].toLower();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_badgesForActivate << badge;
|
||||||
|
emit badgesForActivateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "badges updated to :: " << m_badgesForActivate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UniversalSettings::load()
|
void UniversalSettings::load()
|
||||||
{
|
{
|
||||||
//! check if user has set the autostart option
|
//! check if user has set the autostart option
|
||||||
@ -76,6 +145,10 @@ void UniversalSettings::load()
|
|||||||
|
|
||||||
//! load configuration
|
//! load configuration
|
||||||
loadConfig();
|
loadConfig();
|
||||||
|
|
||||||
|
//! load global shortcuts badges at startup
|
||||||
|
initGlobalShortcutsWatcher();
|
||||||
|
parseGlobalShortcuts();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UniversalSettings::showInfoWindow() const
|
bool UniversalSettings::showInfoWindow() const
|
||||||
@ -185,6 +258,11 @@ void UniversalSettings::setLayoutsWindowSize(QSize size)
|
|||||||
emit layoutsWindowSizeChanged();
|
emit layoutsWindowSizeChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList UniversalSettings::badgesForActivate() const
|
||||||
|
{
|
||||||
|
return m_badgesForActivate;
|
||||||
|
}
|
||||||
|
|
||||||
QStringList UniversalSettings::layoutsColumnWidths() const
|
QStringList UniversalSettings::layoutsColumnWidths() const
|
||||||
{
|
{
|
||||||
return m_layoutsColumnWidths;
|
return m_layoutsColumnWidths;
|
||||||
@ -288,7 +366,7 @@ bool UniversalSettings::kwin_metaForwardedToLatte() const
|
|||||||
|
|
||||||
output = output.remove("\n");
|
output = output.remove("\n");
|
||||||
|
|
||||||
return (output == UniversalSettings::KWinMetaForwardToLatteString);
|
return (output == KWINMETAFORWARDTOLATTESTRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UniversalSettings::kwin_forwardMetaToLatte(bool forward)
|
void UniversalSettings::kwin_forwardMetaToLatte(bool forward)
|
||||||
@ -302,9 +380,9 @@ void UniversalSettings::kwin_forwardMetaToLatte(bool forward)
|
|||||||
parameters << "--file" << "kwinrc" << "--group" << "ModifierOnlyShortcuts" << "--key" << "Meta";
|
parameters << "--file" << "kwinrc" << "--group" << "ModifierOnlyShortcuts" << "--key" << "Meta";
|
||||||
|
|
||||||
if (forward) {
|
if (forward) {
|
||||||
parameters << UniversalSettings::KWinMetaForwardToLatteString;
|
parameters << KWINMETAFORWARDTOLATTESTRING;
|
||||||
} else {
|
} else {
|
||||||
parameters << UniversalSettings::KWinMetaForwardToPlasmaString;;
|
parameters << KWINMETAFORWARDTOPLASMASTRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
process.start("kwriteconfig5", parameters);
|
process.start("kwriteconfig5", parameters);
|
||||||
|
@ -44,6 +44,7 @@ class UniversalSettings : public QObject
|
|||||||
Q_PROPERTY(bool showInfoWindow READ showInfoWindow WRITE setShowInfoWindow NOTIFY showInfoWindowChanged)
|
Q_PROPERTY(bool showInfoWindow READ showInfoWindow WRITE setShowInfoWindow NOTIFY showInfoWindowChanged)
|
||||||
Q_PROPERTY(QString currentLayoutName READ currentLayoutName WRITE setCurrentLayoutName NOTIFY currentLayoutNameChanged)
|
Q_PROPERTY(QString currentLayoutName READ currentLayoutName WRITE setCurrentLayoutName NOTIFY currentLayoutNameChanged)
|
||||||
|
|
||||||
|
Q_PROPERTY(QStringList badgesForActivate READ badgesForActivate NOTIFY badgesForActivateChanged)
|
||||||
Q_PROPERTY(QStringList launchers READ launchers WRITE setLaunchers NOTIFY launchersChanged)
|
Q_PROPERTY(QStringList launchers READ launchers WRITE setLaunchers NOTIFY launchersChanged)
|
||||||
|
|
||||||
Q_PROPERTY(Latte::Dock::MouseSensitivity mouseSensitivity READ mouseSensitivity WRITE setMouseSensitivity NOTIFY mouseSensitivityChanged)
|
Q_PROPERTY(Latte::Dock::MouseSensitivity mouseSensitivity READ mouseSensitivity WRITE setMouseSensitivity NOTIFY mouseSensitivityChanged)
|
||||||
@ -85,6 +86,8 @@ public:
|
|||||||
QSize layoutsWindowSize() const;
|
QSize layoutsWindowSize() const;
|
||||||
void setLayoutsWindowSize(QSize size);
|
void setLayoutsWindowSize(QSize size);
|
||||||
|
|
||||||
|
QStringList badgesForActivate() const;
|
||||||
|
|
||||||
QStringList layoutsColumnWidths() const;
|
QStringList layoutsColumnWidths() const;
|
||||||
void setLayoutsColumnWidths(QStringList widths);
|
void setLayoutsColumnWidths(QStringList widths);
|
||||||
|
|
||||||
@ -107,6 +110,7 @@ public slots:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void autostartChanged();
|
void autostartChanged();
|
||||||
|
void badgesForActivateChanged();
|
||||||
void canDisableBordersChanged();
|
void canDisableBordersChanged();
|
||||||
void currentLayoutNameChanged();
|
void currentLayoutNameChanged();
|
||||||
void downloadWindowSizeChanged();
|
void downloadWindowSizeChanged();
|
||||||
@ -125,12 +129,15 @@ private slots:
|
|||||||
void loadConfig();
|
void loadConfig();
|
||||||
void saveConfig();
|
void saveConfig();
|
||||||
|
|
||||||
private:
|
void shortcutsFileChanged(const QString &file);
|
||||||
static const QString KWinMetaForwardToLatteString;
|
|
||||||
static const QString KWinMetaForwardToPlasmaString;
|
|
||||||
|
|
||||||
|
private:
|
||||||
void cleanupSettings();
|
void cleanupSettings();
|
||||||
|
|
||||||
|
void initGlobalShortcutsWatcher();
|
||||||
|
//! access user set global shortcuts for activate entries
|
||||||
|
void parseGlobalShortcuts();
|
||||||
|
|
||||||
bool kwin_metaForwardedToLatte() const;
|
bool kwin_metaForwardedToLatte() const;
|
||||||
void kwin_forwardMetaToLatte(bool forward);
|
void kwin_forwardMetaToLatte(bool forward);
|
||||||
|
|
||||||
@ -151,6 +158,7 @@ private:
|
|||||||
QSize m_downloadWindowSize{800, 550};
|
QSize m_downloadWindowSize{800, 550};
|
||||||
QSize m_layoutsWindowSize{700, 450};
|
QSize m_layoutsWindowSize{700, 450};
|
||||||
|
|
||||||
|
QStringList m_badgesForActivate{"1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "z", "x", "c", "v", "b", "n", "m", ",", "."};
|
||||||
QStringList m_layoutsColumnWidths;
|
QStringList m_layoutsColumnWidths;
|
||||||
QStringList m_launchers;
|
QStringList m_launchers;
|
||||||
|
|
||||||
@ -159,6 +167,7 @@ private:
|
|||||||
|
|
||||||
KConfigGroup m_universalGroup;
|
KConfigGroup m_universalGroup;
|
||||||
KSharedConfig::Ptr m_config;
|
KSharedConfig::Ptr m_config;
|
||||||
|
KSharedConfig::Ptr m_shortcutsConfigPtr;
|
||||||
|
|
||||||
SortedActivitiesModel *m_runningActivitiesModel{nullptr};
|
SortedActivitiesModel *m_runningActivitiesModel{nullptr};
|
||||||
|
|
||||||
|
@ -617,10 +617,12 @@ Item{
|
|||||||
Loader{
|
Loader{
|
||||||
id: appletNumberLoader
|
id: appletNumberLoader
|
||||||
anchors.fill: container.appletWrapper
|
anchors.fill: container.appletWrapper
|
||||||
active: opacityN>0
|
active: isValidDelayer > 0
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
|
visible: badgeString!==""
|
||||||
|
|
||||||
property int fixedIndex: -1
|
property int fixedIndex: -1
|
||||||
|
property string badgeString: ""
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active) {
|
if (active) {
|
||||||
@ -630,12 +632,31 @@ Item{
|
|||||||
|
|
||||||
Component.onCompleted: fixedIndex = parabolicManager.pseudoAppletIndex(index);
|
Component.onCompleted: fixedIndex = parabolicManager.pseudoAppletIndex(index);
|
||||||
|
|
||||||
property real opacityN: container.canShowAppletNumberBadge &&
|
property real isValidDelayer: container.canShowAppletNumberBadge &&
|
||||||
((root.unifiedGlobalShortcuts && root.showAppletsNumbers && fixedIndex<20)
|
((root.showAppletsNumbers && root.unifiedGlobalShortcuts)
|
||||||
|| (root.showMetaBadge && applet.id===applicationLauncherId)) ? 1 : 0
|
|| (root.showMetaBadge && applet.id===applicationLauncherId)) ? 1 : 0
|
||||||
|
|
||||||
Behavior on opacityN {
|
Behavior on isValidDelayer {
|
||||||
NumberAnimation { duration: root.durationTime*2*units.longDuration }
|
NumberAnimation { duration: root.durationTime*units.longDuration }
|
||||||
|
}
|
||||||
|
|
||||||
|
Binding{
|
||||||
|
target: appletNumberLoader
|
||||||
|
property:"badgeString"
|
||||||
|
value: {
|
||||||
|
//! dont change value on hiding/releasing
|
||||||
|
if (!root.showMetaBadge && !root.showAppletsNumbers) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root.showMetaBadge && applet && applet.id === applicationLauncherId) {
|
||||||
|
return '\u2318';
|
||||||
|
} else if (appletNumberLoader.fixedIndex>=1 && appletNumberLoader.fixedIndex<20) {
|
||||||
|
return root.badgesForActivate[appletNumberLoader.fixedIndex-1];
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceComponent: Item{
|
sourceComponent: Item{
|
||||||
@ -660,67 +681,11 @@ Item{
|
|||||||
minimumWidth: 0.4 * root.iconSize
|
minimumWidth: 0.4 * root.iconSize
|
||||||
height: width
|
height: width
|
||||||
border.color: root.minimizedDotColor
|
border.color: root.minimizedDotColor
|
||||||
numberValue: appletNumberLoader.fixedIndex < 10 ? appletNumberLoader.fixedIndex : 0
|
|
||||||
|
|
||||||
Binding{
|
|
||||||
target: appletNumber
|
|
||||||
property:"textValue"
|
|
||||||
value: {
|
|
||||||
//! dont change value on hiding/releasing
|
|
||||||
if (!root.showMetaBadge && !root.showAppletsNumbers) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (root.showMetaBadge && applet.id === applicationLauncherId) {
|
|
||||||
return '\u2318';
|
|
||||||
} else if (appletNumber.keysArrayIndex>=0 && appletNumber.keysArrayIndex<10) {
|
|
||||||
return appletNumber.keysAboveTen[appletNumber.keysArrayIndex];
|
|
||||||
} else {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Binding{
|
|
||||||
target: appletNumber
|
|
||||||
property:"showNumber"
|
|
||||||
value: {
|
|
||||||
//! dont change value on hiding/releasing
|
|
||||||
if (!root.showMetaBadge && !root.showAppletsNumbers) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (appletNumberLoader.fixedIndex < 10 && !(root.showMetaBadge && applet.id === applicationLauncherId)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Binding{
|
|
||||||
target: appletNumber
|
|
||||||
property:"showText"
|
|
||||||
value: {
|
|
||||||
//! dont change value on hiding/releasing
|
|
||||||
if (!root.showMetaBadge && !root.showAppletsNumbers) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((appletNumberLoader.fixedIndex>=10 && appletNumberLoader.fixedIndex<20) ||
|
|
||||||
(root.showMetaBadge && applet.id === applicationLauncherId)) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proportion: 0
|
proportion: 0
|
||||||
radiusPerCentage: 50
|
radiusPerCentage: 50
|
||||||
|
showNumber: false
|
||||||
property int keysArrayIndex: appletNumberLoader.fixedIndex-10;
|
showText: true
|
||||||
property var keysAboveTen: ['0', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.']
|
textValue: appletNumberLoader.badgeString
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -300,6 +300,14 @@ DragDrop.DropArea {
|
|||||||
|
|
||||||
readonly property string plasmoidName: "org.kde.latte.plasmoid"
|
readonly property string plasmoidName: "org.kde.latte.plasmoid"
|
||||||
|
|
||||||
|
property var badgesForActivate: {
|
||||||
|
if (!universalSettings) {
|
||||||
|
return ['1','2','3','4','5','6','7','8','9','0', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return universalSettings.badgesForActivate;
|
||||||
|
}
|
||||||
|
|
||||||
property var iconsArray: [16, 22, 32, 48, 64, 96, 128, 256]
|
property var iconsArray: [16, 22, 32, 48, 64, 96, 128, 256]
|
||||||
property var layoutManager: LayoutManager
|
property var layoutManager: LayoutManager
|
||||||
|
|
||||||
|
@ -244,6 +244,8 @@ Item {
|
|||||||
property alias hoveredIndex: icList.hoveredIndex
|
property alias hoveredIndex: icList.hoveredIndex
|
||||||
|
|
||||||
property QtObject currentLayout : latteDock && latteDock.dockManagedLayout ? latteDock.dockManagedLayout : null
|
property QtObject currentLayout : latteDock && latteDock.dockManagedLayout ? latteDock.dockManagedLayout : null
|
||||||
|
|
||||||
|
property var badgesForActivate: latteDock ? latteDock.badgesForActivate : []
|
||||||
property var managedLayoutName: currentLayout ? currentLayout.name : ""
|
property var managedLayoutName: currentLayout ? currentLayout.name : ""
|
||||||
|
|
||||||
property Item latteDock: null
|
property Item latteDock: null
|
||||||
|
@ -458,10 +458,13 @@ Item{
|
|||||||
Loader{
|
Loader{
|
||||||
id: taskNumberLoader
|
id: taskNumberLoader
|
||||||
anchors.fill: iconImageBuffer
|
anchors.fill: iconImageBuffer
|
||||||
active: opacityN>0 && !launcherAnimation.running
|
active: isValidDelayer>0 && !launcherAnimation.running
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
|
visible: badgeString !== ""
|
||||||
|
|
||||||
property int fixedIndex:-1
|
property int fixedIndex:-1
|
||||||
|
property string badgeString: (taskNumberLoader.fixedIndex>=1 && taskNumberLoader.fixedIndex<20 && root.badgesForActivate.length===19) ?
|
||||||
|
root.badgesForActivate[taskNumberLoader.fixedIndex-1] : ""
|
||||||
|
|
||||||
onActiveChanged: {
|
onActiveChanged: {
|
||||||
if (active) {
|
if (active) {
|
||||||
@ -471,10 +474,10 @@ Item{
|
|||||||
|
|
||||||
Component.onCompleted: fixedIndex = parabolicManager.pseudoTaskIndex(index+1);
|
Component.onCompleted: fixedIndex = parabolicManager.pseudoTaskIndex(index+1);
|
||||||
|
|
||||||
property real opacityN: root.showTasksNumbers && !mainItemContainer.isSeparator && fixedIndex<20 ? 1 : 0
|
property real isValidDelayer: root.showTasksNumbers && !mainItemContainer.isSeparator && fixedIndex<20 ? 1 : 0
|
||||||
|
|
||||||
Behavior on opacityN {
|
Behavior on isValidDelayer {
|
||||||
NumberAnimation { duration: root.durationTime*2*units.longDuration }
|
NumberAnimation { duration: root.durationTime*units.longDuration }
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceComponent: Item{
|
sourceComponent: Item{
|
||||||
@ -496,21 +499,16 @@ Item{
|
|||||||
id: taskNumber
|
id: taskNumber
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
border.color: root.minimizedDotColor
|
border.color: root.minimizedDotColor
|
||||||
//opacity: taskNumberLoader.opacityN && !root.enableShadows ? 1 : 0
|
|
||||||
|
|
||||||
minimumWidth: 0.4 * root.iconSize
|
minimumWidth: 0.4 * root.iconSize
|
||||||
height: width
|
height: width
|
||||||
numberValue: taskNumberLoader.fixedIndex < 10 ? taskNumberLoader.fixedIndex : 0
|
textValue: taskNumberLoader.badgeString
|
||||||
textValue: (keysArrayIndex>=0 && keysArrayIndex<10) ? keysAboveTen[keysArrayIndex] : ''
|
|
||||||
|
|
||||||
showNumber: taskNumberLoader.fixedIndex < 10
|
showNumber: false
|
||||||
showText: taskNumberLoader.fixedIndex>=10 && taskNumberLoader.fixedIndex<20
|
showText: true
|
||||||
|
|
||||||
proportion: 0
|
proportion: 0
|
||||||
radiusPerCentage: 50
|
radiusPerCentage: 50
|
||||||
|
|
||||||
property int keysArrayIndex: taskNumberLoader.fixedIndex-10;
|
|
||||||
property var keysAboveTen: ['0', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.']
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user