From ca4cbddba6a3856bcc3303c4e897c7bc0a218e63 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 1 Mar 2024 12:29:03 +0400 Subject: [PATCH] Check shortcuts / messages limits. --- Telegram/Resources/langs/lang.strings | 3 + .../chat_helpers/stickers_list_footer.cpp | 5 +- .../history_view_compose_controls.cpp | 1 + .../business/settings_away_message.cpp | 45 ++++++++-- .../settings/business/settings_greeting.cpp | 44 ++++++++-- .../business/settings_quick_replies.cpp | 71 +++++++++------- .../business/settings_recipients_helper.cpp | 83 +++++++++++++++++++ .../business/settings_recipients_helper.h | 22 +++++ .../business/settings_shortcut_messages.cpp | 24 +++++- .../SourceFiles/settings/settings_main.cpp | 4 - Telegram/lib_ui | 2 +- 11 files changed, 253 insertions(+), 51 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 896fdc415..add970d06 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -2226,6 +2226,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_greeting_empty_title" = "New Greeting Message"; "lng_greeting_empty_about" = "Create greetings that will be automatically sent to new customers."; "lng_greeting_message_placeholder" = "Add a Greeting"; +"lng_greeting_limit_reached" = "You have too many quick replies. Remove one to add a greeting message."; "lng_away_title" = "Away Message"; "lng_away_about" = "Automatically reply with a message when you are away."; @@ -2242,7 +2243,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_away_empty_title" = "New Away Message"; "lng_away_empty_about" = "Add messages that will be automatically sent when you are off."; "lng_away_message_placeholder" = "Add an Away Message"; +"lng_away_limit_reached" = "You have too many quick replies. Remove one to add an away message."; +"lng_business_edit_messages" = "Edit messages"; "lng_business_limit_reached#one" = "Limit of {count} message reached."; "lng_business_limit_reached#other" = "Limit of {count} messages reached."; diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_footer.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_footer.cpp index 4534818d3..6659343d2 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_footer.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_footer.cpp @@ -114,10 +114,7 @@ std::optional SetIdEmojiSection(uint64 id) { rpl::producer> GifSectionsValue( not_null session) { const auto config = &session->account().appConfig(); - return rpl::single( - rpl::empty_value() - ) | rpl::then( - config->refreshed() + return config->value( ) | rpl::map([=] { return config->get>( u"gif_search_emojies"_q, diff --git a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp index 9cfec19f5..bd8d6cb12 100644 --- a/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp +++ b/Telegram/SourceFiles/history/view/controls/history_view_compose_controls.cpp @@ -2347,6 +2347,7 @@ void SetupRestrictionView( }); state->label = makeLabel(value.text, st->premiumRequired.label); } + state->updateGeometries(); }, widget->lifetime()); widget->sizeValue( diff --git a/Telegram/SourceFiles/settings/business/settings_away_message.cpp b/Telegram/SourceFiles/settings/business/settings_away_message.cpp index 69ac74bee..739d12d2a 100644 --- a/Telegram/SourceFiles/settings/business/settings_away_message.cpp +++ b/Telegram/SourceFiles/settings/business/settings_away_message.cpp @@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "settings/business/settings_shortcut_messages.h" #include "ui/boxes/choose_date_time.h" #include "ui/text/text_utilities.h" +#include "ui/toast/toast.h" #include "ui/widgets/buttons.h" #include "ui/widgets/checkbox.h" #include "ui/wrap/slide_wrap.h" @@ -43,6 +44,8 @@ private: void setupContent(not_null controller); void save(); + rpl::variable _canHave; + rpl::event_stream<> _deactivateOnAttempt; rpl::variable _recipients; rpl::variable _schedule; rpl::variable _enabled; @@ -231,13 +234,35 @@ void AwayMessage::setupContent( .aboutMargins = st::peerAppearanceCoverLabelMargin, }); + const auto session = &controller->session(); + _canHave = rpl::combine( + ShortcutsCountValue(session), + ShortcutsLimitValue(session), + ShortcutExistsValue(session, u"away"_q), + (_1 < _2) || _3); + Ui::AddSkip(content); const auto enabled = content->add(object_ptr( content, tr::lng_away_enable(), st::settingsButtonNoIcon - ))->toggleOn(rpl::single(!disabled)); + ))->toggleOn(rpl::single( + !disabled + ) | rpl::then(rpl::merge( + _canHave.value() | rpl::filter(!_1), + _deactivateOnAttempt.events() | rpl::map_to(false) + ))); + _enabled = enabled->toggledValue(); + _enabled.value() | rpl::filter(_1) | rpl::start_with_next([=] { + if (!_canHave.current()) { + controller->showToast({ + .text = tr::lng_away_limit_reached(tr::now), + .adaptive = true, + }); + _deactivateOnAttempt.fire({}); + } + }, lifetime()); const auto wrap = content->add( object_ptr>( @@ -254,11 +279,21 @@ void AwayMessage::setupContent( object_ptr(inner))); const auto createInner = createWrap->entity(); Ui::AddSkip(createInner); - const auto create = createInner->add(object_ptr( + const auto create = AddButtonWithLabel( createInner, - tr::lng_away_create(), - st::settingsButtonLightNoIcon - )); + rpl::conditional( + ShortcutExistsValue(session, u"away"_q), + tr::lng_business_edit_messages(), + tr::lng_away_create()), + ShortcutMessagesCountValue( + session, + u"away"_q + ) | rpl::map([=](int count) { + return count + ? tr::lng_forum_messages(tr::now, lt_count, count) + : QString(); + }), + st::settingsButtonLightNoIcon); create->setClickedCallback([=] { const auto owner = &controller->session().data(); const auto id = owner->shortcutMessages().emplaceShortcut("away"); diff --git a/Telegram/SourceFiles/settings/business/settings_greeting.cpp b/Telegram/SourceFiles/settings/business/settings_greeting.cpp index 96b2615c4..43cba0763 100644 --- a/Telegram/SourceFiles/settings/business/settings_greeting.cpp +++ b/Telegram/SourceFiles/settings/business/settings_greeting.cpp @@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "settings/business/settings_recipients_helper.h" #include "ui/layers/generic_box.h" #include "ui/text/text_utilities.h" +#include "ui/toast/toast.h" #include "ui/widgets/box_content_divider.h" #include "ui/widgets/buttons.h" #include "ui/widgets/vertical_drum_picker.h" @@ -53,6 +54,8 @@ private: Ui::RoundRect _bottomSkipRounding; rpl::variable _recipients; + rpl::variable _canHave; + rpl::event_stream<> _deactivateOnAttempt; rpl::variable _noActivityDays; rpl::variable _enabled; @@ -198,14 +201,35 @@ void Greeting::setupContent( .aboutMargins = st::peerAppearanceCoverLabelMargin, }); + const auto session = &controller->session(); + _canHave = rpl::combine( + ShortcutsCountValue(session), + ShortcutsLimitValue(session), + ShortcutExistsValue(session, u"hello"_q), + (_1 < _2) || _3); + Ui::AddSkip(content); const auto enabled = content->add(object_ptr( content, tr::lng_greeting_enable(), st::settingsButtonNoIcon - ))->toggleOn(rpl::single(!disabled)); + ))->toggleOn(rpl::single( + !disabled + ) | rpl::then(rpl::merge( + _canHave.value() | rpl::filter(!_1), + _deactivateOnAttempt.events() | rpl::map_to(false) + ))); _enabled = enabled->toggledValue(); + _enabled.value() | rpl::filter(_1) | rpl::start_with_next([=] { + if (!_canHave.current()) { + controller->showToast({ + .text = tr::lng_greeting_limit_reached(tr::now), + .adaptive = true, + }); + _deactivateOnAttempt.fire({}); + } + }, lifetime()); Ui::AddSkip(content); @@ -237,11 +261,21 @@ void Greeting::setupContent( object_ptr(inner))); const auto createInner = createWrap->entity(); Ui::AddSkip(createInner); - const auto create = createInner->add(object_ptr( + const auto create = AddButtonWithLabel( createInner, - tr::lng_greeting_create(), - st::settingsButtonLightNoIcon - )); + rpl::conditional( + ShortcutExistsValue(session, u"hello"_q), + tr::lng_business_edit_messages(), + tr::lng_greeting_create()), + ShortcutMessagesCountValue( + session, + u"hello"_q + ) | rpl::map([=](int count) { + return count + ? tr::lng_forum_messages(tr::now, lt_count, count) + : QString(); + }), + st::settingsButtonLightNoIcon); create->setClickedCallback([=] { const auto owner = &controller->session().data(); const auto id = owner->shortcutMessages().emplaceShortcut("hello"); diff --git a/Telegram/SourceFiles/settings/business/settings_quick_replies.cpp b/Telegram/SourceFiles/settings/business/settings_quick_replies.cpp index aac5f918c..53fb228ba 100644 --- a/Telegram/SourceFiles/settings/business/settings_quick_replies.cpp +++ b/Telegram/SourceFiles/settings/business/settings_quick_replies.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/business/data_shortcut_messages.h" #include "data/data_session.h" #include "lang/lang_keys.h" +#include "main/main_account.h" #include "main/main_session.h" #include "settings/business/settings_recipients_helper.h" #include "settings/business/settings_shortcut_messages.h" @@ -42,6 +43,8 @@ private: void setupContent(not_null controller); void save(); + rpl::variable _count; + }; QuickReplies::QuickReplies( @@ -75,29 +78,47 @@ void QuickReplies::setupContent( .about = tr::lng_replies_about(Ui::Text::WithEntities), .aboutMargins = st::peerAppearanceCoverLabelMargin, }); - Ui::AddSkip(content); - const auto add = content->add(object_ptr( - content, - tr::lng_replies_add(), - st::settingsButtonNoIcon - )); + + const auto addWrap = content->add( + object_ptr(content)); const auto owner = &controller->session().data(); const auto messages = &owner->shortcutMessages(); - add->setClickedCallback([=] { - const auto submit = [=](QString name, Fn close) { - const auto id = messages->emplaceShortcut(name); - showOther(ShortcutMessagesId(id)); - close(); - }; - controller->show( - Box(EditShortcutNameBox, QString(), crl::guard(this, submit))); - }); + rpl::combine( + _count.value(), + ShortcutsLimitValue(&controller->session()) + ) | rpl::start_with_next([=](int count, int limit) { + while (addWrap->count()) { + delete addWrap->widgetAt(0); + } + if (count < limit) { + const auto add = addWrap->add(object_ptr( + addWrap, + tr::lng_replies_add(), + st::settingsButtonNoIcon + )); - const auto dividerWrap = content->add( - object_ptr(content)); + add->setClickedCallback([=] { + const auto submit = [=](QString name, Fn close) { + const auto id = messages->emplaceShortcut(name); + showOther(ShortcutMessagesId(id)); + close(); + }; + controller->show( + Box(EditShortcutNameBox, QString(), crl::guard(this, submit))); + }); + if (count > 0) { + AddSkip(addWrap); + AddDivider(addWrap); + AddSkip(addWrap); + } + } + if (const auto width = content->width()) { + content->resizeToWidth(width); + } + }, lifetime()); const auto inner = content->add( object_ptr(content)); @@ -108,7 +129,8 @@ void QuickReplies::setupContent( const auto &shortcuts = messages->shortcuts(); auto i = 0; - for (const auto &[_, shortcut] : shortcuts.list) { + for (const auto &[_, shortcut] + : shortcuts.list | ranges::views::reverse) { if (!shortcut.count) { continue; } @@ -132,18 +154,7 @@ void QuickReplies::setupContent( while (old--) { delete inner->widgetAt(0); } - if (!inner->count()) { - while (dividerWrap->count()) { - delete dividerWrap->widgetAt(0); - } - } else if (!dividerWrap->count()) { - AddSkip(dividerWrap); - AddDivider(dividerWrap); - AddSkip(dividerWrap); - } - if (const auto width = content->width()) { - content->resizeToWidth(width); - } + _count = inner->count(); }, content->lifetime()); Ui::ResizeFitChild(this, content); diff --git a/Telegram/SourceFiles/settings/business/settings_recipients_helper.cpp b/Telegram/SourceFiles/settings/business/settings_recipients_helper.cpp index 83c11a9cd..5787bb234 100644 --- a/Telegram/SourceFiles/settings/business/settings_recipients_helper.cpp +++ b/Telegram/SourceFiles/settings/business/settings_recipients_helper.cpp @@ -9,10 +9,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/filters/edit_filter_chats_list.h" #include "boxes/filters/edit_filter_chats_preview.h" +#include "data/business/data_shortcut_messages.h" #include "data/data_session.h" #include "data/data_user.h" #include "history/history.h" #include "lang/lang_keys.h" +#include "main/main_account.h" +#include "main/main_app_config.h" +#include "main/main_session.h" #include "settings/settings_common.h" #include "ui/widgets/checkbox.h" #include "ui/wrap/slide_wrap.h" @@ -291,4 +295,83 @@ void AddBusinessRecipientsSelector( }); } +int ShortcutsCount(not_null session) { + const auto &shortcuts = session->data().shortcutMessages().shortcuts(); + auto result = 0; + for (const auto &[_, shortcut] : shortcuts.list) { + if (shortcut.count > 0) { + ++result; + } + } + return result; +} + +rpl::producer ShortcutsCountValue(not_null session) { + const auto messages = &session->data().shortcutMessages(); + return rpl::single(rpl::empty) | rpl::then( + messages->shortcutsChanged() + ) | rpl::map([=] { + return ShortcutsCount(session); + }); +} + +int ShortcutMessagesCount( + not_null session, + const QString &name) { + const auto &shortcuts = session->data().shortcutMessages().shortcuts(); + for (const auto &[_, shortcut] : shortcuts.list) { + if (shortcut.name == name) { + return shortcut.count; + } + } + return 0; +} + +rpl::producer ShortcutMessagesCountValue( + not_null session, + const QString &name) { + const auto messages = &session->data().shortcutMessages(); + return rpl::single(rpl::empty) | rpl::then( + messages->shortcutsChanged() + ) | rpl::map([=] { + return ShortcutMessagesCount(session, name); + }); +} + +bool ShortcutExists(not_null session, const QString &name) { + return ShortcutMessagesCount(session, name) > 0; +} + +rpl::producer ShortcutExistsValue( + not_null session, + const QString &name) { + return ShortcutMessagesCountValue(session, name) + | rpl::map(rpl::mappers::_1 > 0); +} + +int ShortcutsLimit(not_null session) { + const auto appConfig = &session->account().appConfig(); + return appConfig->get("quick_replies_limit", 100); +} + +rpl::producer ShortcutsLimitValue(not_null session) { + const auto appConfig = &session->account().appConfig(); + return appConfig->value() | rpl::map([=] { + return ShortcutsLimit(session); + }); +} + +int ShortcutMessagesLimit(not_null session) { + const auto appConfig = &session->account().appConfig(); + return appConfig->get("quick_reply_messages_limit", 20); +} + +rpl::producer ShortcutMessagesLimitValue( + not_null session) { + const auto appConfig = &session->account().appConfig(); + return appConfig->value() | rpl::map([=] { + return ShortcutMessagesLimit(session); + }); +} + } // namespace Settings diff --git a/Telegram/SourceFiles/settings/business/settings_recipients_helper.h b/Telegram/SourceFiles/settings/business/settings_recipients_helper.h index 60efd7425..e05f702e6 100644 --- a/Telegram/SourceFiles/settings/business/settings_recipients_helper.h +++ b/Telegram/SourceFiles/settings/business/settings_recipients_helper.h @@ -71,4 +71,26 @@ void AddBusinessRecipientsSelector( not_null container, BusinessRecipientsSelectorDescriptor &&descriptor); +[[nodiscard]] int ShortcutsCount(not_null session); +[[nodiscard]] rpl::producer ShortcutsCountValue( + not_null session); +[[nodiscard]] int ShortcutMessagesCount( + not_null session, + const QString &name); +[[nodiscard]] rpl::producer ShortcutMessagesCountValue( + not_null session, + const QString &name); +[[nodiscard]] bool ShortcutExists( + not_null session, + const QString &name); +[[nodiscard]] rpl::producer ShortcutExistsValue( + not_null session, + const QString &name); +[[nodiscard]] int ShortcutsLimit(not_null session); +[[nodiscard]] rpl::producer ShortcutsLimitValue( + not_null session); +[[nodiscard]] int ShortcutMessagesLimit(not_null session); +[[nodiscard]] rpl::producer ShortcutMessagesLimitValue( + not_null session); + } // namespace Settings diff --git a/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp b/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp index b72acab4b..91ba0c63f 100644 --- a/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp +++ b/Telegram/SourceFiles/settings/business/settings_shortcut_messages.cpp @@ -35,6 +35,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "inline_bots/inline_bot_result.h" #include "lang/lang_keys.h" #include "lang/lang_numbers_animation.h" +#include "main/main_account.h" +#include "main/main_app_config.h" #include "main/main_session.h" #include "menu/menu_send.h" #include "settings/business/settings_quick_replies.h" @@ -259,6 +261,7 @@ private: rpl::variable _shortcutId; rpl::variable _shortcut; rpl::variable _container; + rpl::variable _count; std::shared_ptr _style; std::shared_ptr _theme; QPointer _inner; @@ -618,9 +621,22 @@ void ShortcutMessages::setupComposeControls() { }; _composeControls->setCurrentDialogsEntryState(state); + auto writeRestriction = rpl::combine( + _count.value(), + ShortcutMessagesLimitValue(_session) + ) | rpl::map([=](int count, int limit) { + return (count >= limit) + ? Controls::WriteRestriction{ + .text = tr::lng_business_limit_reached( + tr::now, + lt_count, + limit), + .type = Controls::WriteRestrictionType::Rights, + } : Controls::WriteRestriction(); + }); _composeControls->setHistory({ .history = _history.get(), - .writeRestriction = rpl::single(Controls::WriteRestriction()), + .writeRestriction = std::move(writeRestriction), }); _composeControls->cancelRequests( @@ -831,7 +847,11 @@ rpl::producer ShortcutMessages::listSource( ) | rpl::map([=] { return messages->list(shortcutId); }); - }) | rpl::flatten_latest(); + }) | rpl::flatten_latest( + ) | rpl::after_next([=](const Data::MessagesSlice &slice) { + _count = slice.fullCount.value_or( + messages->count(_shortcutId.current())); + }); } bool ShortcutMessages::listAllowsMultiSelect() { diff --git a/Telegram/SourceFiles/settings/settings_main.cpp b/Telegram/SourceFiles/settings/settings_main.cpp index 4dd57db8f..c746a881a 100644 --- a/Telegram/SourceFiles/settings/settings_main.cpp +++ b/Telegram/SourceFiles/settings/settings_main.cpp @@ -446,10 +446,6 @@ void SetupPremium( button->addClickHandler([=] { controller->showGiftPremiumsBox(u"gift"_q); }); - constexpr auto kNewExpiresAt = int(1735689600); - if (base::unixtime::now() < kNewExpiresAt) { - Ui::NewBadge::AddToRight(button); - } } Ui::AddSkip(container); } diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 333587d95..14794d222 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 333587d95edefcae1ebaf8838d3f499639fc2de8 +Subproject commit 14794d22210cb21b82db20aa55b1f3c8733b5fbd