Highlight found messages in feed.

This commit is contained in:
John Preston 2018-02-16 20:59:35 +03:00
parent 07528be1e6
commit 351a423337
13 changed files with 145 additions and 60 deletions

View File

@ -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) {
memento->setFilter(std::move(_filter));

View File

@ -85,6 +85,8 @@ public:
not_null<const HistoryView::Element*> view) override;
void elementAnimationAutoplayAsync(
not_null<const HistoryView::Element*> view) override;
TimeMs elementHighlightTime(
not_null<const HistoryView::Element*> element) override;
~InnerWidget();

View File

@ -159,7 +159,11 @@ void Widget::scrollDownClicked() {
}
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;
_nextAnimatedScrollDelta = _inner->isBelowPosition(position)
? -_scroll->height()
@ -424,6 +428,9 @@ void Widget::listContentRefreshed() {
position,
_nextAnimatedScrollDelta,
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();
_inner->restoreState(memento->list());
if (const auto position = memento->position()) {
_currentMessageId = position.fullId;
_currentMessageId = _highlightMessageId = position.fullId;
showAtPosition(position);
}
}

View File

@ -129,6 +129,7 @@ private:
std::unique_ptr<HistoryView::Element> _emptyTextView;
FullMsgId _currentMessageId;
FullMsgId _highlightMessageId;
base::optional<Data::MessagePosition> _nextAnimatedScrollPosition;
int _nextAnimatedScrollDelta = 0;

View File

@ -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);
}
};

View File

@ -174,26 +174,34 @@ void Element::setY(int y) {
_y = y;
}
int Element::marginTop() const {
const auto item = data();
auto result = 0;
if (!isHidden()) {
if (isAttachedToPrevious()) {
result += st::msgMarginTopAttached;
} else {
result += st::msgMargin.top();
}
void Element::paintHighlight(
Painter &p,
int geometryHeight) const {
const auto animms = delegate()->elementHighlightTime(this);
if (!animms
|| animms >= st::activeFadeInDuration + st::activeFadeOutDuration) {
return;
}
result += displayedDateHeight();
if (const auto bar = Get<UnreadBar>()) {
result += bar->height();
}
return result;
}
int Element::marginBottom() const {
const auto item = data();
return isHidden() ? 0 : st::msgMargin.bottom();
const auto top = marginTop();
const auto bottom = marginBottom();
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 {

View File

@ -42,6 +42,8 @@ public:
virtual bool elementUnderCursor(not_null<const Element*> view) = 0;
virtual void elementAnimationAutoplayAsync(
not_null<const Element*> element) = 0;
virtual TimeMs elementHighlightTime(
not_null<const Element*> element) = 0;
};
@ -126,8 +128,9 @@ public:
int y() const;
void setY(int y);
int marginTop() const;
int marginBottom() const;
virtual int marginTop() const = 0;
virtual int marginBottom() const = 0;
void setPendingResize();
bool pendingResize() const;
bool isUnderCursor() const;
@ -242,8 +245,9 @@ public:
virtual ~Element();
protected:
void setInitialSize(int maxWidth, int minHeight);
void setCurrentSize(int width, int height);
void paintHighlight(
Painter &p,
int geometryHeight) const;
private:
// This should be called only from previousInBlocksChanged()

View File

@ -239,7 +239,8 @@ ListWidget::ListWidget(
, _itemAverageHeight(itemMinimalHeight())
, _scrollDateCheck([this] { scrollDateCheck(); })
, _applyUpdatedScrollState([this] { applyUpdatedScrollState(); })
, _selectEnabled(_delegate->listAllowsMultiSelect()) {
, _selectEnabled(_delegate->listAllowsMultiSelect())
, _highlightTimer([this] { updateHighlightedMessage(); }) {
setMouseTracking(true);
_scrollDateHideTimer.setCallback([this] { scrollDateHideByTimer(); });
Auth().data().viewRepaintRequest(
@ -417,6 +418,32 @@ bool ListWidget::isBelowPosition(Data::MessagePosition position) const {
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() {
if (!_unreadBarElement) {
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) {
memento->setAroundPosition(_aroundPosition);
auto state = countScrollState();

View File

@ -149,6 +149,7 @@ public:
AnimatedScroll type);
bool isAbovePosition(Data::MessagePosition position) const;
bool isBelowPosition(Data::MessagePosition position) const;
void highlightMessage(FullMsgId itemId);
TextWithEntities getSelectedText() const;
MessageIdsList getSelectedItems() const;
@ -175,6 +176,7 @@ public:
bool elementUnderCursor(not_null<const Element*> view) override;
void elementAnimationAutoplayAsync(
not_null<const Element*> view) override;
TimeMs elementHighlightTime(not_null<const Element*> element) override;
~ListWidget();
@ -378,6 +380,8 @@ private:
void applyUpdatedScrollState();
void scrollToAnimationCallback(FullMsgId attachToId);
void updateHighlightedMessage();
// 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.
//
@ -469,6 +473,10 @@ private:
QPoint _trippleClickPoint;
TimeMs _trippleClickStartTime = 0;
TimeMs _highlightStart = 0;
FullMsgId _highlightedMessageId;
base::Timer _highlightTimer;
rpl::lifetime _viewerLifetime;
};

View File

@ -342,6 +342,26 @@ QSize Message::performCountOptimalSize() {
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(
Painter &p,
QRect clip,
@ -376,25 +396,11 @@ void Message::draw(
return;
}
auto fullAnimMs = App::main() ? App::main()->highlightStartTime(item) : 0LL;
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;
paintHighlight(p, g.height());
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(selected ? (outbg ? st::outTextPaletteSelected : st::inTextPaletteSelected) : (outbg ? st::outTextPalette : st::inTextPalette));
p.setTextPalette(selected
? (outbg ? st::outTextPaletteSelected : st::inTextPaletteSelected)
: (outbg ? st::outTextPalette : st::inTextPalette));
auto keyboard = item->inlineReplyKeyboard();
if (keyboard) {

View File

@ -32,6 +32,8 @@ public:
not_null<ElementDelegate*> delegate,
not_null<HistoryMessage*> data);
int marginTop() const override;
int marginBottom() const override;
void draw(
Painter &p,
QRect clip,

View File

@ -373,6 +373,14 @@ bool Service::isHidden() const {
return Element::isHidden();
}
int Service::marginTop() const {
return st::msgServiceMargin.top();
}
int Service::marginBottom() const {
return st::msgServiceMargin.bottom();
}
void Service::draw(
Painter &p,
QRect clip,
@ -410,23 +418,7 @@ void Service::draw(
return;
}
auto fullAnimMs = App::main() ? App::main()->highlightStartTime(item) : 0LL;
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);
}
}
paintHighlight(p, height);
p.setTextPalette(st::serviceTextPalette);

View File

@ -19,6 +19,8 @@ public:
not_null<ElementDelegate*> delegate,
not_null<HistoryService*> data);
int marginTop() const override;
int marginBottom() const override;
bool isHidden() const override;
void draw(
Painter &p,