mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Animate search suggestions.
This commit is contained in:
parent
19f5d95a3c
commit
0180fe9468
4 changed files with 122 additions and 21 deletions
|
@ -1030,10 +1030,7 @@ void Widget::fullSearchRefreshOn(rpl::producer<> events) {
|
|||
|
||||
void Widget::updateControlsVisibility(bool fast) {
|
||||
updateLoadMoreChatsVisibility();
|
||||
_scroll->setVisible(!_suggestions);
|
||||
if (_suggestions) {
|
||||
_suggestions->show();
|
||||
}
|
||||
_scroll->setVisible(!_suggestions && _hidingSuggestions.empty());
|
||||
updateStoriesVisibility();
|
||||
if ((_openedFolder || _openedForum) && _searchHasFocus) {
|
||||
setInnerFocus();
|
||||
|
@ -1120,10 +1117,32 @@ void Widget::updateSuggestions(anim::type animated) {
|
|||
const auto suggest = _searchHasFocus
|
||||
&& !_searchInChat
|
||||
&& (_inner->state() == WidgetState::Default);
|
||||
if (anim::Disabled() || !session().data().chatsListLoaded()) {
|
||||
animated = anim::type::instant;
|
||||
}
|
||||
if (!suggest && _suggestions) {
|
||||
_suggestions = nullptr;
|
||||
_scroll->show();
|
||||
if (animated == anim::type::normal) {
|
||||
startWidthAnimation();
|
||||
_suggestions->hide(animated, [=, raw = _suggestions.get()] {
|
||||
stopWidthAnimation();
|
||||
_hidingSuggestions.erase(
|
||||
ranges::remove(
|
||||
_hidingSuggestions,
|
||||
raw,
|
||||
&std::unique_ptr<Suggestions>::get),
|
||||
end(_hidingSuggestions));
|
||||
updateControlsVisibility();
|
||||
});
|
||||
_hidingSuggestions.push_back(std::move(_suggestions));
|
||||
} else {
|
||||
_suggestions = nullptr;
|
||||
_hidingSuggestions.clear();
|
||||
_scroll->show();
|
||||
}
|
||||
} else if (suggest && !_suggestions) {
|
||||
if (animated == anim::type::normal) {
|
||||
startWidthAnimation();
|
||||
}
|
||||
_suggestions = std::make_unique<Suggestions>(
|
||||
this,
|
||||
controller(),
|
||||
|
@ -1141,9 +1160,12 @@ void Widget::updateSuggestions(anim::type animated) {
|
|||
}
|
||||
}, _suggestions->lifetime());
|
||||
|
||||
_suggestions->show();
|
||||
_scroll->hide();
|
||||
updateControlsGeometry();
|
||||
|
||||
_suggestions->show(animated, [=] {
|
||||
stopWidthAnimation();
|
||||
});
|
||||
_scroll->hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1542,18 +1564,15 @@ void Widget::scrollToDefault(bool verytop) {
|
|||
anim::sineInOut);
|
||||
}
|
||||
|
||||
void Widget::startWidthAnimation() {
|
||||
if (!_widthAnimationCache.isNull()) {
|
||||
return;
|
||||
}
|
||||
[[nodiscard]] QPixmap Widget::grabNonNarrowScrollFrame() {
|
||||
auto scrollGeometry = _scroll->geometry();
|
||||
auto grabGeometry = QRect(
|
||||
scrollGeometry.x(),
|
||||
scrollGeometry.y(),
|
||||
st::columnMinimalWidthLeft,
|
||||
std::max(scrollGeometry.width(), st::columnMinimalWidthLeft),
|
||||
scrollGeometry.height());
|
||||
_scroll->setGeometry(grabGeometry);
|
||||
_inner->resize(st::columnMinimalWidthLeft, _inner->height());
|
||||
_inner->resize(grabGeometry.width(), _inner->height());
|
||||
_inner->setNarrowRatio(0.);
|
||||
Ui::SendPendingMoveResizeEvents(_scroll);
|
||||
auto image = QImage(
|
||||
|
@ -1565,11 +1584,18 @@ void Widget::startWidthAnimation() {
|
|||
QPainter p(&image);
|
||||
Ui::RenderWidget(p, _scroll);
|
||||
}
|
||||
_widthAnimationCache = Ui::PixmapFromImage(std::move(image));
|
||||
if (scrollGeometry != grabGeometry) {
|
||||
_scroll->setGeometry(scrollGeometry);
|
||||
updateControlsGeometry();
|
||||
}
|
||||
return Ui::PixmapFromImage(std::move(image));
|
||||
}
|
||||
|
||||
void Widget::startWidthAnimation() {
|
||||
if (!_widthAnimationCache.isNull()) {
|
||||
return;
|
||||
}
|
||||
_widthAnimationCache = grabNonNarrowScrollFrame();
|
||||
_scroll->hide();
|
||||
updateStoriesVisibility();
|
||||
}
|
||||
|
@ -1578,9 +1604,6 @@ void Widget::stopWidthAnimation() {
|
|||
_widthAnimationCache = QPixmap();
|
||||
if (!_showAnimation) {
|
||||
_scroll->setVisible(!_suggestions);
|
||||
if (_suggestions) {
|
||||
_suggestions->show();
|
||||
}
|
||||
}
|
||||
updateStoriesVisibility();
|
||||
update();
|
||||
|
@ -3226,7 +3249,15 @@ void Widget::paintEvent(QPaintEvent *e) {
|
|||
|
||||
auto belowTop = _scroll->y() + _scroll->height();
|
||||
if (!_widthAnimationCache.isNull()) {
|
||||
p.drawPixmapLeft(0, _scroll->y(), width(), _widthAnimationCache);
|
||||
const auto suggestionsShown = _suggestions
|
||||
? _suggestions->shownOpacity()
|
||||
: !_hidingSuggestions.empty()
|
||||
? _hidingSuggestions.back()->shownOpacity()
|
||||
: 0.;
|
||||
const auto suggestionsSkip = suggestionsShown
|
||||
* (st::topPeers.height + st::searchedBarHeight);
|
||||
const auto top = _scroll->y() + suggestionsSkip;
|
||||
p.drawPixmapLeft(0, top, width(), _widthAnimationCache);
|
||||
belowTop = _scroll->y()
|
||||
+ (_widthAnimationCache.height() / style::DevicePixelRatio());
|
||||
}
|
||||
|
@ -3302,12 +3333,17 @@ bool Widget::cancelSearch() {
|
|||
setFocus();
|
||||
clearingInChat = true;
|
||||
}
|
||||
const auto clearSearchFocus = !_searchInChat && _searchHasFocus;
|
||||
if (!_suggestions && clearSearchFocus) {
|
||||
// Don't create suggestions in unfocus case.
|
||||
setFocus();
|
||||
}
|
||||
_lastSearchPeer = nullptr;
|
||||
_lastSearchId = _lastSearchMigratedId = 0;
|
||||
_inner->clearFilter();
|
||||
clearSearchField();
|
||||
applySearchUpdate();
|
||||
if (!_searchInChat && _searchHasFocus) {
|
||||
if (_suggestions && clearSearchFocus) {
|
||||
setFocus();
|
||||
}
|
||||
return clearingQuery || clearingInChat;
|
||||
|
|
|
@ -105,6 +105,7 @@ public:
|
|||
void jumpToTop(bool belowPinned = false);
|
||||
void raiseWithTooltip();
|
||||
|
||||
[[nodiscard]] QPixmap grabNonNarrowScrollFrame();
|
||||
void startWidthAnimation();
|
||||
void stopWidthAnimation();
|
||||
|
||||
|
@ -277,6 +278,7 @@ private:
|
|||
object_ptr<Ui::ElasticScroll> _scroll;
|
||||
QPointer<InnerWidget> _inner;
|
||||
std::unique_ptr<Suggestions> _suggestions;
|
||||
std::vector<std::unique_ptr<Suggestions>> _hidingSuggestions;
|
||||
class BottomButton;
|
||||
object_ptr<BottomButton> _updateTelegram = { nullptr };
|
||||
object_ptr<BottomButton> _loadMoreChats = { nullptr };
|
||||
|
|
|
@ -545,8 +545,61 @@ void Suggestions::chooseRow() {
|
|||
}
|
||||
}
|
||||
|
||||
void Suggestions::show(anim::type animated, Fn<void()> finish) {
|
||||
RpWidget::show();
|
||||
|
||||
_hidden = false;
|
||||
if (animated == anim::type::instant) {
|
||||
_shownAnimation.stop();
|
||||
_scroll->show();
|
||||
} else {
|
||||
_shownAnimation.start([=] {
|
||||
update();
|
||||
if (!_shownAnimation.animating() && finish) {
|
||||
finish();
|
||||
_cache = QPixmap();
|
||||
_scroll->show();
|
||||
}
|
||||
}, 0., 1., st::slideDuration, anim::easeOutQuint);
|
||||
_cache = Ui::GrabWidget(_scroll.get());
|
||||
_scroll->hide();
|
||||
}
|
||||
}
|
||||
|
||||
void Suggestions::hide(anim::type animated, Fn<void()> finish) {
|
||||
_hidden = true;
|
||||
if (isHidden()) {
|
||||
return;
|
||||
} else if (animated == anim::type::instant) {
|
||||
RpWidget::hide();
|
||||
} else {
|
||||
_shownAnimation.start([=] {
|
||||
update();
|
||||
if (!_shownAnimation.animating() && finish) {
|
||||
finish();
|
||||
}
|
||||
}, 1., 0., st::slideDuration, anim::easeOutQuint);
|
||||
_cache = Ui::GrabWidget(_scroll.get());
|
||||
_scroll->hide();
|
||||
}
|
||||
}
|
||||
|
||||
float64 Suggestions::shownOpacity() const {
|
||||
return _shownAnimation.value(_hidden ? 0. : 1.);
|
||||
}
|
||||
|
||||
void Suggestions::paintEvent(QPaintEvent *e) {
|
||||
QPainter(this).fillRect(e->rect(), st::windowBg);
|
||||
const auto opacity = shownOpacity();
|
||||
auto color = st::windowBg->c;
|
||||
color.setAlphaF(color.alphaF() * opacity);
|
||||
|
||||
auto p = QPainter(this);
|
||||
p.fillRect(e->rect(), color);
|
||||
if (_scroll->isHidden()) {
|
||||
const auto slide = st::topPeers.height + st::searchedBarHeight;
|
||||
p.setOpacity(opacity);
|
||||
p.drawPixmap(0, (opacity - 1.) * slide, _cache);
|
||||
}
|
||||
}
|
||||
|
||||
void Suggestions::resizeEvent(QResizeEvent *e) {
|
||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "base/object_ptr.h"
|
||||
#include "dialogs/ui/top_peers_strip.h"
|
||||
#include "ui/effects/animations.h"
|
||||
#include "ui/rp_widget.h"
|
||||
|
||||
namespace Main {
|
||||
|
@ -44,6 +45,10 @@ public:
|
|||
void selectJump(Qt::Key direction, int pageSize = 0);
|
||||
void chooseRow();
|
||||
|
||||
void show(anim::type animated, Fn<void()> finish);
|
||||
void hide(anim::type animated, Fn<void()> finish);
|
||||
[[nodiscard]] float64 shownOpacity() const;
|
||||
|
||||
[[nodiscard]] rpl::producer<not_null<PeerData*>> topPeerChosen() const {
|
||||
return _topPeerChosen.events();
|
||||
}
|
||||
|
@ -81,6 +86,11 @@ private:
|
|||
rpl::event_stream<not_null<PeerData*>> _topPeerChosen;
|
||||
rpl::event_stream<not_null<PeerData*>> _recentPeerChosen;
|
||||
|
||||
Ui::Animations::Simple _shownAnimation;
|
||||
Fn<void()> _showFinished;
|
||||
bool _hidden = false;
|
||||
QPixmap _cache;
|
||||
|
||||
};
|
||||
|
||||
[[nodiscard]] rpl::producer<TopPeersList> TopPeersContent(
|
||||
|
|
Loading…
Add table
Reference in a new issue