Disable automatic conversions from 8-bit strings
This commit is contained in:
@@ -43,18 +43,18 @@ QByteArray CoverUtils::Sha1CoverHash(const QString &artist, const QString &album
|
||||
|
||||
QString CoverUtils::AlbumCoverFilename(QString artist, QString album, const QString &extension) {
|
||||
|
||||
artist.remove('/').remove('\\');
|
||||
album.remove('/').remove('\\');
|
||||
artist.remove(QLatin1Char('/')).remove(QLatin1Char('\\'));
|
||||
album.remove(QLatin1Char('/')).remove(QLatin1Char('\\'));
|
||||
|
||||
QString filename = artist + "-" + album;
|
||||
QString filename = artist + QStringLiteral("-") + album;
|
||||
filename = Utilities::Transliterate(filename.toLower());
|
||||
filename = filename.replace(' ', '-')
|
||||
filename = filename.replace(QLatin1Char(' '), QLatin1Char('-'))
|
||||
.replace(QLatin1String("--"), QLatin1String("-"))
|
||||
.remove(QRegularExpression(QString(kInvalidFatCharactersRegex), QRegularExpression::CaseInsensitiveOption))
|
||||
.remove(QRegularExpression(QLatin1String(kInvalidFatCharactersRegex), QRegularExpression::CaseInsensitiveOption))
|
||||
.simplified();
|
||||
|
||||
if (!extension.isEmpty()) {
|
||||
filename.append('.');
|
||||
filename.append(QLatin1Char('.'));
|
||||
filename.append(extension);
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ QString CoverUtils::CoverFilePath(const CoverOptions &options, const Song::Sourc
|
||||
path = Song::ImageCacheDir(source);
|
||||
}
|
||||
|
||||
if (path.right(1) == QDir::separator() || path.right(1) == "/") {
|
||||
if (path.right(1) == QDir::separator() || path.right(1) == QLatin1String("/")) {
|
||||
path.chop(1);
|
||||
}
|
||||
|
||||
@@ -92,11 +92,11 @@ QString CoverUtils::CoverFilePath(const CoverOptions &options, const Song::Sourc
|
||||
options.cover_filename == CoverOptions::CoverFilename::Pattern &&
|
||||
!options.cover_pattern.isEmpty()) {
|
||||
filename = CoverFilenameFromVariable(options, artist, album);
|
||||
filename.remove(QRegularExpression(QString(kInvalidFatCharactersRegex), QRegularExpression::CaseInsensitiveOption)).remove('/').remove('\\');
|
||||
filename.remove(QRegularExpression(QLatin1String(kInvalidFatCharactersRegex), QRegularExpression::CaseInsensitiveOption)).remove(QLatin1Char('/')).remove(QLatin1Char('\\'));
|
||||
if (options.cover_lowercase) filename = filename.toLower();
|
||||
if (options.cover_replace_spaces) filename.replace(QRegularExpression(QStringLiteral("\\s")), QStringLiteral("-"));
|
||||
if (!extension.isEmpty()) {
|
||||
filename.append('.');
|
||||
filename.append(QLatin1Char('.'));
|
||||
filename.append(extension);
|
||||
}
|
||||
}
|
||||
@@ -105,7 +105,7 @@ QString CoverUtils::CoverFilePath(const CoverOptions &options, const Song::Sourc
|
||||
filename = CoverFilenameFromSource(source, cover_url, artist, album, album_id, extension);
|
||||
}
|
||||
|
||||
QString filepath(path + "/" + filename);
|
||||
QString filepath(path + QStringLiteral("/") + filename);
|
||||
|
||||
return filepath;
|
||||
|
||||
@@ -118,7 +118,7 @@ QString CoverUtils::CoverFilenameFromSource(const Song::Source source, const QUr
|
||||
switch (source) {
|
||||
case Song::Source::Tidal:
|
||||
if (!album_id.isEmpty()) {
|
||||
filename = album_id + "-" + cover_url.fileName();
|
||||
filename = album_id + QStringLiteral("-") + cover_url.fileName();
|
||||
break;
|
||||
}
|
||||
[[fallthrough]];
|
||||
@@ -137,12 +137,12 @@ QString CoverUtils::CoverFilenameFromSource(const Song::Source source, const QUr
|
||||
case Song::Source::SomaFM:
|
||||
case Song::Source::RadioParadise:
|
||||
case Song::Source::Unknown:
|
||||
filename = Sha1CoverHash(artist, album).toHex();
|
||||
filename = QString::fromLatin1(Sha1CoverHash(artist, album).toHex());
|
||||
break;
|
||||
}
|
||||
|
||||
if (!extension.isEmpty()) {
|
||||
filename.append('.');
|
||||
filename.append(QLatin1Char('.'));
|
||||
filename.append(extension);
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ QString CoverUtils::CoverFilenameFromVariable(const CoverOptions &options, const
|
||||
filename.replace(QLatin1String("%artist"), artist);
|
||||
filename.replace(QLatin1String("%album"), album);
|
||||
if (!extension.isEmpty()) {
|
||||
filename.append('.');
|
||||
filename.append(QLatin1Char('.'));
|
||||
filename.append(extension);
|
||||
}
|
||||
return filename;
|
||||
|
||||
@@ -36,7 +36,7 @@ QString GetEnv(const QString &key) {
|
||||
void SetEnv(const char *key, const QString &value) {
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
_putenv(QString("%1=%2").arg(key, value).toLocal8Bit().constData());
|
||||
_putenv(QStringLiteral("%1=%2").arg(QLatin1String(key), value).toLocal8Bit().constData());
|
||||
#else
|
||||
setenv(key, value.toLocal8Bit().constData(), 1);
|
||||
#endif
|
||||
@@ -52,19 +52,19 @@ QString DesktopEnvironment() {
|
||||
if (!qEnvironmentVariableIsEmpty("GNOME_DESKTOP_SESSION_ID")) return QStringLiteral("Gnome");
|
||||
|
||||
QString session = GetEnv(QStringLiteral("DESKTOP_SESSION"));
|
||||
qint64 slash = session.lastIndexOf('/');
|
||||
qint64 slash = session.lastIndexOf(QLatin1Char('/'));
|
||||
if (slash != -1) {
|
||||
QSettings desktop_file(QStringLiteral("%1.desktop").arg(session), QSettings::IniFormat);
|
||||
desktop_file.beginGroup("Desktop Entry");
|
||||
QString name = desktop_file.value("DesktopNames").toString();
|
||||
desktop_file.beginGroup(QStringLiteral("Desktop Entry"));
|
||||
QString name = desktop_file.value(QStringLiteral("DesktopNames")).toString();
|
||||
desktop_file.endGroup();
|
||||
if (!name.isEmpty()) return name;
|
||||
session = session.mid(slash + 1);
|
||||
}
|
||||
|
||||
if (session == "kde") return QStringLiteral("KDE");
|
||||
else if (session == "gnome") return QStringLiteral("Gnome");
|
||||
else if (session == "xfce") return QStringLiteral("XFCE");
|
||||
if (session == QStringLiteral("kde")) return QStringLiteral("KDE");
|
||||
else if (session == QStringLiteral("gnome")) return QStringLiteral("Gnome");
|
||||
else if (session == QStringLiteral("xfce")) return QStringLiteral("XFCE");
|
||||
|
||||
return QStringLiteral("Unknown");
|
||||
|
||||
|
||||
@@ -46,11 +46,11 @@ void OpenInFileManager(const QString &path, const QUrl &url) {
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
proc.startCommand(QStringLiteral("xdg-mime query default inode/directory"));
|
||||
#else
|
||||
proc.start("xdg-mime", QStringList() << "query" << "default" << "inode/directory");
|
||||
proc.start(QStringLiteral("xdg-mime"), QStringList() << QStringLiteral("query") << QStringLiteral("default") << QStringLiteral("inode/directory"));
|
||||
#endif
|
||||
proc.waitForFinished();
|
||||
QString desktop_file = proc.readLine().simplified();
|
||||
QString xdg_data_dirs = QString(qgetenv("XDG_DATA_DIRS"));
|
||||
QString desktop_file = QString::fromUtf8(proc.readLine()).simplified();
|
||||
QString xdg_data_dirs = QString::fromUtf8(qgetenv("XDG_DATA_DIRS"));
|
||||
if (xdg_data_dirs.isEmpty()) {
|
||||
xdg_data_dirs = QStringLiteral("/usr/local/share/:/usr/share/");
|
||||
}
|
||||
@@ -62,15 +62,15 @@ void OpenInFileManager(const QString &path, const QUrl &url) {
|
||||
QString desktop_file_path = QStringLiteral("%1/applications/%2").arg(data_dir, desktop_file);
|
||||
if (!QFile::exists(desktop_file_path)) continue;
|
||||
QSettings setting(desktop_file_path, QSettings::IniFormat);
|
||||
setting.beginGroup("Desktop Entry");
|
||||
if (setting.contains("Exec")) {
|
||||
QString cmd = setting.value("Exec").toString();
|
||||
setting.beginGroup(QStringLiteral("Desktop Entry"));
|
||||
if (setting.contains(QStringLiteral("Exec"))) {
|
||||
QString cmd = setting.value(QStringLiteral("Exec")).toString();
|
||||
if (cmd.isEmpty()) break;
|
||||
cmd = cmd.remove(QRegularExpression(QStringLiteral("[%][a-zA-Z]*( |$)"), QRegularExpression::CaseInsensitiveOption));
|
||||
# if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
command_params = cmd.split(' ', Qt::SkipEmptyParts);
|
||||
command_params = cmd.split(QLatin1Char(' '), Qt::SkipEmptyParts);
|
||||
# else
|
||||
command_params = cmd.split(' ', QString::SkipEmptyParts);
|
||||
command_params = cmd.split(QLatin1Char(' '), QString::SkipEmptyParts);
|
||||
# endif
|
||||
command = command_params.first();
|
||||
command_params.removeFirst();
|
||||
@@ -83,7 +83,7 @@ void OpenInFileManager(const QString &path, const QUrl &url) {
|
||||
command = command.split(QStringLiteral("/")).last();
|
||||
}
|
||||
|
||||
if (command.isEmpty() || command == "exo-open") {
|
||||
if (command.isEmpty() || command == QStringLiteral("exo-open")) {
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
||||
}
|
||||
else if (command.startsWith(QLatin1String("nautilus"))) {
|
||||
@@ -108,14 +108,14 @@ void OpenInFileManager(const QString &path, const QUrl &url) {
|
||||
#ifdef Q_OS_MACOS
|
||||
// Better than openUrl(dirname(path)) - also highlights file at path
|
||||
void RevealFileInFinder(const QString &path) {
|
||||
QProcess::execute("/usr/bin/open", QStringList() << "-R" << path);
|
||||
QProcess::execute(QStringLiteral("/usr/bin/open"), QStringList() << QStringLiteral("-R") << path);
|
||||
}
|
||||
#endif // Q_OS_MACOS
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
void ShowFileInExplorer(const QString &path);
|
||||
void ShowFileInExplorer(const QString &path) {
|
||||
QProcess::execute("explorer.exe", QStringList() << "/select," << QDir::toNativeSeparators(path));
|
||||
QProcess::execute(QStringLiteral("explorer.exe"), QStringList() << QStringLiteral("/select,") << QDir::toNativeSeparators(path));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -86,21 +86,21 @@ bool Copy(QIODevice *source, QIODevice *destination) {
|
||||
bool CopyRecursive(const QString &source, const QString &destination) {
|
||||
|
||||
// Make the destination directory
|
||||
QString dir_name = source.section('/', -1, -1);
|
||||
QString dest_path = destination + "/" + dir_name;
|
||||
QString dir_name = source.section(QLatin1Char('/'), -1, -1);
|
||||
QString dest_path = destination + QLatin1Char('/') + dir_name;
|
||||
QDir().mkpath(dest_path);
|
||||
|
||||
QDir dir(source);
|
||||
for (const QString &child : dir.entryList(QDir::NoDotAndDotDot | QDir::Dirs)) {
|
||||
if (!CopyRecursive(source + "/" + child, dest_path)) {
|
||||
qLog(Warning) << "Failed to copy dir" << source + "/" + child << "to" << dest_path;
|
||||
if (!CopyRecursive(source + QLatin1Char('/') + child, dest_path)) {
|
||||
qLog(Warning) << "Failed to copy dir" << source + QLatin1Char('/') + child << "to" << dest_path;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const QString &child : dir.entryList(QDir::NoDotAndDotDot | QDir::Files)) {
|
||||
if (!QFile::copy(source + "/" + child, dest_path + "/" + child)) {
|
||||
qLog(Warning) << "Failed to copy file" << source + "/" + child << "to" << dest_path;
|
||||
if (!QFile::copy(source + QLatin1Char('/') + child, dest_path + QLatin1Char('/') + child)) {
|
||||
qLog(Warning) << "Failed to copy file" << source + QLatin1Char('/') + child << "to" << dest_path;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -112,13 +112,13 @@ bool RemoveRecursive(const QString &path) {
|
||||
|
||||
QDir dir(path);
|
||||
for (const QString &child : dir.entryList(QDir::NoDotAndDotDot | QDir::Dirs | QDir::Hidden)) {
|
||||
if (!RemoveRecursive(path + "/" + child)) {
|
||||
if (!RemoveRecursive(path + QLatin1Char('/') + child)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (const QString &child : dir.entryList(QDir::NoDotAndDotDot | QDir::Files | QDir::Hidden)) {
|
||||
if (!QFile::remove(path + "/" + child)) {
|
||||
if (!QFile::remove(path + QLatin1Char('/') + child)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ QStringList ImageUtils::SupportedImageMimeTypes() {
|
||||
|
||||
if (kSupportedImageMimeTypes.isEmpty()) {
|
||||
for (const QByteArray &mimetype : QImageReader::supportedMimeTypes()) {
|
||||
kSupportedImageMimeTypes << mimetype;
|
||||
kSupportedImageMimeTypes << QString::fromUtf8(mimetype);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ QStringList ImageUtils::SupportedImageFormats() {
|
||||
|
||||
if (kSupportedImageFormats.isEmpty()) {
|
||||
for (const QByteArray &filetype : QImageReader::supportedImageFormats()) {
|
||||
kSupportedImageFormats << filetype;
|
||||
kSupportedImageFormats << QString::fromUtf8(filetype);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ QByteArray ImageUtils::FileToJpegData(const QString &filename) {
|
||||
if (filename.isEmpty()) return QByteArray();
|
||||
|
||||
QByteArray image_data = Utilities::ReadDataFromFile(filename);
|
||||
if (Utilities::MimeTypeFromData(image_data) == "image/jpeg") return image_data;
|
||||
if (Utilities::MimeTypeFromData(image_data) == QStringLiteral("image/jpeg")) return image_data;
|
||||
else {
|
||||
QImage image;
|
||||
if (image.loadFromData(image_data)) {
|
||||
|
||||
@@ -31,7 +31,7 @@ QString MacAddress() {
|
||||
|
||||
for (QNetworkInterface &netif : QNetworkInterface::allInterfaces()) {
|
||||
if (
|
||||
(netif.hardwareAddress() == "00:00:00:00:00:00") ||
|
||||
(netif.hardwareAddress() == QStringLiteral("00:00:00:00:00:00")) ||
|
||||
(netif.flags() & QNetworkInterface::IsLoopBack) ||
|
||||
!(netif.flags() & QNetworkInterface::IsUp) ||
|
||||
!(netif.flags() & QNetworkInterface::IsRunning)
|
||||
|
||||
@@ -49,7 +49,7 @@ int ParseSearchTime(const QString &time_str) {
|
||||
if (c.isDigit()) {
|
||||
accum = accum * 10 + c.digitValue();
|
||||
}
|
||||
else if (c == ':') {
|
||||
else if (c == QLatin1Char(':')) {
|
||||
seconds = seconds * 60 + accum;
|
||||
accum = 0;
|
||||
++colon_count;
|
||||
@@ -89,7 +89,7 @@ float ParseSearchRating(const QString &rating_str) {
|
||||
}
|
||||
|
||||
// check if the search is a float
|
||||
else if (rating_str.at(0) == 'f') {
|
||||
else if (rating_str.at(0) == QLatin1Char('f')) {
|
||||
QString rating_float = rating_str;
|
||||
rating_float = rating_float.remove(0, 1);
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ QString PrettySize(const quint64 bytes) {
|
||||
|
||||
if (bytes > 0) {
|
||||
if (bytes <= 1000) {
|
||||
ret = QString::number(bytes) + " bytes";
|
||||
ret = QString::number(bytes) + QStringLiteral(" bytes");
|
||||
}
|
||||
else if (bytes <= 1000 * 1000) {
|
||||
ret = QString::asprintf("%.1f KB", static_cast<float>(bytes) / 1000.0F);
|
||||
@@ -52,16 +52,16 @@ QString PrettySize(const quint64 bytes) {
|
||||
}
|
||||
|
||||
QString PrettySize(const QSize size) {
|
||||
return QString::number(size.width()) + "x" + QString::number(size.height());
|
||||
return QString::number(size.width()) + QLatin1Char('x') + QString::number(size.height());
|
||||
}
|
||||
|
||||
QString PathWithoutFilenameExtension(const QString &filename) {
|
||||
if (filename.section('/', -1, -1).contains('.')) return filename.section('.', 0, -2);
|
||||
if (filename.section(QLatin1Char('/'), -1, -1).contains(QLatin1Char('.'))) return filename.section(QLatin1Char('.'), 0, -2);
|
||||
return filename;
|
||||
}
|
||||
|
||||
QString FiddleFileExtension(const QString &filename, const QString &new_extension) {
|
||||
return PathWithoutFilenameExtension(filename) + "." + new_extension;
|
||||
return PathWithoutFilenameExtension(filename) + QLatin1Char('.') + new_extension;
|
||||
}
|
||||
|
||||
const char *EnumToString(const QMetaObject &meta, const char *name, const int value) {
|
||||
@@ -86,7 +86,7 @@ QStringList Prepend(const QString &text, const QStringList &list) {
|
||||
QStringList Updateify(const QStringList &list) {
|
||||
|
||||
QStringList ret(list);
|
||||
for (int i = 0; i < ret.count(); ++i) ret[i].prepend(ret[i] + " = :");
|
||||
for (int i = 0; i < ret.count(); ++i) ret[i].prepend(ret[i] + QStringLiteral(" = :"));
|
||||
return ret;
|
||||
|
||||
}
|
||||
@@ -136,61 +136,61 @@ QString ReplaceVariable(const QString &variable, const Song &song, const QString
|
||||
|
||||
QString value = variable;
|
||||
|
||||
if (variable == "%title%") {
|
||||
if (variable == QStringLiteral("%title%")) {
|
||||
value = song.PrettyTitle();
|
||||
}
|
||||
else if (variable == "%album%") {
|
||||
else if (variable == QStringLiteral("%album%")) {
|
||||
value = song.album();
|
||||
}
|
||||
else if (variable == "%artist%") {
|
||||
else if (variable == QStringLiteral("%artist%")) {
|
||||
value = song.artist();
|
||||
}
|
||||
else if (variable == "%albumartist%") {
|
||||
else if (variable == QStringLiteral("%albumartist%")) {
|
||||
value = song.effective_albumartist();
|
||||
}
|
||||
else if (variable == "%track%") {
|
||||
else if (variable == QStringLiteral("%track%")) {
|
||||
value.setNum(song.track());
|
||||
}
|
||||
else if (variable == "%disc%") {
|
||||
else if (variable == QStringLiteral("%disc%")) {
|
||||
value.setNum(song.disc());
|
||||
}
|
||||
else if (variable == "%year%") {
|
||||
else if (variable == QStringLiteral("%year%")) {
|
||||
value = song.PrettyYear();
|
||||
}
|
||||
else if (variable == "%originalyear%") {
|
||||
else if (variable == QStringLiteral("%originalyear%")) {
|
||||
value = song.PrettyOriginalYear();
|
||||
}
|
||||
else if (variable == "%genre%") {
|
||||
else if (variable == QStringLiteral("%genre%")) {
|
||||
value = song.genre();
|
||||
}
|
||||
else if (variable == "%composer%") {
|
||||
else if (variable == QStringLiteral("%composer%")) {
|
||||
value = song.composer();
|
||||
}
|
||||
else if (variable == "%performer%") {
|
||||
else if (variable == QStringLiteral("%performer%")) {
|
||||
value = song.performer();
|
||||
}
|
||||
else if (variable == "%grouping%") {
|
||||
else if (variable == QStringLiteral("%grouping%")) {
|
||||
value = song.grouping();
|
||||
}
|
||||
else if (variable == "%length%") {
|
||||
else if (variable == QStringLiteral("%length%")) {
|
||||
value = song.PrettyLength();
|
||||
}
|
||||
else if (variable == "%filename%") {
|
||||
else if (variable == QStringLiteral("%filename%")) {
|
||||
value = song.basefilename();
|
||||
}
|
||||
else if (variable == "%url%") {
|
||||
else if (variable == QStringLiteral("%url%")) {
|
||||
value = song.url().toString();
|
||||
}
|
||||
else if (variable == "%playcount%") {
|
||||
else if (variable == QStringLiteral("%playcount%")) {
|
||||
value.setNum(song.playcount());
|
||||
}
|
||||
else if (variable == "%skipcount%") {
|
||||
else if (variable == QStringLiteral("%skipcount%")) {
|
||||
value.setNum(song.skipcount());
|
||||
}
|
||||
else if (variable == "%rating%") {
|
||||
else if (variable == QStringLiteral("%rating%")) {
|
||||
value = song.PrettyRating();
|
||||
}
|
||||
else if (variable == "%newline%") {
|
||||
else if (variable == QStringLiteral("%newline%")) {
|
||||
return QString(newline); // No HTML escaping, return immediately.
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ QString PrettyTime(int seconds) {
|
||||
}
|
||||
|
||||
QString PrettyTimeDelta(const int seconds) {
|
||||
return (seconds >= 0 ? "+" : "-") + PrettyTime(seconds);
|
||||
return (seconds >= 0 ? QStringLiteral("+") : QStringLiteral("-")) + PrettyTime(seconds);
|
||||
}
|
||||
|
||||
QString PrettyTimeNanosec(const qint64 nanoseconds) {
|
||||
@@ -67,7 +67,7 @@ QString WordyTime(const quint64 seconds) {
|
||||
if (days > 0) parts << (days == 1 ? QObject::tr("1 day") : QObject::tr("%1 days").arg(days));
|
||||
parts << PrettyTime(static_cast<int>(seconds - days * 60 * 60 * 24));
|
||||
|
||||
return parts.join(QStringLiteral(" "));
|
||||
return parts.join(QLatin1Char(' '));
|
||||
|
||||
}
|
||||
|
||||
@@ -82,8 +82,8 @@ QString Ago(const qint64 seconds_since_epoch, const QLocale &locale) {
|
||||
const qint64 days_ago = then.date().daysTo(now.date());
|
||||
const QString time = then.time().toString(locale.timeFormat(QLocale::ShortFormat));
|
||||
|
||||
if (days_ago == 0) return QObject::tr("Today") + " " + time;
|
||||
if (days_ago == 1) return QObject::tr("Yesterday") + " " + time;
|
||||
if (days_ago == 0) return QObject::tr("Today") + QLatin1Char(' ') + time;
|
||||
if (days_ago == 1) return QObject::tr("Yesterday") + QLatin1Char(' ') + time;
|
||||
if (days_ago <= 7) return QObject::tr("%1 days ago").arg(days_ago);
|
||||
|
||||
return then.date().toString(locale.dateFormat(QLocale::ShortFormat));
|
||||
|
||||
Reference in New Issue
Block a user