From 08873486115d8103386022ed27a4fa9e58979546 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 20 Mar 2024 13:17:05 +0400 Subject: [PATCH] Show length limit in chat intro fields. --- .../view/history_view_context_menu.cpp | 66 +++++++------ .../history/view/history_view_context_menu.h | 2 + .../settings/business/settings_chat_intro.cpp | 98 +++++++++++++------ .../business/settings_quick_replies.cpp | 33 +------ Telegram/SourceFiles/settings/settings.style | 3 +- 5 files changed, 113 insertions(+), 89 deletions(-) diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index 5a7852b82..22d3292a3 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -1019,14 +1019,8 @@ void EditTagBox( struct State { std::unique_ptr custom; QImage image; - rpl::variable length; }; const auto state = field->lifetime().make_state(); - state->length = rpl::single( - int(title.size()) - ) | rpl::then(field->changes() | rpl::map([=] { - return int(field->getLastText().size()); - })); if (const auto customId = id.custom()) { state->custom = owner->customEmojiManager().create( @@ -1059,28 +1053,8 @@ void EditTagBox( } } }, field->lifetime()); - const auto warning = Ui::CreateChild( - field, - state->length.value() | rpl::map([](int count) { - return (count > kTagNameLimit / 2) - ? QString::number(kTagNameLimit - count) - : QString(); - }), - st::editTagLimit); - state->length.value() | rpl::map( - rpl::mappers::_1 > kTagNameLimit - ) | rpl::start_with_next([=](bool exceeded) { - warning->setTextColorOverride(exceeded - ? st::attentionButtonFg->c - : std::optional()); - }, warning->lifetime()); - rpl::combine( - field->sizeValue(), - warning->sizeValue() - ) | rpl::start_with_next([=] { - warning->moveToRight(0, st::editTagField.textMargins.top()); - }, warning->lifetime()); - warning->setAttribute(Qt::WA_TransparentForMouseEvents); + + AddLengthLimitLabel(field, kTagNameLimit); const auto save = [=] { const auto text = field->getLastText(); @@ -1840,4 +1814,40 @@ bool ItemHasTtl(HistoryItem *item) { : false; } +void AddLengthLimitLabel(not_null field, int limit) { + struct State { + rpl::variable length; + }; + const auto state = field->lifetime().make_state(); + state->length = rpl::single( + rpl::empty + ) | rpl::then(field->changes()) | rpl::map([=] { + return int(field->getLastText().size()); + }); + auto warningText = state->length.value() | rpl::map([=](int count) { + const auto threshold = std::min(limit / 2, 9); + const auto left = limit - count; + return (left < threshold) ? QString::number(left) : QString(); + }); + const auto warning = Ui::CreateChild( + field.get(), + std::move(warningText), + st::editTagLimit); + state->length.value() | rpl::map( + rpl::mappers::_1 > limit + ) | rpl::start_with_next([=](bool exceeded) { + warning->setTextColorOverride(exceeded + ? st::attentionButtonFg->c + : std::optional()); + }, warning->lifetime()); + rpl::combine( + field->sizeValue(), + warning->sizeValue() + ) | rpl::start_with_next([=] { + warning->moveToRight(0, 0); + }, warning->lifetime()); + warning->setAttribute(Qt::WA_TransparentForMouseEvents); + +} + } // namespace HistoryView diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.h b/Telegram/SourceFiles/history/view/history_view_context_menu.h index 8f00f4da8..8582a57fb 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.h +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.h @@ -123,4 +123,6 @@ void AddEmojiPacksAction( [[nodiscard]] bool ItemHasTtl(HistoryItem *item); +void AddLengthLimitLabel(not_null field, int limit); + } // namespace HistoryView diff --git a/Telegram/SourceFiles/settings/business/settings_chat_intro.cpp b/Telegram/SourceFiles/settings/business/settings_chat_intro.cpp index 28a223039..6ce2ddfad 100644 --- a/Telegram/SourceFiles/settings/business/settings_chat_intro.cpp +++ b/Telegram/SourceFiles/settings/business/settings_chat_intro.cpp @@ -16,9 +16,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_document.h" #include "data/data_session.h" #include "history/view/history_view_about_view.h" +#include "history/view/history_view_context_menu.h" #include "history/view/history_view_element.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/business/settings_recipients_helper.h" #include "ui/chat/chat_style.h" @@ -141,6 +144,30 @@ private: }; +[[nodiscard]] int PartLimit( + not_null session, + const QString &key, + int defaultValue) { + return session->account().appConfig().get(key, defaultValue); +} + +[[nodiscard]] not_null AddPartInput( + not_null container, + rpl::producer placeholder, + QString current, + int limit) { + const auto field = container->add( + object_ptr( + container, + st::settingsChatIntroField, + tr::lng_chat_intro_enter_title(), + current), + st::settingsChatIntroFieldMargins); + field->setMaxLength(limit); + HistoryView::AddLengthLimitLabel(field, limit); + return field; +} + [[nodiscard]] object_ptr CreateIntroStickerButton( not_null parent, std::shared_ptr show, @@ -266,6 +293,10 @@ PreviewWrap::PreviewWrap( } }, lifetime()); + session->downloaderTaskFinished() | rpl::start_with_next([=] { + update(); + }, lifetime()); + prepare(std::move(value)); } @@ -438,19 +469,28 @@ rpl::producer ChatIntro::title() { [[nodiscard]] rpl::producer IntroWithRandomSticker( not_null session, rpl::producer intro) { - return std::move(intro) | rpl::map([=](Data::ChatIntro intro) - -> rpl::producer { - if (intro.sticker) { - return rpl::single(std::move(intro)); + auto random = rpl::single( + Api::RandomHelloStickerValue(session) + ) | rpl::then(rpl::duplicate( + intro + ) | rpl::map([=](const Data::ChatIntro &intro) { + return intro.sticker; + }) | rpl::distinct_until_changed( + ) | rpl::filter([](DocumentData *sticker) { + return !sticker; + }) | rpl::map([=] { + return Api::RandomHelloStickerValue(session); + })) | rpl::flatten_latest(); + + return rpl::combine( + std::move(intro), + std::move(random) + ) | rpl::map([=](Data::ChatIntro intro, DocumentData *hello) { + if (!intro.sticker) { + intro.sticker = hello; } - return Api::RandomHelloStickerValue( - session - ) | rpl::map([=](DocumentData *sticker) { - auto copy = intro; - copy.sticker = sticker; - return copy; - }); - }) | rpl::flatten_latest(); + return intro; + }); } void ChatIntro::setupContent( @@ -458,7 +498,8 @@ void ChatIntro::setupContent( using namespace rpl::mappers; const auto content = Ui::CreateChild(this); - const auto info = &controller->session().data().businessInfo(); + const auto session = &controller->session(); + const auto info = &session->data().businessInfo(); const auto current = info->chatIntro(); _intro = info->chatIntro(); @@ -471,24 +512,20 @@ void ChatIntro::setupContent( const auto preview = content->add( object_ptr( content, - &controller->session(), - IntroWithRandomSticker(&controller->session(), _intro.value())), + session, + IntroWithRandomSticker(session, _intro.value())), {}); - const auto title = content->add( - object_ptr( - content, - st::settingsChatIntroField, - tr::lng_chat_intro_enter_title(), - current.title), - st::settingsChatIntroFieldMargins); - const auto description = content->add( - object_ptr( - content, - st::settingsChatIntroField, - tr::lng_chat_intro_enter_message(), - current.description), - st::settingsChatIntroFieldMargins); + const auto title = AddPartInput( + content, + tr::lng_chat_intro_enter_title(), + current.title, + PartLimit(session, u"intro_title_length_limit"_q, 32)); + const auto description = AddPartInput( + content, + tr::lng_chat_intro_enter_message(), + current.description, + PartLimit(session, u"intro_description_length_limit"_q, 70)); content->add(CreateIntroStickerButton( content, controller->uiShow(), @@ -538,6 +575,9 @@ void ChatIntro::setupContent( })); resetWrap->entity()->setClickedCallback([=] { _intro = Data::ChatIntro(); + title->clear(); + description->clear(); + title->setFocus(); }); Ui::ResizeFitChild(this, content); diff --git a/Telegram/SourceFiles/settings/business/settings_quick_replies.cpp b/Telegram/SourceFiles/settings/business/settings_quick_replies.cpp index d46d05615..b8c990d03 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 "core/application.h" #include "data/business/data_shortcut_messages.h" #include "data/data_session.h" +#include "history/view/history_view_context_menu.h" // AddLengthLimitLabel. #include "lang/lang_keys.h" #include "main/main_account.h" #include "main/main_session.h" @@ -211,37 +212,7 @@ void EditShortcutNameBox( field->selectAll(); field->setMaxLength(kShortcutLimit * 2); - struct State { - rpl::variable length; - }; - const auto state = field->lifetime().make_state(); - state->length = rpl::single( - int(name.size()) - ) | rpl::then(field->changes() | rpl::map([=] { - return int(field->getLastText().size()); - })); - const auto warning = Ui::CreateChild( - field, - state->length.value() | rpl::map([](int count) { - return (count > kShortcutLimit * 3 / 4) - ? QString::number(kShortcutLimit - count) - : QString(); - }), - st::editTagLimit); - state->length.value() | rpl::map( - rpl::mappers::_1 > kShortcutLimit - ) | rpl::start_with_next([=](bool exceeded) { - warning->setTextColorOverride(exceeded - ? st::attentionButtonFg->c - : std::optional()); - }, warning->lifetime()); - rpl::combine( - field->sizeValue(), - warning->sizeValue() - ) | rpl::start_with_next([=] { - warning->moveToRight(0, 0); - }, warning->lifetime()); - warning->setAttribute(Qt::WA_TransparentForMouseEvents); + HistoryView::AddLengthLimitLabel(field, kShortcutLimit); const auto callback = [=] { const auto name = field->getLastText().trimmed(); diff --git a/Telegram/SourceFiles/settings/settings.style b/Telegram/SourceFiles/settings/settings.style index 2060cdd93..2545afbf9 100644 --- a/Telegram/SourceFiles/settings/settings.style +++ b/Telegram/SourceFiles/settings/settings.style @@ -641,5 +641,6 @@ settingsChatbotsDeleteIcon: icon {{ "dialogs/dialogs_cancel_search", dialogsMenu settingsChatbotsDeleteIconOver: icon {{ "dialogs/dialogs_cancel_search", dialogsMenuIconFgOver }}; settingsChatIntroField: InputField(defaultMultiSelectSearchField) { + textMargins: margins(2px, 0px, 32px, 0px); } -settingsChatIntroFieldMargins: margins(20px, 8px, 20px, 8px); +settingsChatIntroFieldMargins: margins(20px, 15px, 20px, 8px);