From 6da62f902b5c718c968fb024eebf398db7146aef Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 9 Jun 2016 22:28:58 +0300 Subject: [PATCH] Animated show and hide of the new history-to-down button. Fixed render in outbox read event handler for channels / supergroups. --- Telegram/SourceFiles/app.cpp | 19 +++--- Telegram/SourceFiles/historywidget.cpp | 12 ++-- Telegram/SourceFiles/mainwidget.cpp | 19 +++--- .../ui/buttons/history_down_button.cpp | 64 +++++++++++++++++-- .../ui/buttons/history_down_button.h | 16 +++++ 5 files changed, 101 insertions(+), 29 deletions(-) diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index c05e0624e..272c9b29b 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -1203,18 +1203,21 @@ namespace { } void feedInboxRead(const PeerId &peer, MsgId upTo) { - History *h = App::historyLoaded(peer); - if (h) { - h->inboxRead(upTo); + if (auto history = App::historyLoaded(peer)) { + history->inboxRead(upTo); } } void feedOutboxRead(const PeerId &peer, MsgId upTo) { - History *h = App::historyLoaded(peer); - if (h) { - h->outboxRead(upTo); - if (h->peer->isUser()) { - h->peer->asUser()->madeAction(); + if (auto history = App::historyLoaded(peer)) { + history->outboxRead(upTo); + if (history->lastMsg && history->lastMsg->out() && history->lastMsg->id <= upTo) { + if (App::main()) App::main()->dlgUpdated(history, history->lastMsg->id); + } + history->updateChatListEntry(); + + if (history->peer->isUser()) { + history->peer->asUser()->madeAction(); } } } diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp index 55bbfa12a..85fc58ff5 100644 --- a/Telegram/SourceFiles/historywidget.cpp +++ b/Telegram/SourceFiles/historywidget.cpp @@ -2906,7 +2906,6 @@ HistoryWidget::HistoryWidget(QWidget *parent) : TWidget(parent) updateScrollColors(); - _historyToEnd->hide(); _historyToEnd->installEventFilter(this); _fieldAutocomplete->hide(); @@ -5004,6 +5003,7 @@ void HistoryWidget::showAnimated(Window::SlideDirection direction, const Window: _cacheUnder = params.oldContentCache; show(); _topShadow.setVisible(params.withTopBarShadow ? false : true); + _historyToEnd->finishAnimation(); _cacheOver = App::main()->grabForShowAnimation(params); App::main()->topBar()->startAnim(); _topShadow.setVisible(params.withTopBarShadow ? true : false); @@ -5056,6 +5056,7 @@ void HistoryWidget::step_show(float64 ms, bool timer) { if (dt >= 1) { _a_show.stop(); _topShadow.setVisible(_peer ? true : false); + _historyToEnd->finishAnimation(); a_coordUnder.finish(); a_coordOver.finish(); @@ -5100,6 +5101,7 @@ void HistoryWidget::animStop() { if (!_a_show.animating()) return; _a_show.stop(); _topShadow.setVisible(_peer ? true : false); + _historyToEnd->finishAnimation(); } void HistoryWidget::step_record(float64 ms, bool timer) { @@ -6846,10 +6848,10 @@ void HistoryWidget::updateToEndVisibility() { return false; }; bool toEndVisible = isToEndVisible(); - if (toEndVisible && _historyToEnd->isHidden()) { - _historyToEnd->show(); - } else if (!toEndVisible && !_historyToEnd->isHidden()) { - _historyToEnd->hide(); + if (toEndVisible && _historyToEnd->hidden()) { + _historyToEnd->showAnimated(); + } else if (!toEndVisible && !_historyToEnd->hidden()) { + _historyToEnd->hideAnimated(); } } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index e59b115fd..4a1f6524d 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -4178,17 +4178,11 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { } // update before applying skipped - PeerId id = peerFromMTP(d.vpeer); - App::feedOutboxRead(id, d.vmax_id.v); - if (_history->peer() && _history->peer()->id == id) { + auto peerId = peerFromMTP(d.vpeer); + App::feedOutboxRead(peerId, d.vmax_id.v); + if (_history->peer() && _history->peer()->id == peerId) { _history->update(); } - if (History *h = App::historyLoaded(id)) { - if (h->lastMsg && h->lastMsg->out() && h->lastMsg->id <= d.vmax_id.v) { - dlgUpdated(h, h->lastMsg->id); - } - h->updateChatListEntry(); - } ptsApplySkippedUpdates(); } break; @@ -4538,8 +4532,11 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { case mtpc_updateReadChannelOutbox: { auto &d(update.c_updateReadChannelOutbox()); - auto channel = App::channelLoaded(d.vchannel_id.v); - App::feedOutboxRead(peerFromChannel(d.vchannel_id.v), d.vmax_id.v); + auto peerId = peerFromChannel(d.vchannel_id.v); + App::feedOutboxRead(peerId, d.vmax_id.v); + if (_history->peer() && _history->peer()->id == peerId) { + _history->update(); + } } break; case mtpc_updateDeleteChannelMessages: { diff --git a/Telegram/SourceFiles/ui/buttons/history_down_button.cpp b/Telegram/SourceFiles/ui/buttons/history_down_button.cpp index 3ba35eec6..409091755 100644 --- a/Telegram/SourceFiles/ui/buttons/history_down_button.cpp +++ b/Telegram/SourceFiles/ui/buttons/history_down_button.cpp @@ -30,16 +30,44 @@ HistoryDownButton::HistoryDownButton(QWidget *parent) : Button(parent) , a_arrowOpacity(st::btnAttachEmoji.opacity, st::btnAttachEmoji.opacity) , _a_arrowOver(animation(this, &HistoryDownButton::step_arrowOver)) { setCursor(style::cur_pointer); - resize(st::historyToDown.width(), st::historyToDownPaddingTop + st::historyToDown.height()); + + int iconWidth = st::historyToDown.width(); + int iconHeight = st::historyToDown.height(); + int retina = cIntRetinaFactor(); + resize(iconWidth, st::historyToDownPaddingTop + iconHeight); + + QImage cache(iconWidth * retina, iconHeight * retina, QImage::Format_ARGB32_Premultiplied); + cache.setDevicePixelRatio(cRetinaFactor()); + { + Painter p(&cache); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(0, 0, iconWidth, iconHeight, st::transparent); + st::historyToDown.paint(p, QPoint(0, 0), st::historyToDown.width()); + } + _cache = App::pixmapFromImageInPlace(std_::move(cache)); + _cache.setDevicePixelRatio(cRetinaFactor()); + + hide(); } void HistoryDownButton::paintEvent(QPaintEvent *e) { Painter p(this); - st::historyToDown.paint(p, QPoint(0, st::historyToDownPaddingTop), width()); - p.setOpacity(a_arrowOpacity.current()); + + float64 opacity = 1.; + if (_a_show.animating(getms())) { + opacity = _a_show.current(); + p.setOpacity(opacity); + p.drawPixmap(0, st::historyToDownPaddingTop, _cache); + } else if (!_shown) { + hide(); + return; + } else { + st::historyToDown.paint(p, QPoint(0, st::historyToDownPaddingTop), width()); + } + p.setOpacity(opacity * a_arrowOpacity.current()); st::historyToDownArrow.paint(p, QPoint(0, st::historyToDownPaddingTop), width()); if (_unreadCount > 0) { - p.setOpacity(1); + p.setOpacity(opacity); bool active = false, muted = false; auto unreadString = QString::number(_unreadCount); if (unreadString.size() > 4) { @@ -66,6 +94,33 @@ void HistoryDownButton::setUnreadCount(int unreadCount) { update(); } +bool HistoryDownButton::hidden() const { + return !_shown; +} + +void HistoryDownButton::showAnimated() { + if (_shown) return; + + if (isHidden()) show(); + toggleAnimated(); +} + +void HistoryDownButton::hideAnimated() { + if (!_shown) return; + toggleAnimated(); +} + +void HistoryDownButton::toggleAnimated() { + _shown = !_shown; + float64 from = _shown ? 0. : 1., to = _shown ? 1. : 0.; + START_ANIMATION(_a_show, func(this, &HistoryDownButton::repaintCallback), from, to, st::btnAttachEmoji.duration, anim::linear); +} + +void HistoryDownButton::finishAnimation() { + _a_show.finish(); + setVisible(_shown); +} + void HistoryDownButton::step_arrowOver(float64 ms, bool timer) { float64 dt = ms / st::btnAttachEmoji.duration; if (dt >= 1) { @@ -77,5 +132,4 @@ void HistoryDownButton::step_arrowOver(float64 ms, bool timer) { if (timer) update(); } - } // namespace Ui diff --git a/Telegram/SourceFiles/ui/buttons/history_down_button.h b/Telegram/SourceFiles/ui/buttons/history_down_button.h index 4b81ca5d3..43dbd098c 100644 --- a/Telegram/SourceFiles/ui/buttons/history_down_button.h +++ b/Telegram/SourceFiles/ui/buttons/history_down_button.h @@ -33,17 +33,33 @@ public: return _unreadCount; } + bool hidden() const; + + void showAnimated(); + void hideAnimated(); + + void finishAnimation(); + protected: void paintEvent(QPaintEvent *e) override; void onStateChanged(int oldState, ButtonStateChangeSource source) override; private: + void toggleAnimated(); + void repaintCallback() { + update(); + } void step_arrowOver(float64 ms, bool timer); + QPixmap _cache; + bool _shown = false; + anim::fvalue a_arrowOpacity; Animation _a_arrowOver; + FloatAnimation _a_show; + int _unreadCount = 0; };