diff --git a/Telegram/SourceFiles/chat_helpers/field_characters_count_manager.cpp b/Telegram/SourceFiles/chat_helpers/field_characters_count_manager.cpp new file mode 100644 index 0000000000..87d1f61abd --- /dev/null +++ b/Telegram/SourceFiles/chat_helpers/field_characters_count_manager.cpp @@ -0,0 +1,36 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "chat_helpers/field_characters_count_manager.h" + +FieldCharsCountManager::FieldCharsCountManager() = default; + +void FieldCharsCountManager::setCount(int count) { + _previous = _current; + _current = count; + if (_previous != _current) { + constexpr auto kMax = 15; + const auto was = (_previous > kMax); + const auto now = (_current > kMax); + if (was != now) { + _isLimitExceeded = now; + _limitExceeds.fire({}); + } + } +} + +int FieldCharsCountManager::count() const { + return _current; +} + +bool FieldCharsCountManager::isLimitExceeded() const { + return _isLimitExceeded; +} + +rpl::producer<> FieldCharsCountManager::limitExceeds() const { + return _limitExceeds.events(); +} diff --git a/Telegram/SourceFiles/chat_helpers/field_characters_count_manager.h b/Telegram/SourceFiles/chat_helpers/field_characters_count_manager.h new file mode 100644 index 0000000000..eba367818e --- /dev/null +++ b/Telegram/SourceFiles/chat_helpers/field_characters_count_manager.h @@ -0,0 +1,26 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +class FieldCharsCountManager final { +public: + FieldCharsCountManager(); + + void setCount(int count); + [[nodiscard]] int count() const; + [[nodiscard]] bool isLimitExceeded() const; + [[nodiscard]] rpl::producer<> limitExceeds() const; + +private: + int _current = 0; + int _previous = 0; + bool _isLimitExceeded = false; + + rpl::event_stream<> _limitExceeds; + +}; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 1bc4ac21fa..5ce512bf6c 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -423,6 +423,22 @@ HistoryWidget::HistoryWidget( }); InitMessageFieldFade(_field, st::historyComposeField.textBg); + _fieldCharsCountManager.limitExceeds( + ) | rpl::start_with_next([=] { + const auto hide = _fieldCharsCountManager.isLimitExceeded(); + if (_silent) { + _silent->setVisible(!hide); + } + if (_ttlInfo) { + _ttlInfo->setVisible(!hide); + } + if (_scheduled) { + _scheduled->setVisible(!hide); + } + updateFieldSize(); + moveFieldControls(); + }, lifetime()); + _keyboard->sendCommandRequests( ) | rpl::start_with_next([=](Bot::SendCommandRequest r) { sendBotCommand(r); @@ -1673,7 +1689,7 @@ void HistoryWidget::fieldChanged() { } }); - checkCharsLimitation(); + checkCharsCount(); updateSendButtonType(); if (!HasSendText(_field)) { @@ -1998,7 +2014,6 @@ bool HistoryWidget::applyDraft(FieldHistoryAction fieldHistoryAction) { updateControlsVisibility(); updateControlsGeometry(); refreshTopBarActiveChat(); - checkCharsLimitation(); if (_editMsgId) { updateReplyEditTexts(); if (!_replyEditMsg) { @@ -2388,6 +2403,7 @@ void HistoryWidget::showHistory( if (!applyDraft()) { clearFieldText(); } + checkCharsCount(); _send->finishAnimating(); updateControlsGeometry(); @@ -2813,6 +2829,7 @@ bool HistoryWidget::canWriteMessage() const { void HistoryWidget::updateControlsVisibility() { auto fieldDisabledRemoved = (_fieldDisabled != nullptr); + const auto hideExtraButtons = _fieldCharsCountManager.isLimitExceeded(); const auto guard = gsl::finally([&] { if (fieldDisabledRemoved) { _fieldDisabled = nullptr; @@ -2999,7 +3016,7 @@ void HistoryWidget::updateControlsVisibility() { auto rightButtonsChanged = false; if (_silent) { const auto was = _silent->isVisible(); - const auto now = (!_editMsgId); + const auto now = (!_editMsgId) && (!hideExtraButtons); if (was != now) { _silent->setVisible(now); rightButtonsChanged = true; @@ -3007,7 +3024,7 @@ void HistoryWidget::updateControlsVisibility() { } if (_scheduled) { const auto was = _scheduled->isVisible(); - const auto now = (!_editMsgId); + const auto now = (!_editMsgId) && (!hideExtraButtons); if (was != now) { _scheduled->setVisible(now); rightButtonsChanged = true; @@ -3015,7 +3032,7 @@ void HistoryWidget::updateControlsVisibility() { } if (_ttlInfo) { const auto was = _ttlInfo->isVisible(); - const auto now = (!_editMsgId); + const auto now = (!_editMsgId) && (!hideExtraButtons); if (was != now) { _ttlInfo->setVisible(now); rightButtonsChanged = true; @@ -3936,7 +3953,7 @@ void HistoryWidget::saveEditMsg() { const auto maxCaptionSize = !hasMediaWithCaption ? MaxMessageSize : Data::PremiumLimits(&session()).captionLengthCurrent(); - const auto remove = Ui::FieldCharacterCount(_field) - maxCaptionSize; + const auto remove = _fieldCharsCountManager.count() - maxCaptionSize; if (remove > 0) { controller()->showToast( tr::lng_edit_limit_reached(tr::now, lt_count, remove)); @@ -4826,7 +4843,7 @@ bool HistoryWidget::updateCmdStartShown() { } else if (!_botMenu.button) { buttonChanged = true; _botMenu.text = bot->botInfo->botMenuButtonText; - _botMenu.small = (Ui::FieldCharacterCount(_field) > kSmallMenuAfter); + _botMenu.small = (_fieldCharsCountManager.count() > kSmallMenuAfter); if (_botMenu.small) { if (const auto e = FirstEmoji(_botMenu.text); !e.isEmpty()) { _botMenu.text = e; @@ -4863,7 +4880,7 @@ bool HistoryWidget::updateCmdStartShown() { } }, _botMenu.button->lifetime()); } - const auto textSmall = Ui::FieldCharacterCount(_field) > kSmallMenuAfter; + const auto textSmall = _fieldCharsCountManager.count() > kSmallMenuAfter; const auto textChanged = _botMenu.button && ((_botMenu.text != bot->botInfo->botMenuButtonText) || (_botMenu.small != textSmall)); @@ -7378,6 +7395,11 @@ void HistoryWidget::showPremiumToast(not_null document) { _stickerToast->showFor(document); } +void HistoryWidget::checkCharsCount() { + _fieldCharsCountManager.setCount(Ui::FieldCharacterCount(_field)); + checkCharsLimitation(); +} + void HistoryWidget::checkCharsLimitation() { if (!_history || !_editMsgId) { _charsLimitation = nullptr; @@ -7393,7 +7415,7 @@ void HistoryWidget::checkCharsLimitation() { const auto maxCaptionSize = !hasMediaWithCaption ? MaxMessageSize : Data::PremiumLimits(&session()).captionLengthCurrent(); - const auto remove = Ui::FieldCharacterCount(_field) - maxCaptionSize; + const auto remove = _fieldCharsCountManager.count() - maxCaptionSize; if (remove > 0) { if (!_charsLimitation) { _charsLimitation = base::make_unique_q( @@ -7425,7 +7447,7 @@ void HistoryWidget::setFieldText( _textUpdateEvents = TextUpdateEvent::SaveDraft | TextUpdateEvent::SendTyping; - checkCharsLimitation(); + checkCharsCount(); if (_preview) { _preview->checkNow(false); diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index eafa19ac9d..a61e74fff1 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_view_top_toast.h" #include "history/history.h" #include "chat_helpers/field_autocomplete.h" +#include "chat_helpers/field_characters_count_manager.h" #include "window/section_widget.h" #include "ui/widgets/fields/input_field.h" #include "mtproto/sender.h" @@ -646,6 +647,7 @@ private: void switchToSearch(QString query); + void checkCharsCount(); void checkCharsLimitation(); MTP::Sender _api; @@ -785,6 +787,8 @@ private: object_ptr _kbScroll; const not_null _keyboard; + FieldCharsCountManager _fieldCharsCountManager; + std::unique_ptr _chooseTheme; object_ptr _membersDropdown = { nullptr }; diff --git a/Telegram/cmake/td_ui.cmake b/Telegram/cmake/td_ui.cmake index eb1c7d79c6..0e98ad7b80 100644 --- a/Telegram/cmake/td_ui.cmake +++ b/Telegram/cmake/td_ui.cmake @@ -63,6 +63,8 @@ PRIVATE calls/group/ui/desktop_capture_choose_source.cpp calls/group/ui/desktop_capture_choose_source.h + chat_helpers/field_characters_count_manager.cpp + chat_helpers/field_characters_count_manager.h chat_helpers/stickers_emoji_image_loader.cpp chat_helpers/stickers_emoji_image_loader.h