mirror of https://github.com/procxx/kepka.git
Highlight found messages in feed.
This commit is contained in:
parent
07528be1e6
commit
351a423337
|
@ -508,6 +508,10 @@ void InnerWidget::elementAnimationAutoplayAsync(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimeMs InnerWidget::elementHighlightTime(
|
||||||
|
not_null<const HistoryView::Element*> element) {
|
||||||
|
return TimeMs(0);
|
||||||
|
}
|
||||||
|
|
||||||
void InnerWidget::saveState(not_null<SectionMemento*> memento) {
|
void InnerWidget::saveState(not_null<SectionMemento*> memento) {
|
||||||
memento->setFilter(std::move(_filter));
|
memento->setFilter(std::move(_filter));
|
||||||
|
|
|
@ -85,6 +85,8 @@ public:
|
||||||
not_null<const HistoryView::Element*> view) override;
|
not_null<const HistoryView::Element*> view) override;
|
||||||
void elementAnimationAutoplayAsync(
|
void elementAnimationAutoplayAsync(
|
||||||
not_null<const HistoryView::Element*> view) override;
|
not_null<const HistoryView::Element*> view) override;
|
||||||
|
TimeMs elementHighlightTime(
|
||||||
|
not_null<const HistoryView::Element*> element) override;
|
||||||
|
|
||||||
~InnerWidget();
|
~InnerWidget();
|
||||||
|
|
||||||
|
|
|
@ -159,7 +159,11 @@ void Widget::scrollDownClicked() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::showAtPosition(Data::MessagePosition position) {
|
void Widget::showAtPosition(Data::MessagePosition position) {
|
||||||
if (!showAtPositionNow(position)) {
|
if (showAtPositionNow(position)) {
|
||||||
|
if (const auto highlight = base::take(_highlightMessageId)) {
|
||||||
|
_inner->highlightMessage(highlight);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
_nextAnimatedScrollPosition = position;
|
_nextAnimatedScrollPosition = position;
|
||||||
_nextAnimatedScrollDelta = _inner->isBelowPosition(position)
|
_nextAnimatedScrollDelta = _inner->isBelowPosition(position)
|
||||||
? -_scroll->height()
|
? -_scroll->height()
|
||||||
|
@ -424,6 +428,9 @@ void Widget::listContentRefreshed() {
|
||||||
position,
|
position,
|
||||||
_nextAnimatedScrollDelta,
|
_nextAnimatedScrollDelta,
|
||||||
HistoryView::ListWidget::AnimatedScroll::Part);
|
HistoryView::ListWidget::AnimatedScroll::Part);
|
||||||
|
if (const auto highlight = base::take(_highlightMessageId)) {
|
||||||
|
_inner->highlightMessage(highlight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -447,7 +454,7 @@ void Widget::restoreState(not_null<Memento*> memento) {
|
||||||
_undefinedAroundPosition = !list->aroundPosition();
|
_undefinedAroundPosition = !list->aroundPosition();
|
||||||
_inner->restoreState(memento->list());
|
_inner->restoreState(memento->list());
|
||||||
if (const auto position = memento->position()) {
|
if (const auto position = memento->position()) {
|
||||||
_currentMessageId = position.fullId;
|
_currentMessageId = _highlightMessageId = position.fullId;
|
||||||
showAtPosition(position);
|
showAtPosition(position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,6 +129,7 @@ private:
|
||||||
std::unique_ptr<HistoryView::Element> _emptyTextView;
|
std::unique_ptr<HistoryView::Element> _emptyTextView;
|
||||||
|
|
||||||
FullMsgId _currentMessageId;
|
FullMsgId _currentMessageId;
|
||||||
|
FullMsgId _highlightMessageId;
|
||||||
base::optional<Data::MessagePosition> _nextAnimatedScrollPosition;
|
base::optional<Data::MessagePosition> _nextAnimatedScrollPosition;
|
||||||
int _nextAnimatedScrollDelta = 0;
|
int _nextAnimatedScrollDelta = 0;
|
||||||
|
|
||||||
|
|
|
@ -3006,6 +3006,18 @@ not_null<HistoryView::ElementDelegate*> HistoryInner::ElementDelegate() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
TimeMs elementHighlightTime(
|
||||||
|
not_null<const HistoryView::Element*> view) override {
|
||||||
|
const auto fullAnimMs = App::main()->highlightStartTime(
|
||||||
|
view->data());
|
||||||
|
if (fullAnimMs > 0) {
|
||||||
|
const auto now = getms();
|
||||||
|
if (fullAnimMs < now) {
|
||||||
|
return now - fullAnimMs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TimeMs(0);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -174,26 +174,34 @@ void Element::setY(int y) {
|
||||||
_y = y;
|
_y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Element::marginTop() const {
|
void Element::paintHighlight(
|
||||||
const auto item = data();
|
Painter &p,
|
||||||
auto result = 0;
|
int geometryHeight) const {
|
||||||
if (!isHidden()) {
|
const auto animms = delegate()->elementHighlightTime(this);
|
||||||
if (isAttachedToPrevious()) {
|
if (!animms
|
||||||
result += st::msgMarginTopAttached;
|
|| animms >= st::activeFadeInDuration + st::activeFadeOutDuration) {
|
||||||
} else {
|
return;
|
||||||
result += st::msgMargin.top();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
result += displayedDateHeight();
|
|
||||||
if (const auto bar = Get<UnreadBar>()) {
|
|
||||||
result += bar->height();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Element::marginBottom() const {
|
const auto top = marginTop();
|
||||||
const auto item = data();
|
const auto bottom = marginBottom();
|
||||||
return isHidden() ? 0 : st::msgMargin.bottom();
|
const auto fill = qMin(top, bottom);
|
||||||
|
const auto skiptop = top - fill;
|
||||||
|
const auto fillheight = fill + geometryHeight + fill;
|
||||||
|
|
||||||
|
const auto dt = (animms > st::activeFadeInDuration)
|
||||||
|
? (1. - (animms - st::activeFadeInDuration)
|
||||||
|
/ float64(st::activeFadeOutDuration))
|
||||||
|
: (animms / float64(st::activeFadeInDuration));
|
||||||
|
const auto o = p.opacity();
|
||||||
|
p.setOpacity(o * dt);
|
||||||
|
p.fillRect(
|
||||||
|
0,
|
||||||
|
skiptop,
|
||||||
|
width(),
|
||||||
|
fillheight,
|
||||||
|
st::defaultTextPalette.selectOverlay);
|
||||||
|
p.setOpacity(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Element::isUnderCursor() const {
|
bool Element::isUnderCursor() const {
|
||||||
|
|
|
@ -42,6 +42,8 @@ public:
|
||||||
virtual bool elementUnderCursor(not_null<const Element*> view) = 0;
|
virtual bool elementUnderCursor(not_null<const Element*> view) = 0;
|
||||||
virtual void elementAnimationAutoplayAsync(
|
virtual void elementAnimationAutoplayAsync(
|
||||||
not_null<const Element*> element) = 0;
|
not_null<const Element*> element) = 0;
|
||||||
|
virtual TimeMs elementHighlightTime(
|
||||||
|
not_null<const Element*> element) = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -126,8 +128,9 @@ public:
|
||||||
int y() const;
|
int y() const;
|
||||||
void setY(int y);
|
void setY(int y);
|
||||||
|
|
||||||
int marginTop() const;
|
virtual int marginTop() const = 0;
|
||||||
int marginBottom() const;
|
virtual int marginBottom() const = 0;
|
||||||
|
|
||||||
void setPendingResize();
|
void setPendingResize();
|
||||||
bool pendingResize() const;
|
bool pendingResize() const;
|
||||||
bool isUnderCursor() const;
|
bool isUnderCursor() const;
|
||||||
|
@ -242,8 +245,9 @@ public:
|
||||||
virtual ~Element();
|
virtual ~Element();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setInitialSize(int maxWidth, int minHeight);
|
void paintHighlight(
|
||||||
void setCurrentSize(int width, int height);
|
Painter &p,
|
||||||
|
int geometryHeight) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This should be called only from previousInBlocksChanged()
|
// This should be called only from previousInBlocksChanged()
|
||||||
|
|
|
@ -239,7 +239,8 @@ ListWidget::ListWidget(
|
||||||
, _itemAverageHeight(itemMinimalHeight())
|
, _itemAverageHeight(itemMinimalHeight())
|
||||||
, _scrollDateCheck([this] { scrollDateCheck(); })
|
, _scrollDateCheck([this] { scrollDateCheck(); })
|
||||||
, _applyUpdatedScrollState([this] { applyUpdatedScrollState(); })
|
, _applyUpdatedScrollState([this] { applyUpdatedScrollState(); })
|
||||||
, _selectEnabled(_delegate->listAllowsMultiSelect()) {
|
, _selectEnabled(_delegate->listAllowsMultiSelect())
|
||||||
|
, _highlightTimer([this] { updateHighlightedMessage(); }) {
|
||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
_scrollDateHideTimer.setCallback([this] { scrollDateHideByTimer(); });
|
_scrollDateHideTimer.setCallback([this] { scrollDateHideByTimer(); });
|
||||||
Auth().data().viewRepaintRequest(
|
Auth().data().viewRepaintRequest(
|
||||||
|
@ -417,6 +418,32 @@ bool ListWidget::isBelowPosition(Data::MessagePosition position) const {
|
||||||
return _items.front()->data()->position() > position;
|
return _items.front()->data()->position() > position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListWidget::highlightMessage(FullMsgId itemId) {
|
||||||
|
if (const auto item = App::histItemById(itemId)) {
|
||||||
|
if (const auto view = viewForItem(item)) {
|
||||||
|
_highlightStart = getms();
|
||||||
|
_highlightedMessageId = itemId;
|
||||||
|
_highlightTimer.callEach(AnimationTimerDelta);
|
||||||
|
|
||||||
|
repaintItem(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ListWidget::updateHighlightedMessage() {
|
||||||
|
if (const auto item = App::histItemById(_highlightedMessageId)) {
|
||||||
|
if (const auto view = viewForItem(item)) {
|
||||||
|
repaintItem(view);
|
||||||
|
auto duration = st::activeFadeInDuration + st::activeFadeOutDuration;
|
||||||
|
if (getms() - _highlightStart <= duration) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_highlightTimer.cancel();
|
||||||
|
_highlightedMessageId = FullMsgId();
|
||||||
|
}
|
||||||
|
|
||||||
void ListWidget::checkUnreadBarCreation() {
|
void ListWidget::checkUnreadBarCreation() {
|
||||||
if (!_unreadBarElement) {
|
if (!_unreadBarElement) {
|
||||||
if (const auto index = _delegate->listUnreadBarView(_items)) {
|
if (const auto index = _delegate->listUnreadBarView(_items)) {
|
||||||
|
@ -1071,6 +1098,16 @@ void ListWidget::elementAnimationAutoplayAsync(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimeMs ListWidget::elementHighlightTime(
|
||||||
|
not_null<const HistoryView::Element*> element) {
|
||||||
|
if (element->data()->fullId() == _highlightedMessageId) {
|
||||||
|
if (_highlightTimer.isActive()) {
|
||||||
|
return getms() - _highlightStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TimeMs(0);
|
||||||
|
}
|
||||||
|
|
||||||
void ListWidget::saveState(not_null<ListMemento*> memento) {
|
void ListWidget::saveState(not_null<ListMemento*> memento) {
|
||||||
memento->setAroundPosition(_aroundPosition);
|
memento->setAroundPosition(_aroundPosition);
|
||||||
auto state = countScrollState();
|
auto state = countScrollState();
|
||||||
|
|
|
@ -149,6 +149,7 @@ public:
|
||||||
AnimatedScroll type);
|
AnimatedScroll type);
|
||||||
bool isAbovePosition(Data::MessagePosition position) const;
|
bool isAbovePosition(Data::MessagePosition position) const;
|
||||||
bool isBelowPosition(Data::MessagePosition position) const;
|
bool isBelowPosition(Data::MessagePosition position) const;
|
||||||
|
void highlightMessage(FullMsgId itemId);
|
||||||
|
|
||||||
TextWithEntities getSelectedText() const;
|
TextWithEntities getSelectedText() const;
|
||||||
MessageIdsList getSelectedItems() const;
|
MessageIdsList getSelectedItems() const;
|
||||||
|
@ -175,6 +176,7 @@ public:
|
||||||
bool elementUnderCursor(not_null<const Element*> view) override;
|
bool elementUnderCursor(not_null<const Element*> view) override;
|
||||||
void elementAnimationAutoplayAsync(
|
void elementAnimationAutoplayAsync(
|
||||||
not_null<const Element*> view) override;
|
not_null<const Element*> view) override;
|
||||||
|
TimeMs elementHighlightTime(not_null<const Element*> element) override;
|
||||||
|
|
||||||
~ListWidget();
|
~ListWidget();
|
||||||
|
|
||||||
|
@ -378,6 +380,8 @@ private:
|
||||||
void applyUpdatedScrollState();
|
void applyUpdatedScrollState();
|
||||||
void scrollToAnimationCallback(FullMsgId attachToId);
|
void scrollToAnimationCallback(FullMsgId attachToId);
|
||||||
|
|
||||||
|
void updateHighlightedMessage();
|
||||||
|
|
||||||
// This function finds all history items that are displayed and calls template method
|
// 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.
|
// for each found message (in given direction) in the passed history with passed top offset.
|
||||||
//
|
//
|
||||||
|
@ -469,6 +473,10 @@ private:
|
||||||
QPoint _trippleClickPoint;
|
QPoint _trippleClickPoint;
|
||||||
TimeMs _trippleClickStartTime = 0;
|
TimeMs _trippleClickStartTime = 0;
|
||||||
|
|
||||||
|
TimeMs _highlightStart = 0;
|
||||||
|
FullMsgId _highlightedMessageId;
|
||||||
|
base::Timer _highlightTimer;
|
||||||
|
|
||||||
rpl::lifetime _viewerLifetime;
|
rpl::lifetime _viewerLifetime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -342,6 +342,26 @@ QSize Message::performCountOptimalSize() {
|
||||||
return QSize(maxWidth, minHeight);
|
return QSize(maxWidth, minHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Message::marginTop() const {
|
||||||
|
auto result = 0;
|
||||||
|
if (!isHidden()) {
|
||||||
|
if (isAttachedToPrevious()) {
|
||||||
|
result += st::msgMarginTopAttached;
|
||||||
|
} else {
|
||||||
|
result += st::msgMargin.top();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result += displayedDateHeight();
|
||||||
|
if (const auto bar = Get<UnreadBar>()) {
|
||||||
|
result += bar->height();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Message::marginBottom() const {
|
||||||
|
return isHidden() ? 0 : st::msgMargin.bottom();
|
||||||
|
}
|
||||||
|
|
||||||
void Message::draw(
|
void Message::draw(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
QRect clip,
|
QRect clip,
|
||||||
|
@ -376,25 +396,11 @@ void Message::draw(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto fullAnimMs = App::main() ? App::main()->highlightStartTime(item) : 0LL;
|
paintHighlight(p, g.height());
|
||||||
if (fullAnimMs > 0 && fullAnimMs <= ms) {
|
|
||||||
auto animms = ms - fullAnimMs;
|
|
||||||
if (animms < st::activeFadeInDuration + st::activeFadeOutDuration) {
|
|
||||||
auto top = marginTop();
|
|
||||||
auto bottom = marginBottom();
|
|
||||||
auto fill = qMin(top, bottom);
|
|
||||||
auto skiptop = top - fill;
|
|
||||||
auto fillheight = fill + g.height() + fill;
|
|
||||||
|
|
||||||
auto dt = (animms > st::activeFadeInDuration) ? (1. - (animms - st::activeFadeInDuration) / float64(st::activeFadeOutDuration)) : (animms / float64(st::activeFadeInDuration));
|
p.setTextPalette(selected
|
||||||
auto o = p.opacity();
|
? (outbg ? st::outTextPaletteSelected : st::inTextPaletteSelected)
|
||||||
p.setOpacity(o * dt);
|
: (outbg ? st::outTextPalette : st::inTextPalette));
|
||||||
p.fillRect(0, skiptop, width(), fillheight, st::defaultTextPalette.selectOverlay);
|
|
||||||
p.setOpacity(o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p.setTextPalette(selected ? (outbg ? st::outTextPaletteSelected : st::inTextPaletteSelected) : (outbg ? st::outTextPalette : st::inTextPalette));
|
|
||||||
|
|
||||||
auto keyboard = item->inlineReplyKeyboard();
|
auto keyboard = item->inlineReplyKeyboard();
|
||||||
if (keyboard) {
|
if (keyboard) {
|
||||||
|
|
|
@ -32,6 +32,8 @@ public:
|
||||||
not_null<ElementDelegate*> delegate,
|
not_null<ElementDelegate*> delegate,
|
||||||
not_null<HistoryMessage*> data);
|
not_null<HistoryMessage*> data);
|
||||||
|
|
||||||
|
int marginTop() const override;
|
||||||
|
int marginBottom() const override;
|
||||||
void draw(
|
void draw(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
QRect clip,
|
QRect clip,
|
||||||
|
|
|
@ -373,6 +373,14 @@ bool Service::isHidden() const {
|
||||||
return Element::isHidden();
|
return Element::isHidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Service::marginTop() const {
|
||||||
|
return st::msgServiceMargin.top();
|
||||||
|
}
|
||||||
|
|
||||||
|
int Service::marginBottom() const {
|
||||||
|
return st::msgServiceMargin.bottom();
|
||||||
|
}
|
||||||
|
|
||||||
void Service::draw(
|
void Service::draw(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
QRect clip,
|
QRect clip,
|
||||||
|
@ -410,23 +418,7 @@ void Service::draw(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto fullAnimMs = App::main() ? App::main()->highlightStartTime(item) : 0LL;
|
paintHighlight(p, height);
|
||||||
if (fullAnimMs > 0 && fullAnimMs <= ms) {
|
|
||||||
auto animms = ms - fullAnimMs;
|
|
||||||
if (animms < st::activeFadeInDuration + st::activeFadeOutDuration) {
|
|
||||||
auto top = st::msgServiceMargin.top();
|
|
||||||
auto bottom = st::msgServiceMargin.bottom();
|
|
||||||
auto fill = qMin(top, bottom);
|
|
||||||
auto skiptop = top - fill;
|
|
||||||
auto fillheight = fill + height + fill;
|
|
||||||
|
|
||||||
auto dt = (animms > st::activeFadeInDuration) ? (1. - (animms - st::activeFadeInDuration) / float64(st::activeFadeOutDuration)) : (animms / float64(st::activeFadeInDuration));
|
|
||||||
auto o = p.opacity();
|
|
||||||
p.setOpacity(o * dt);
|
|
||||||
p.fillRect(0, skiptop, width(), fillheight, st::defaultTextPalette.selectOverlay);
|
|
||||||
p.setOpacity(o);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
p.setTextPalette(st::serviceTextPalette);
|
p.setTextPalette(st::serviceTextPalette);
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@ public:
|
||||||
not_null<ElementDelegate*> delegate,
|
not_null<ElementDelegate*> delegate,
|
||||||
not_null<HistoryService*> data);
|
not_null<HistoryService*> data);
|
||||||
|
|
||||||
|
int marginTop() const override;
|
||||||
|
int marginBottom() const override;
|
||||||
bool isHidden() const override;
|
bool isHidden() const override;
|
||||||
void draw(
|
void draw(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
|
|
Loading…
Reference in New Issue