diff --git a/Telegram/SourceFiles/ayu/ayu_settings.cpp b/Telegram/SourceFiles/ayu/ayu_settings.cpp index 78da91e6a4..206daa18d7 100644 --- a/Telegram/SourceFiles/ayu/ayu_settings.cpp +++ b/Telegram/SourceFiles/ayu/ayu_settings.cpp @@ -327,6 +327,8 @@ AyuGramSettings::AyuGramSettings() { showMessageSeconds = false; showMessageShot = true; + filterZalgo = true; + // ~ Confirmations stickerConfirmation = false; gifConfirmation = false; @@ -664,6 +666,10 @@ void set_showMessageShot(bool val) { settings->showMessageShot = val; } +void set_filterZalgo(bool val) { + settings->filterZalgo = val; +} + void set_stickerConfirmation(bool val) { settings->stickerConfirmation = val; } diff --git a/Telegram/SourceFiles/ayu/ayu_settings.h b/Telegram/SourceFiles/ayu/ayu_settings.h index 679ff29e19..75734fec69 100644 --- a/Telegram/SourceFiles/ayu/ayu_settings.h +++ b/Telegram/SourceFiles/ayu/ayu_settings.h @@ -140,6 +140,8 @@ public: bool showMessageSeconds; bool showMessageShot; + bool filterZalgo; + bool stickerConfirmation; bool gifConfirmation; bool voiceConfirmation; @@ -247,6 +249,8 @@ void set_showPeerId(int val); void set_showMessageSeconds(bool val); void set_showMessageShot(bool val); +void set_filterZalgo(bool val); + void set_stickerConfirmation(bool val); void set_gifConfirmation(bool val); void set_voiceConfirmation(bool val); @@ -333,6 +337,7 @@ inline void to_json(nlohmann::json &nlohmann_json_j, const AyuGramSettings &nloh NLOHMANN_JSON_TO(showPeerId) NLOHMANN_JSON_TO(showMessageSeconds) NLOHMANN_JSON_TO(showMessageShot) + NLOHMANN_JSON_TO(filterZalgo) NLOHMANN_JSON_TO(stickerConfirmation) NLOHMANN_JSON_TO(gifConfirmation) NLOHMANN_JSON_TO(voiceConfirmation) @@ -418,6 +423,7 @@ inline void from_json(const nlohmann::json &nlohmann_json_j, AyuGramSettings &nl NLOHMANN_JSON_FROM_WITH_DEFAULT(showPeerId) NLOHMANN_JSON_FROM_WITH_DEFAULT(showMessageSeconds) NLOHMANN_JSON_FROM_WITH_DEFAULT(showMessageShot) + NLOHMANN_JSON_FROM_WITH_DEFAULT(filterZalgo) NLOHMANN_JSON_FROM_WITH_DEFAULT(stickerConfirmation) NLOHMANN_JSON_FROM_WITH_DEFAULT(gifConfirmation) NLOHMANN_JSON_FROM_WITH_DEFAULT(voiceConfirmation) diff --git a/Telegram/SourceFiles/ayu/ui/settings/settings_general.cpp b/Telegram/SourceFiles/ayu/ui/settings/settings_general.cpp index 0e428317ae..7f7428fe4c 100644 --- a/Telegram/SourceFiles/ayu/ui/settings/settings_general.cpp +++ b/Telegram/SourceFiles/ayu/ui/settings/settings_general.cpp @@ -9,9 +9,11 @@ #include "lang_auto.h" #include "settings_ayu_utils.h" #include "ayu/ayu_settings.h" +#include "core/application.h" #include "settings/settings_common.h" #include "styles/style_settings.h" #include "ui/vertical_list.h" +#include "ui/boxes/confirm_box.h" #include "ui/boxes/single_choice_box.h" #include "ui/widgets/buttons.h" #include "ui/wrap/vertical_layout.h" @@ -204,6 +206,37 @@ void SetupQoLToggles(not_null container, not_nulltoggleOn( + rpl::single(settings->filterZalgo) + )->toggledValue( + ) | rpl::filter( + [=](bool enabled) + { + return (enabled != settings->filterZalgo); + }) | on_next( + [=](bool enabled) + { + AyuSettings::set_filterZalgo(enabled); + AyuSettings::save(); + + // restart because hooks for filter are in Peer::setName which can be updated only on restart + // same for HistoryItem::setText + controller->show(Ui::MakeConfirmBox({ + .text = tr::lng_settings_need_restart(), + .confirmed = [] + { + Core::Restart(); + }, + .confirmText = tr::lng_settings_restart_now(), + .cancelText = tr::lng_settings_restart_later(), + })); + }, + container->lifetime()); + AddButtonWithIcon( container, tr::ayu_SettingsShowMessageSeconds(), diff --git a/Telegram/SourceFiles/ayu/utils/telegram_helpers.cpp b/Telegram/SourceFiles/ayu/utils/telegram_helpers.cpp index 9605af10a7..f984cb4ae2 100644 --- a/Telegram/SourceFiles/ayu/utils/telegram_helpers.cpp +++ b/Telegram/SourceFiles/ayu/utils/telegram_helpers.cpp @@ -67,6 +67,9 @@ const auto regDateBotUsername = QString("exteraAuthBot"); constexpr auto regDateBotFallbackId = 6247153446L; const auto regDateBotFallbackUsername = QString("ayugrambot"); +const auto kZalgoPattern = QStringLiteral( + "\\p{Mn}{3,}|[\\x{202A}-\\x{202E}\\x{2066}-\\x{2069}\\x{200E}\\x{200F}\\x{061C}]"); + } Main::Session *getSession(ID userId) { @@ -1043,6 +1046,35 @@ PeerData *getPeerFromDialogId(unsigned long long id) { return getPeerFromDialogId(id); } +QString filterZalgo(const QString &text) { + static const auto regex = QRegularExpression( + kZalgoPattern, + QRegularExpression::UseUnicodePropertiesOption); + + auto match = regex.match(text); + if (!match.hasMatch()) { + return text; + } + + QString output; + output.reserve(text.length()); + int lastEnd = 0; + + auto it = regex.globalMatch(text); + while (it.hasNext()) { + match = it.next(); + output.append(text.mid(lastEnd, match.capturedStart() - lastEnd)); + const int matchLength = match.capturedLength(); + for (int i = 0; i < matchLength; i++) { + output.append(QChar(0x2060)); + } + lastEnd = match.capturedEnd(); + } + output.append(text.mid(lastEnd)); + + return output; +} + void getUserRegistrationDateInner( not_null user, ID botId, diff --git a/Telegram/SourceFiles/ayu/utils/telegram_helpers.h b/Telegram/SourceFiles/ayu/utils/telegram_helpers.h index a74e3dd0f8..f1dadd0b91 100644 --- a/Telegram/SourceFiles/ayu/utils/telegram_helpers.h +++ b/Telegram/SourceFiles/ayu/utils/telegram_helpers.h @@ -106,5 +106,7 @@ not_null currentSession(); PeerData* getPeerFromDialogId(ID id); PeerData* getPeerFromDialogId(unsigned long long id); +QString filterZalgo(const QString &text); + void getRegistrationDate(not_null peer, Fn callback); diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index d7b018e16e..cafac704ee 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -40,6 +40,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/unread_badge.h" #include "window/notifications_manager.h" +// AyuGram includes +#include "ayu/ayu_settings.h" +#include "ayu/utils/telegram_helpers.h" + + namespace { using UpdateFlag = Data::PeerUpdate::Flag; @@ -133,7 +138,12 @@ void ChannelData::setPhoto(const MTPChatPhoto &photo) { void ChannelData::setName( const QString &newName, const QString &newUsername) { - updateNameDelayed(newName.isEmpty() ? name() : newName, {}, newUsername); + auto filteredName = newName; + const auto &settings = AyuSettings::getInstance(); + if (settings.filterZalgo) { + filteredName = filterZalgo(filteredName); + } + updateNameDelayed(filteredName.isEmpty() ? name() : filteredName, {}, newUsername); } void ChannelData::setUsername(const QString &username) { diff --git a/Telegram/SourceFiles/data/data_chat.cpp b/Telegram/SourceFiles/data/data_chat.cpp index dca11acce5..c720ac88a8 100644 --- a/Telegram/SourceFiles/data/data_chat.cpp +++ b/Telegram/SourceFiles/data/data_chat.cpp @@ -20,6 +20,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "apiwrap.h" #include "api/api_invite_links.h" +// AyuGram includes +#include "ayu/ayu_settings.h" +#include "ayu/utils/telegram_helpers.h" + + namespace { using UpdateFlag = Data::PeerUpdate::Flag; @@ -112,7 +117,12 @@ bool ChatData::anyoneCanAddMembers() const { } void ChatData::setName(const QString &newName) { - updateNameDelayed(newName.isEmpty() ? name() : newName, {}, {}); + auto filteredName = newName; + const auto &settings = AyuSettings::getInstance(); + if (settings.filterZalgo) { + filteredName = filterZalgo(filteredName); + } + updateNameDelayed(filteredName.isEmpty() ? name() : filteredName, {}, {}); } void ChatData::applyEditAdmin(not_null user, bool isAdmin) { diff --git a/Telegram/SourceFiles/data/data_user.cpp b/Telegram/SourceFiles/data/data_user.cpp index 11a8ab006b..de99780d12 100644 --- a/Telegram/SourceFiles/data/data_user.cpp +++ b/Telegram/SourceFiles/data/data_user.cpp @@ -346,17 +346,26 @@ void UserData::setName( const QString &newLastName, const QString &newPhoneName, const QString &newUsername) { - bool changeName = !newFirstName.isEmpty() || !newLastName.isEmpty(); + auto filteredFirstName = newFirstName; + auto filteredLastName = newLastName; + + const auto &settings = AyuSettings::getInstance(); + if (settings.filterZalgo) { + filteredFirstName = filterZalgo(filteredFirstName); + filteredLastName = filterZalgo(filteredLastName); + } + + bool changeName = !filteredFirstName.isEmpty() || !filteredLastName.isEmpty(); QString newFullName; - if (changeName && newFirstName.trimmed().isEmpty()) { - firstName = newLastName; + if (changeName && filteredFirstName.trimmed().isEmpty()) { + firstName = filteredLastName; lastName = QString(); newFullName = firstName; } else { if (changeName) { - firstName = newFirstName; - lastName = newLastName; + firstName = filteredFirstName; + lastName = filteredLastName; } newFullName = lastName.isEmpty() ? firstName diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 71902b2872..d0931d5db3 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -74,7 +74,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL // AyuGram includes #include "ayu/ayu_settings.h" -#include "ayu/ayu_state.h" #include "ayu/features/message_shot/message_shot.h" #include "ayu/utils/telegram_helpers.h" #include "ui/emoji_config.h" @@ -3952,6 +3951,10 @@ FullReplyTo HistoryItem::replyTo() const { void HistoryItem::setText(const TextWithEntities &textWithEntities) { auto text = textWithEntities; + const auto &settings = AyuSettings::getInstance(); + if (settings.filterZalgo) { + text.text = filterZalgo(text.text); + } static const auto kEmojiLinkRegex = QRegularExpression( QStringLiteral("^tg://emoji\\?id=(\\d+)$"));