mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-26 11:13:18 +02:00
176 lines
4.1 KiB
C++
176 lines
4.1 KiB
C++
/*
|
|
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 {
|
|
|
|
constexpr auto kAnimationFirstPart = st::activeFadeInDuration
|
|
/ float64(st::activeFadeInDuration + st::activeFadeOutDuration);
|
|
|
|
ElementHighlighter::ElementHighlighter(
|
|
not_null<Data::Session*> data,
|
|
ViewForItem viewForItem,
|
|
RepaintView repaintView)
|
|
: _data(data)
|
|
, _viewForItem(std::move(viewForItem))
|
|
, _repaintView(std::move(repaintView))
|
|
, _animation(*this) {
|
|
}
|
|
|
|
void ElementHighlighter::enqueue(not_null<Element*> view) {
|
|
const auto item = view->data();
|
|
const auto fullId = item->fullId();
|
|
if (_queue.empty() && !_animation.animating()) {
|
|
highlight(fullId);
|
|
} else if (_highlightedMessageId != fullId
|
|
&& !base::contains(_queue, fullId)) {
|
|
_queue.push_back(fullId);
|
|
checkNextHighlight();
|
|
}
|
|
}
|
|
|
|
void ElementHighlighter::checkNextHighlight() {
|
|
if (_animation.animating()) {
|
|
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);
|
|
}
|
|
|
|
float64 ElementHighlighter::progress(
|
|
not_null<const HistoryItem*> item) const {
|
|
if (item->fullId() == _highlightedMessageId) {
|
|
const auto progress = _animation.progress();
|
|
return std::min(progress / kAnimationFirstPart, 1.)
|
|
- ((progress - kAnimationFirstPart) / (1. - kAnimationFirstPart));
|
|
}
|
|
return 0.;
|
|
}
|
|
|
|
void ElementHighlighter::highlight(FullMsgId itemId) {
|
|
if (const auto item = _data->message(itemId)) {
|
|
if (const auto view = _viewForItem(item)) {
|
|
if (_highlightedMessageId
|
|
&& _highlightedMessageId != itemId) {
|
|
if (const auto was = _data->message(_highlightedMessageId)) {
|
|
if (const auto view = _viewForItem(was)) {
|
|
repaintHighlightedItem(view);
|
|
}
|
|
}
|
|
}
|
|
_highlightedMessageId = itemId;
|
|
_animation.start();
|
|
|
|
repaintHighlightedItem(view);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ElementHighlighter::repaintHighlightedItem(
|
|
not_null<const Element*> 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);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ElementHighlighter::clear() {
|
|
_animation.cancel();
|
|
_highlightedMessageId = FullMsgId();
|
|
_queue.clear();
|
|
}
|
|
|
|
ElementHighlighter::AnimationManager::AnimationManager(
|
|
ElementHighlighter &parent)
|
|
: _parent(parent) {
|
|
}
|
|
|
|
bool ElementHighlighter::AnimationManager::animating() const {
|
|
if (anim::Disabled()) {
|
|
return (_timer && _timer->isActive());
|
|
} else {
|
|
return _simple.animating();
|
|
}
|
|
}
|
|
|
|
float64 ElementHighlighter::AnimationManager::progress() const {
|
|
if (anim::Disabled()) {
|
|
return (_timer && _timer->isActive()) ? kAnimationFirstPart : 0.;
|
|
} else {
|
|
return _simple.value(0.);
|
|
}
|
|
}
|
|
|
|
void ElementHighlighter::AnimationManager::start() {
|
|
const auto finish = [=] {
|
|
cancel();
|
|
_parent._highlightedMessageId = FullMsgId();
|
|
_parent.checkNextHighlight();
|
|
};
|
|
cancel();
|
|
if (anim::Disabled()) {
|
|
_timer.emplace([=] {
|
|
_parent.updateMessage();
|
|
finish();
|
|
});
|
|
_timer->callOnce(st::activeFadeOutDuration);
|
|
_parent.updateMessage();
|
|
} else {
|
|
const auto to = 1.;
|
|
_simple.start(
|
|
[=](float64 value) {
|
|
_parent.updateMessage();
|
|
if (value == to) {
|
|
finish();
|
|
}
|
|
},
|
|
0.,
|
|
to,
|
|
st::activeFadeInDuration + st::activeFadeOutDuration);
|
|
}
|
|
}
|
|
|
|
void ElementHighlighter::AnimationManager::cancel() {
|
|
_simple.stop();
|
|
_timer.reset();
|
|
}
|
|
|
|
} // namespace HistoryView
|