diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp
index 2172c34c..a56aaa6d 100644
--- a/src/UserSettingsPage.cpp
+++ b/src/UserSettingsPage.cpp
@@ -133,6 +133,12 @@ UserSettings::load(std::optional<QString> profile)
presenceValue = 0;
presence_ = static_cast<Presence>(presenceValue);
+ auto tempShowImage = settings.value(prefix + "user/show_images", "").toString().toStdString();
+ auto showImageValue = QMetaEnum::fromType<ShowImage>().keyToValue(tempShowImage.c_str());
+ if (showImageValue < 0)
+ showImageValue = 0;
+ showImage_ = static_cast<ShowImage>(showImageValue);
+
collapsedSpaces_.clear();
auto tempSpaces = settings.value(prefix + "user/collapsed_spaces", QList<QVariant>{}).toList();
for (const auto &e : std::as_const(tempSpaces))
@@ -613,6 +619,16 @@ UserSettings::setPresence(Presence state)
}
void
+UserSettings::setShowImage(ShowImage state)
+{
+ if (state == showImage_)
+ return;
+ showImage_ = state;
+ emit showImageChanged(state);
+ save();
+}
+
+void
UserSettings::setTheme(QString theme)
{
if (theme == theme_)
@@ -955,6 +971,9 @@ UserSettings::save()
settings.setValue(
prefix + "user/presence",
QString::fromUtf8(QMetaEnum::fromType<Presence>().valueToKey(static_cast<int>(presence_))));
+ settings.setValue(
+ prefix + "user/show_images",
+ QString::fromUtf8(QMetaEnum::fromType<ShowImage>().valueToKey(static_cast<int>(showImage_))));
QVariantList v;
v.reserve(collapsedSpaces_.size());
@@ -1024,6 +1043,8 @@ UserSettingsModel::data(const QModelIndex &index, int role) const
return tr("Enable small Avatars");
case AnimateImagesOnHover:
return tr("Play animated images only on hover");
+ case ShowImage:
+ return tr("Show images automatically");
case TypingNotifications:
return tr("Typing notifications");
case SortByImportance:
@@ -1182,6 +1203,8 @@ UserSettingsModel::data(const QModelIndex &index, int role) const
return i->smallAvatars();
case AnimateImagesOnHover:
return i->animateImagesOnHover();
+ case ShowImage:
+ return static_cast<int>(i->showImage());
case TypingNotifications:
return i->typingNotifications();
case SortByImportance:
@@ -1349,6 +1372,10 @@ UserSettingsModel::data(const QModelIndex &index, int role) const
return tr("Avatars are resized to fit above the message.");
case AnimateImagesOnHover:
return tr("Plays media like GIFs or WEBPs only when explicitly hovering over them.");
+ case ShowImage:
+ return tr("If images should be automatically displayed. You can select between always "
+ "showing images by default, only show them by default in private rooms or "
+ "always require interaction to show images.");
case TypingNotifications:
return tr(
"Show who is typing in a room.\nThis will also enable or disable sending typing "
@@ -1504,6 +1531,7 @@ UserSettingsModel::data(const QModelIndex &index, int role) const
case CameraResolution:
case CameraFrameRate:
case Ringtone:
+ case ShowImage:
return Options;
case TimelineMaxWidth:
case PrivacyScreenTimeout:
@@ -1631,6 +1659,12 @@ UserSettingsModel::data(const QModelIndex &index, int role) const
QStringLiteral("Dark"),
QStringLiteral("System"),
};
+ case ShowImage:
+ return QStringList{
+ tr("Always"),
+ tr("Only in private rooms"),
+ tr("Never"),
+ };
case Microphone:
return vecToList(CallDevices::instance().names(false, i->microphone().toStdString()));
case Camera:
@@ -1710,6 +1744,16 @@ UserSettingsModel::setData(const QModelIndex &index, const QVariant &value, int
} else
return false;
}
+ case ShowImage: {
+ auto showImageValue = value.toInt();
+ if (showImageValue < 0 ||
+
+ QMetaEnum::fromType<UserSettings::ShowImage>().keyCount() <= showImageValue)
+ return false;
+
+ i->setShowImage(static_cast<UserSettings::ShowImage>(showImageValue));
+ return true;
+ }
case MessageHoverHighlight: {
if (value.userType() == QMetaType::Bool) {
i->setMessageHoverHighlight(value.toBool());
@@ -2241,6 +2285,9 @@ UserSettingsModel::UserSettingsModel(QObject *p)
connect(s.get(), &UserSettings::animateImagesOnHoverChanged, this, [this]() {
emit dataChanged(index(AnimateImagesOnHover), index(AnimateImagesOnHover), {Value});
});
+ connect(s.get(), &UserSettings::showImageChanged, this, [this]() {
+ emit dataChanged(index(ShowImage), index(ShowImage), {Value});
+ });
connect(s.get(), &UserSettings::typingNotificationsChanged, this, [this]() {
emit dataChanged(index(TypingNotifications), index(TypingNotifications), {Value});
});
diff --git a/src/UserSettingsPage.h b/src/UserSettingsPage.h
index 44cf7c84..63a4d616 100644
--- a/src/UserSettingsPage.h
+++ b/src/UserSettingsPage.h
@@ -75,6 +75,7 @@ class UserSettings final : public QObject
Q_PROPERTY(QString font READ font WRITE setFontFamily NOTIFY fontChanged)
Q_PROPERTY(QString emojiFont READ emojiFont WRITE setEmojiFontFamily NOTIFY emojiFontChanged)
Q_PROPERTY(Presence presence READ presence WRITE setPresence NOTIFY presenceChanged)
+ Q_PROPERTY(ShowImage showImage READ showImage WRITE setShowImage NOTIFY showImageChanged)
Q_PROPERTY(QString ringtone READ ringtone WRITE setRingtone NOTIFY ringtoneChanged)
Q_PROPERTY(QString microphone READ microphone WRITE setMicrophone NOTIFY microphoneChanged)
Q_PROPERTY(QString camera READ camera WRITE setCamera NOTIFY cameraChanged)
@@ -157,6 +158,14 @@ public:
};
Q_ENUM(Presence)
+ enum class ShowImage
+ {
+ Always,
+ OnlyPrivate,
+ Never,
+ };
+ Q_ENUM(ShowImage)
+
void save();
void load(std::optional<QString> profile);
void applyTheme();
@@ -196,6 +205,7 @@ public:
void setPrivacyScreen(bool state);
void setPrivacyScreenTimeout(int state);
void setPresence(Presence state);
+ void setShowImage(ShowImage state);
void setRingtone(QString ringtone);
void setMicrophone(QString microphone);
void setCamera(QString camera);
@@ -273,6 +283,7 @@ public:
return emojiFont_;
}
Presence presence() const { return presence_; }
+ ShowImage showImage() const { return showImage_; }
QString ringtone() const { return ringtone_; }
QString microphone() const { return microphone_; }
QString camera() const { return camera_; }
@@ -343,6 +354,7 @@ signals:
void fontChanged(QString state);
void emojiFontChanged(QString state);
void presenceChanged(Presence state);
+ void showImageChanged(ShowImage state);
void ringtoneChanged(QString ringtone);
void microphoneChanged(QString microphone);
void cameraChanged(QString camera);
@@ -418,6 +430,7 @@ private:
QString font_;
QString emojiFont_;
Presence presence_;
+ ShowImage showImage_;
QString ringtone_;
QString microphone_;
QString camera_;
@@ -490,6 +503,7 @@ class UserSettingsModel : public QAbstractListModel
TimelineSection,
TimelineMaxWidth,
EnlargeEmojiOnlyMessages,
+ ShowImage,
OpenImageExternal,
OpenVideoExternal,
ButtonsInTimeline,
diff --git a/src/notifications/Manager.cpp b/src/notifications/Manager.cpp
index d15eea51..f67e01ff 100644
--- a/src/notifications/Manager.cpp
+++ b/src/notifications/Manager.cpp
@@ -5,9 +5,33 @@
#include "notifications/Manager.h"
#include "Cache.h"
+#include "Cache_p.h"
#include "EventAccessors.h"
+#include "UserSettingsPage.h"
#include "Utils.h"
+bool
+NotificationsManager::allowShowingImages(const mtx::responses::Notification ¬ification)
+{
+ auto show = UserSettings::instance()->showImage();
+
+ switch (show) {
+ case UserSettings::ShowImage::Always:
+ return true;
+ case UserSettings::ShowImage::OnlyPrivate: {
+ auto accessRules = cache::client()
+ ->getStateEvent<mtx::events::state::JoinRules>(notification.room_id)
+ .value_or(mtx::events::StateEvent<mtx::events::state::JoinRules>{})
+ .content;
+
+ return accessRules.join_rule != mtx::events::state::JoinRule::Public;
+ }
+ case UserSettings::ShowImage::Never:
+ default:
+ return false;
+ }
+}
+
QString
NotificationsManager::getMessageTemplate(const mtx::responses::Notification ¬ification)
{
diff --git a/src/notifications/Manager.h b/src/notifications/Manager.h
index 707a4fb3..b748b510 100644
--- a/src/notifications/Manager.h
+++ b/src/notifications/Manager.h
@@ -66,7 +66,6 @@ private:
const QString &text,
const QImage &icon);
void closeNotification(uint id);
-
const bool hasMarkup_;
const bool hasImages_;
#endif
@@ -111,6 +110,7 @@ private slots:
private:
QString getMessageTemplate(const mtx::responses::Notification ¬ification);
+ bool allowShowingImages(const mtx::responses::Notification ¬ification);
// notification ID to (room ID, event ID)
// Only populated on Linux atm
diff --git a/src/notifications/ManagerLinux.cpp b/src/notifications/ManagerLinux.cpp
index 75ba1886..1704d3a3 100644
--- a/src/notifications/ManagerLinux.cpp
+++ b/src/notifications/ManagerLinux.cpp
@@ -114,7 +114,7 @@ NotificationsManager::postNotification(const mtx::responses::Notification ¬if
}
if (hasMarkup_) {
- if (hasImages_ &&
+ if (hasImages_ && allowShowingImages(notification) &&
(mtx::accessors::msg_type(notification.event) == mtx::events::MessageType::Image ||
mtx::accessors::event_type(notification.event) == mtx::events::EventType::Sticker)) {
MxcImageProvider::download(
diff --git a/src/notifications/ManagerMac.cpp b/src/notifications/ManagerMac.cpp
index ee5639e4..03b2480d 100644
--- a/src/notifications/ManagerMac.cpp
+++ b/src/notifications/ManagerMac.cpp
@@ -93,7 +93,9 @@ NotificationsManager::postNotification(const mtx::responses::Notification ¬if
} else {
const QString messageInfo =
(isReply ? tr("%1 replied to a message") : tr("%1 sent a message")).arg(sender);
- if (mtx::accessors::msg_type(notification.event) == mtx::events::MessageType::Image)
+ if (allowShowingImages(notification) &&
+ (mtx::accessors::msg_type(notification.event) == mtx::events::MessageType::Image ||
+ mtx::accessors::event_type(notification.event) == mtx::events::EventType::Sticker))
MxcImageProvider::download(
QString::fromStdString(mtx::accessors::url(notification.event)).remove("mxc://"),
QSize(200, 80),
diff --git a/src/notifications/ManagerWin.cpp b/src/notifications/ManagerWin.cpp
index a69afa4e..03fd4782 100644
--- a/src/notifications/ManagerWin.cpp
+++ b/src/notifications/ManagerWin.cpp
@@ -83,8 +83,9 @@ NotificationsManager::postNotification(const mtx::responses::Notification ¬if
if (!icon.save(iconPath))
iconPath.clear();
- if (mtx::accessors::msg_type(notification.event) == mtx::events::MessageType::Image ||
- mtx::accessors::msg_type(notification.event) == mtx::events::MessageType::Image) {
+ if (allowShowingImages(notification) &&
+ (mtx::accessors::msg_type(notification.event) == mtx::events::MessageType::Image ||
+ mtx::accessors::msg_type(notification.event) == mtx::events::MessageType::Image)) {
MxcImageProvider::download(
QString::fromStdString(mtx::accessors::url(notification.event))
.remove(QStringLiteral("mxc://")),
diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp
index 48b58ee5..eea345b5 100644
--- a/src/timeline/TimelineModel.cpp
+++ b/src/timeline/TimelineModel.cpp
@@ -3387,4 +3387,26 @@ TimelineModel::parentSpace()
return parentSummary.get();
}
+bool
+TimelineModel::showImage() const
+{
+ auto show = UserSettings::instance()->showImage();
+
+ switch (show) {
+ case UserSettings::ShowImage::Always:
+ return true;
+ case UserSettings::ShowImage::OnlyPrivate: {
+ auto accessRules = cache::client()
+ ->getStateEvent<mtx::events::state::JoinRules>(room_id_.toStdString())
+ .value_or(mtx::events::StateEvent<mtx::events::state::JoinRules>{})
+ .content;
+
+ return accessRules.join_rule != mtx::events::state::JoinRule::Public;
+ }
+ case UserSettings::ShowImage::Never:
+ default:
+ return false;
+ }
+}
+
#include "moc_TimelineModel.cpp"
diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h
index 3a189e39..9f96c62d 100644
--- a/src/timeline/TimelineModel.h
+++ b/src/timeline/TimelineModel.h
@@ -323,6 +323,7 @@ public:
const mtx::events::StateEvent<mtx::events::msc2545::ImagePack> &event) const;
Q_INVOKABLE QString formatPolicyRule(const QString &id) const;
Q_INVOKABLE QVariantMap formatRedactedEvent(const QString &id);
+ Q_INVOKABLE bool showImage() const;
Q_INVOKABLE void viewRawMessage(const QString &id);
Q_INVOKABLE void forwardMessage(const QString &eventId, QString roomId);
|