diff --git a/resources/qml/TimelineView.qml b/resources/qml/TimelineView.qml index b5097bc7..145a82ce 100644 --- a/resources/qml/TimelineView.qml +++ b/resources/qml/TimelineView.qml @@ -26,6 +26,7 @@ Page { category: "user" property bool avatar_circles: true property string emoji_font_family: "default" + property double font_size: Qt.application.font.pointSize } Settings { @@ -33,6 +34,7 @@ Page { category: "user/timeline" property bool buttons: true property bool message_hover_highlight: false + property bool enlarge_emoji_only_msg: false } Menu { diff --git a/resources/qml/delegates/TextMessage.qml b/resources/qml/delegates/TextMessage.qml index bef4f76d..d17723f3 100644 --- a/resources/qml/delegates/TextMessage.qml +++ b/resources/qml/delegates/TextMessage.qml @@ -6,4 +6,5 @@ MatrixText { width: parent ? parent.width : undefined height: isReply ? Math.min(chat.height / 8, implicitHeight) : undefined clip: true + font.pointSize: (timelineSettings.enlarge_emoji_only_msg && model.data.isOnlyEmoji > 0 && model.data.isOnlyEmoji < 4) ? settings.font_size * 3 : settings.font_size } diff --git a/src/UserSettingsPage.cpp b/src/UserSettingsPage.cpp index 6af08e12..36fd768c 100644 --- a/src/UserSettingsPage.cpp +++ b/src/UserSettingsPage.cpp @@ -58,6 +58,8 @@ UserSettings::load() isButtonsInTimelineEnabled_ = settings.value("user/timeline/buttons", true).toBool(); isMessageHoverHighlightEnabled_ = settings.value("user/timeline/message_hover_highlight", false).toBool(); + isEnlargeEmojiOnlyMessagesEnabled_ = + settings.value("user/timeline/enlarge_emoji_only_msg", false).toBool(); isMarkdownEnabled_ = settings.value("user/markdown_enabled", true).toBool(); isTypingNotificationsEnabled_ = settings.value("user/typing_notifications", true).toBool(); sortByImportance_ = settings.value("user/sort_by_unread", true).toBool(); @@ -168,6 +170,7 @@ UserSettings::save() settings.beginGroup("timeline"); settings.setValue("buttons", isButtonsInTimelineEnabled_); settings.setValue("message_hover_highlight", isMessageHoverHighlightEnabled_); + settings.setValue("enlarge_emoji_only_msg", isEnlargeEmojiOnlyMessagesEnabled_); settings.endGroup(); settings.setValue("avatar_circles", avatarCircles_); @@ -231,22 +234,23 @@ UserSettingsPage::UserSettingsPage(QSharedPointer settings, QWidge general_->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); general_->setFont(font); - trayToggle_ = new Toggle{this}; - startInTrayToggle_ = new Toggle{this}; - avatarCircles_ = new Toggle{this}; - decryptSidebar_ = new Toggle(this); - groupViewToggle_ = new Toggle{this}; - timelineButtonsToggle_ = new Toggle{this}; - typingNotifications_ = new Toggle{this}; - messageHoverHighlight_ = new Toggle{this}; - sortByImportance_ = new Toggle{this}; - readReceipts_ = new Toggle{this}; - markdownEnabled_ = new Toggle{this}; - desktopNotifications_ = new Toggle{this}; - scaleFactorCombo_ = new QComboBox{this}; - fontSizeCombo_ = new QComboBox{this}; - fontSelectionCombo_ = new QComboBox{this}; - emojiFontSelectionCombo_ = new QComboBox{this}; + trayToggle_ = new Toggle{this}; + startInTrayToggle_ = new Toggle{this}; + avatarCircles_ = new Toggle{this}; + decryptSidebar_ = new Toggle(this); + groupViewToggle_ = new Toggle{this}; + timelineButtonsToggle_ = new Toggle{this}; + typingNotifications_ = new Toggle{this}; + messageHoverHighlight_ = new Toggle{this}; + enlargeEmojiOnlyMessages_ = new Toggle{this}; + sortByImportance_ = new Toggle{this}; + readReceipts_ = new Toggle{this}; + markdownEnabled_ = new Toggle{this}; + desktopNotifications_ = new Toggle{this}; + scaleFactorCombo_ = new QComboBox{this}; + fontSizeCombo_ = new QComboBox{this}; + fontSelectionCombo_ = new QComboBox{this}; + emojiFontSelectionCombo_ = new QComboBox{this}; if (!settings_->isTrayEnabled()) startInTrayToggle_->setDisabled(true); @@ -350,6 +354,7 @@ UserSettingsPage::UserSettingsPage(QSharedPointer settings, QWidge boxWrap(tr("Send messages as Markdown"), markdownEnabled_); boxWrap(tr("Desktop notifications"), desktopNotifications_); boxWrap(tr("Highlight message on hover"), messageHoverHighlight_); + boxWrap(tr("Large Emoji in timeline"), enlargeEmojiOnlyMessages_); formLayout_->addRow(uiLabel_); formLayout_->addRow(new HorizontalLine{this}); @@ -472,6 +477,10 @@ UserSettingsPage::UserSettingsPage(QSharedPointer settings, QWidge settings_->setMessageHoverHighlight(!isDisabled); }); + connect(enlargeEmojiOnlyMessages_, &Toggle::toggled, this, [this](bool isDisabled) { + settings_->setEnlargeEmojiOnlyMessages(!isDisabled); + }); + connect( sessionKeysImportBtn, &QPushButton::clicked, this, &UserSettingsPage::importSessionKeys); @@ -505,6 +514,7 @@ UserSettingsPage::showEvent(QShowEvent *) markdownEnabled_->setState(!settings_->isMarkdownEnabled()); desktopNotifications_->setState(!settings_->hasDesktopNotifications()); messageHoverHighlight_->setState(!settings_->isMessageHoverHighlightEnabled()); + enlargeEmojiOnlyMessages_->setState(!settings_->isEnlargeEmojiOnlyMessagesEnabled()); deviceIdValue_->setText(QString::fromStdString(http::client()->device_id())); deviceFingerprintValue_->setText( diff --git a/src/UserSettingsPage.h b/src/UserSettingsPage.h index 088bbfb5..7dfa3913 100644 --- a/src/UserSettingsPage.h +++ b/src/UserSettingsPage.h @@ -49,6 +49,11 @@ public: isMessageHoverHighlightEnabled_ = state; save(); } + void setEnlargeEmojiOnlyMessages(bool state) + { + isEnlargeEmojiOnlyMessagesEnabled_ = state; + save(); + } void setTray(bool state) { isTrayEnabled_ = state; @@ -124,6 +129,10 @@ public: QString theme() const { return !theme_.isEmpty() ? theme_ : defaultTheme_; } bool isMessageHoverHighlightEnabled() const { return isMessageHoverHighlightEnabled_; } + bool isEnlargeEmojiOnlyMessagesEnabled() const + { + return isEnlargeEmojiOnlyMessagesEnabled_; + } bool isTrayEnabled() const { return isTrayEnabled_; } bool isStartInTrayEnabled() const { return isStartInTrayEnabled_; } bool isGroupViewEnabled() const { return isGroupViewEnabled_; } @@ -151,6 +160,7 @@ private: : "system"; QString theme_; bool isMessageHoverHighlightEnabled_; + bool isEnlargeEmojiOnlyMessagesEnabled_; bool isTrayEnabled_; bool isStartInTrayEnabled_; bool isGroupViewEnabled_; @@ -211,6 +221,7 @@ private: Toggle *timelineButtonsToggle_; Toggle *typingNotifications_; Toggle *messageHoverHighlight_; + Toggle *enlargeEmojiOnlyMessages_; Toggle *sortByImportance_; Toggle *readReceipts_; Toggle *markdownEnabled_; diff --git a/src/Utils.cpp b/src/Utils.cpp index 7f11a8cd..d539eac5 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -51,6 +51,14 @@ utils::localUser() return QString::fromStdString(http::client()->user_id().to_string()); } +bool +utils::codepointIsEmoji(uint code) +{ + // TODO: Be more precise here. + return (code >= 0x2600 && code <= 0x27bf) || (code >= 0x1f300 && code <= 0x1f3ff) || + (code >= 0x1f000 && code <= 0x1faff); +} + QString utils::replaceEmoji(const QString &body) { @@ -63,9 +71,7 @@ utils::replaceEmoji(const QString &body) bool insideFontBlock = false; for (auto &code : utf32_string) { - // TODO: Be more precise here. - if ((code >= 0x2600 && code <= 0x27bf) || (code >= 0x1f300 && code <= 0x1f3ff) || - (code >= 0x1f000 && code <= 0x1faff)) { + if (utils::codepointIsEmoji(code)) { if (!insideFontBlock) { fmtBody += QString(""); insideFontBlock = true; diff --git a/src/Utils.h b/src/Utils.h index d3f66246..80f2aa70 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -36,6 +36,9 @@ namespace utils { using TimelineEvent = mtx::events::collections::TimelineEvents; +bool +codepointIsEmoji(uint code); + QString replaceEmoji(const QString &body); diff --git a/src/timeline/TimelineModel.cpp b/src/timeline/TimelineModel.cpp index 6e653f10..6a4de92c 100644 --- a/src/timeline/TimelineModel.cpp +++ b/src/timeline/TimelineModel.cpp @@ -207,6 +207,7 @@ TimelineModel::roleNames() const {Section, "section"}, {Type, "type"}, {TypeString, "typeString"}, + {IsOnlyEmoji, "isOnlyEmoji"}, {Body, "body"}, {FormattedBody, "formattedBody"}, {UserId, "userId"}, @@ -272,6 +273,22 @@ TimelineModel::data(const QString &id, int role) const return QVariant(toRoomEventType(event)); case TypeString: return QVariant(toRoomEventTypeString(event)); + case IsOnlyEmoji: { + QString qBody = QString::fromStdString(body(event)); + + QVector utf32_string = qBody.toUcs4(); + int emojiCount = 0; + + for (auto &code : utf32_string) { + if (utils::codepointIsEmoji(code)) { + emojiCount++; + } else { + return QVariant(0); + } + } + + return QVariant(emojiCount); + } case Body: return QVariant(utils::replaceEmoji(QString::fromStdString(body(event)))); case FormattedBody: { @@ -374,6 +391,7 @@ TimelineModel::data(const QString &id, int role) const // m.insert(names[Section], data(id, static_cast(Section))); m.insert(names[Type], data(id, static_cast(Type))); m.insert(names[TypeString], data(id, static_cast(TypeString))); + m.insert(names[IsOnlyEmoji], data(id, static_cast(IsOnlyEmoji))); m.insert(names[Body], data(id, static_cast(Body))); m.insert(names[FormattedBody], data(id, static_cast(FormattedBody))); m.insert(names[UserId], data(id, static_cast(UserId))); diff --git a/src/timeline/TimelineModel.h b/src/timeline/TimelineModel.h index 0e9ddb72..dc7b4985 100644 --- a/src/timeline/TimelineModel.h +++ b/src/timeline/TimelineModel.h @@ -140,6 +140,7 @@ public: Section, Type, TypeString, + IsOnlyEmoji, Body, FormattedBody, UserId,