From ba7422805b8ddeb331ce7701d44f43e78c371985 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 5 Jun 2022 01:17:58 +0300 Subject: [PATCH] Moved items highlighting to separate management module. --- Telegram/CMakeLists.txt | 2 + .../history/history_inner_widget.cpp | 9 +- .../history_view_highlight_manager.cpp | 118 ++++++++++++++++++ .../history/history_view_highlight_manager.h | 54 ++++++++ .../SourceFiles/history/history_widget.cpp | 100 ++------------- Telegram/SourceFiles/history/history_widget.h | 13 +- .../history/view/history_view_list_widget.cpp | 57 ++------- .../history/view/history_view_list_widget.h | 9 +- 8 files changed, 198 insertions(+), 164 deletions(-) create mode 100644 Telegram/SourceFiles/history/history_view_highlight_manager.cpp create mode 100644 Telegram/SourceFiles/history/history_view_highlight_manager.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index d258b99aac..9af4fb3f6b 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -728,6 +728,8 @@ PRIVATE history/history_service.h history/history_unread_things.cpp history/history_unread_things.h + history/history_view_highlight_manager.cpp + history/history_view_highlight_manager.h history/history_widget.cpp history/history_widget.h info/info_content_widget.cpp diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index dad1a37fb7..a10436dd93 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -3158,14 +3158,7 @@ void HistoryInner::elementStartStickerLoop( crl::time HistoryInner::elementHighlightTime( not_null item) { - const auto fullAnimMs = _widget->highlightStartTime(item); - if (fullAnimMs > 0) { - const auto now = crl::now(); - if (fullAnimMs < now) { - return now - fullAnimMs; - } - } - return 0; + return _widget->highlightStartTime(item); } void HistoryInner::elementShowPollResults( diff --git a/Telegram/SourceFiles/history/history_view_highlight_manager.cpp b/Telegram/SourceFiles/history/history_view_highlight_manager.cpp new file mode 100644 index 0000000000..40fd10ec6b --- /dev/null +++ b/Telegram/SourceFiles/history/history_view_highlight_manager.cpp @@ -0,0 +1,118 @@ +/* +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 "history/history_view_highlight_manager.h" + +#include "data/data_session.h" +#include "history/history_item.h" +#include "history/view/history_view_element.h" + +namespace HistoryView { + +ElementHighlighter::ElementHighlighter( + not_null data, + ViewForItem viewForItem, + RepaintView repaintView) +: _data(data) +, _viewForItem(std::move(viewForItem)) +, _repaintView(std::move(repaintView)) +, _timer([=] { updateMessage(); }) { +} + +void ElementHighlighter::enqueue(not_null view) { + const auto item = view->data(); + const auto fullId = item->fullId(); + if (_queue.empty() && !_timer.isActive()) { + highlight(fullId); + } else if (_highlightedMessageId != fullId + && !base::contains(_queue, fullId)) { + _queue.push_back(fullId); + checkNextHighlight(); + } +} + +void ElementHighlighter::checkNextHighlight() { + if (_timer.isActive()) { + return; + } + const auto nextHighlight = [&] { + while (!_queue.empty()) { + const auto fullId = _queue.front(); + _queue.pop_front(); + if (const auto item = _data->message(fullId)) { + if (_viewForItem(item)) { + return fullId; + } + } + } + return FullMsgId(); + }(); + if (!nextHighlight) { + return; + } + highlight(nextHighlight); +} + +crl::time ElementHighlighter::elementTime( + not_null item) const { + if (item->fullId() == _highlightedMessageId) { + if (_timer.isActive()) { + return crl::now() - _highlightStart; + } + } + return crl::time(0); +} + +void ElementHighlighter::highlight(FullMsgId itemId) { + if (const auto item = _data->message(itemId)) { + if (const auto view = _viewForItem(item)) { + _highlightStart = crl::now(); + _highlightedMessageId = itemId; + _timer.callEach(AnimationTimerDelta); + + repaintHighlightedItem(view); + } + } +} + +void ElementHighlighter::repaintHighlightedItem( + not_null view) { + if (view->isHiddenByGroup()) { + if (const auto group = _data->groups().find(view->data())) { + if (const auto leader = _viewForItem(group->items.front())) { + if (!leader->isHiddenByGroup()) { + _repaintView(leader); + return; + } + } + } + } + _repaintView(view); +} + +void ElementHighlighter::updateMessage() { + if (const auto item = _data->message(_highlightedMessageId)) { + if (const auto view = _viewForItem(item)) { + repaintHighlightedItem(view); + const auto duration = st::activeFadeInDuration + + st::activeFadeOutDuration; + if (crl::now() - _highlightStart <= duration) { + return; + } + } + } + _timer.cancel(); + _highlightedMessageId = FullMsgId(); + checkNextHighlight(); +} + +void ElementHighlighter::clear() { + _highlightedMessageId = FullMsgId(); + updateMessage(); +} + +} // namespace HistoryView diff --git a/Telegram/SourceFiles/history/history_view_highlight_manager.h b/Telegram/SourceFiles/history/history_view_highlight_manager.h new file mode 100644 index 0000000000..e28a0b9d4d --- /dev/null +++ b/Telegram/SourceFiles/history/history_view_highlight_manager.h @@ -0,0 +1,54 @@ +/* +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 + +#include "base/timer.h" + +class HistoryItem; + +namespace Data { +class Session; +} // namespace Data + +namespace HistoryView { + +class Element; + +class ElementHighlighter final { +public: + using ViewForItem = Fn; + using RepaintView = Fn; + ElementHighlighter( + not_null data, + ViewForItem viewForItem, + RepaintView repaintView); + + void enqueue(not_null view); + void highlight(FullMsgId itemId); + void clear(); + + [[nodiscard]] crl::time elementTime( + not_null item) const; + +private: + void checkNextHighlight(); + void repaintHighlightedItem(not_null view); + void updateMessage(); + + const not_null _data; + const ViewForItem _viewForItem; + const RepaintView _repaintView; + + FullMsgId _highlightedMessageId; + std::deque _queue; + base::Timer _timer; + crl::time _highlightStart = 0; + +}; + +} // namespace HistoryView diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 606a983751..9f5a1c9481 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -277,6 +277,12 @@ HistoryWidget::HistoryWidget( controller, this))) , _membersDropdownShowTimer([=] { showMembersDropdown(); }) +, _highlighter( + &session().data(), + [=](const HistoryItem *item) { return item->mainView(); }, + [=](const HistoryView::Element *view) { + session().data().requestViewRepaint(view); + }) , _saveDraftTimer([=] { saveDraft(); }) , _saveCloudDraftTimer([=] { saveCloudDraft(); }) , _topShadow(this) { @@ -357,8 +363,6 @@ HistoryWidget::HistoryWidget( this, [=] { chooseAttach(); })); - _highlightTimer.setCallback([this] { updateHighlightedMessage(); }); - const auto rawTextEdit = _field->rawTextEdit().get(); rpl::merge( _field->scrollTop().changes() | rpl::to_empty, @@ -1259,92 +1263,12 @@ void HistoryWidget::scrollToAnimationCallback( void HistoryWidget::enqueueMessageHighlight( not_null view) { - auto enqueueMessageId = [this](MsgId universalId) { - if (_highlightQueue.empty() && !_highlightTimer.isActive()) { - highlightMessage(universalId); - } else if (_highlightedMessageId != universalId - && !base::contains(_highlightQueue, universalId)) { - _highlightQueue.push_back(universalId); - checkNextHighlight(); - } - }; - const auto item = view->data(); - if (item->history() == _history) { - enqueueMessageId(item->id); - } else if (item->history() == _migrated) { - enqueueMessageId(-item->id); - } + _highlighter.enqueue(view); } -void HistoryWidget::highlightMessage(MsgId universalMessageId) { - _highlightStart = crl::now(); - _highlightedMessageId = universalMessageId; - _highlightTimer.callEach(AnimationTimerDelta); -} - -void HistoryWidget::checkNextHighlight() { - if (_highlightTimer.isActive()) { - return; - } - auto nextHighlight = [this] { - while (!_highlightQueue.empty()) { - auto msgId = _highlightQueue.front(); - _highlightQueue.pop_front(); - auto item = getItemFromHistoryOrMigrated(msgId); - if (item && item->mainView()) { - return msgId; - } - } - return MsgId(); - }(); - if (!nextHighlight) { - return; - } - highlightMessage(nextHighlight); -} - -void HistoryWidget::updateHighlightedMessage() { - const auto item = getItemFromHistoryOrMigrated(_highlightedMessageId); - auto view = item ? item->mainView() : nullptr; - if (!view) { - return stopMessageHighlight(); - } - auto duration = st::activeFadeInDuration + st::activeFadeOutDuration; - if (crl::now() - _highlightStart > duration) { - return stopMessageHighlight(); - } - - if (const auto group = session().data().groups().find(view->data())) { - if (const auto leader = group->items.front()->mainView()) { - view = leader; - } - } - session().data().requestViewRepaint(view); -} - -crl::time HistoryWidget::highlightStartTime(not_null item) const { - auto isHighlighted = [this](not_null item) { - if (item->id == _highlightedMessageId) { - return (item->history() == _history); - } else if (item->id == -_highlightedMessageId) { - return (item->history() == _migrated); - } - return false; - }; - return (isHighlighted(item) && _highlightTimer.isActive()) - ? _highlightStart - : 0; -} - -void HistoryWidget::stopMessageHighlight() { - _highlightTimer.cancel(); - _highlightedMessageId = 0; - checkNextHighlight(); -} - -void HistoryWidget::clearHighlightMessages() { - _highlightQueue.clear(); - stopMessageHighlight(); +crl::time HistoryWidget::highlightStartTime( + not_null item) const { + return _highlighter.elementTime(item); } int HistoryWidget::itemTopForHighlight( @@ -2048,7 +1972,7 @@ void HistoryWidget::showHistory( showAtMsgId = ShowAtTheEndMsgId; } - clearHighlightMessages(); + _highlighter.clear(); controller()->sendingAnimation().clear(); hideInfoTooltip(anim::type::instant); if (_history) { @@ -6233,7 +6157,7 @@ bool HistoryWidget::replyToNextMessage() { controller()->showPeerHistoryAtItem(next); replyToMessage(next); } else { - clearHighlightMessages(); + _highlighter.clear(); cancelReply(false); } return true; diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 60dd6b3c95..3f8b7c006e 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "history/history_drag_area.h" +#include "history/history_view_highlight_manager.h" #include "history/history.h" #include "ui/widgets/tooltip.h" #include "mainwidget.h" @@ -115,7 +116,6 @@ class TTLButton; } // namespace Controls } // namespace HistoryView -class DragArea; class SendFilesBox; class BotKeyboard; class MessageField; @@ -420,12 +420,6 @@ private: void supportInsertText(const QString &text); void supportShareContact(Support::Contact contact); - void highlightMessage(MsgId universalMessageId); - void checkNextHighlight(); - void updateHighlightedMessage(); - void clearHighlightMessages(); - void stopMessageHighlight(); - auto computeSendButtonType() const; void animationCallback(); @@ -792,10 +786,7 @@ private: Window::SlideDirection _showDirection; QPixmap _cacheUnder, _cacheOver; - MsgId _highlightedMessageId = 0; - std::deque _highlightQueue; - base::Timer _highlightTimer; - crl::time _highlightStart = 0; + HistoryView::ElementHighlighter _highlighter; crl::time _saveDraftStart = 0; bool _saveDraftText = false; diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index 3b1be978b5..1a1632839d 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -283,7 +283,10 @@ ListWidget::ListWidget( , _scrollDateCheck([this] { scrollDateCheck(); }) , _applyUpdatedScrollState([this] { applyUpdatedScrollState(); }) , _selectEnabled(_delegate->listAllowsMultiSelect()) -, _highlightTimer([this] { updateHighlightedMessage(); }) { +, _highlighter( + &session().data(), + [=](const HistoryItem *item) { return viewForItem(item); }, + [=](const Element *view) { repaintItem(view); }) { setMouseTracking(true); _scrollDateHideTimer.setCallback([this] { scrollDateHideByTimer(); }); session().data().viewRepaintRequest( @@ -578,15 +581,7 @@ bool ListWidget::isBelowPosition(Data::MessagePosition position) const { } void ListWidget::highlightMessage(FullMsgId itemId) { - if (const auto item = session().data().message(itemId)) { - if (const auto view = viewForItem(item)) { - _highlightStart = crl::now(); - _highlightedMessageId = itemId; - _highlightTimer.callEach(AnimationTimerDelta); - - repaintHighlightedItem(view); - } - } + _highlighter.highlight(itemId); } void ListWidget::showAroundPosition( @@ -598,39 +593,6 @@ void ListWidget::showAroundPosition( refreshViewer(); } -void ListWidget::repaintHighlightedItem(not_null view) { - if (view->isHiddenByGroup()) { - if (const auto group = session().data().groups().find(view->data())) { - if (const auto leader = viewForItem(group->items.front())) { - if (!leader->isHiddenByGroup()) { - repaintItem(leader); - return; - } - } - } - } - repaintItem(view); -} - -void ListWidget::updateHighlightedMessage() { - if (const auto item = session().data().message(_highlightedMessageId)) { - if (const auto view = viewForItem(item)) { - repaintHighlightedItem(view); - auto duration = st::activeFadeInDuration + st::activeFadeOutDuration; - if (crl::now() - _highlightStart <= duration) { - return; - } - } - } - _highlightTimer.cancel(); - _highlightedMessageId = FullMsgId(); -} - -void ListWidget::clearHighlightedMessage() { - _highlightedMessageId = FullMsgId(); - updateHighlightedMessage(); -} - void ListWidget::checkUnreadBarCreation() { if (!_bar.element) { if (auto data = _delegate->listMessagesBar(_items); data.bar.element) { @@ -1437,12 +1399,7 @@ bool ListWidget::elementUnderCursor( crl::time ListWidget::elementHighlightTime( not_null item) { - if (item->fullId() == _highlightedMessageId) { - if (_highlightTimer.isActive()) { - return crl::now() - _highlightStart; - } - } - return crl::time(0); + return _highlighter.elementTime(item); } bool ListWidget::elementInSelectionMode() { @@ -3266,7 +3223,7 @@ void ListWidget::replyNextMessage(FullMsgId fullId, bool next) { _requestedToShowMessage.fire_copy(newFullId); } else { replyToMessageRequestNotify(FullMsgId()); - clearHighlightedMessage(); + _highlighter.clear(); } }; const auto replyFirst = [&] { diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.h b/Telegram/SourceFiles/history/view/history_view_list_widget.h index 5fac0b4857..53fa0b7871 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.h +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.h @@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mtproto/sender.h" #include "data/data_messages.h" #include "history/view/history_view_element.h" +#include "history/history_view_highlight_manager.h" namespace Main { class Session; @@ -405,7 +406,6 @@ private: int itemTop(not_null view) const; void repaintItem(FullMsgId itemId); void repaintItem(const Element *view); - void repaintHighlightedItem(not_null view); void resizeItem(not_null view); void refreshItem(not_null view); void itemRemoved(not_null item); @@ -516,9 +516,6 @@ private: void startMessageSendingAnimation(not_null item); - void updateHighlightedMessage(); - void clearHighlightedMessage(); - // This function finds all history items that are displayed and calls template method // for each found message (in given direction) in the passed history with passed top offset. // @@ -638,9 +635,7 @@ private: QPoint _trippleClickPoint; crl::time _trippleClickStartTime = 0; - crl::time _highlightStart = 0; - FullMsgId _highlightedMessageId; - base::Timer _highlightTimer; + ElementHighlighter _highlighter; Ui::Animations::Simple _spoilerOpacity;