mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +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) {
|
void Widget::updateControlsVisibility(bool fast) {
|
||||||
updateLoadMoreChatsVisibility();
|
updateLoadMoreChatsVisibility();
|
||||||
_scroll->setVisible(!_suggestions);
|
_scroll->setVisible(!_suggestions && _hidingSuggestions.empty());
|
||||||
if (_suggestions) {
|
|
||||||
_suggestions->show();
|
|
||||||
}
|
|
||||||
updateStoriesVisibility();
|
updateStoriesVisibility();
|
||||||
if ((_openedFolder || _openedForum) && _searchHasFocus) {
|
if ((_openedFolder || _openedForum) && _searchHasFocus) {
|
||||||
setInnerFocus();
|
setInnerFocus();
|
||||||
|
@ -1120,10 +1117,32 @@ void Widget::updateSuggestions(anim::type animated) {
|
||||||
const auto suggest = _searchHasFocus
|
const auto suggest = _searchHasFocus
|
||||||
&& !_searchInChat
|
&& !_searchInChat
|
||||||
&& (_inner->state() == WidgetState::Default);
|
&& (_inner->state() == WidgetState::Default);
|
||||||
|
if (anim::Disabled() || !session().data().chatsListLoaded()) {
|
||||||
|
animated = anim::type::instant;
|
||||||
|
}
|
||||||
if (!suggest && _suggestions) {
|
if (!suggest && _suggestions) {
|
||||||
_suggestions = nullptr;
|
if (animated == anim::type::normal) {
|
||||||
_scroll->show();
|
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) {
|
} else if (suggest && !_suggestions) {
|
||||||
|
if (animated == anim::type::normal) {
|
||||||
|
startWidthAnimation();
|
||||||
|
}
|
||||||
_suggestions = std::make_unique<Suggestions>(
|
_suggestions = std::make_unique<Suggestions>(
|
||||||
this,
|
this,
|
||||||
controller(),
|
controller(),
|
||||||
|
@ -1141,9 +1160,12 @@ void Widget::updateSuggestions(anim::type animated) {
|
||||||
}
|
}
|
||||||
}, _suggestions->lifetime());
|
}, _suggestions->lifetime());
|
||||||
|
|
||||||
_suggestions->show();
|
|
||||||
_scroll->hide();
|
|
||||||
updateControlsGeometry();
|
updateControlsGeometry();
|
||||||
|
|
||||||
|
_suggestions->show(animated, [=] {
|
||||||
|
stopWidthAnimation();
|
||||||
|
});
|
||||||
|
_scroll->hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1542,18 +1564,15 @@ void Widget::scrollToDefault(bool verytop) {
|
||||||
anim::sineInOut);
|
anim::sineInOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::startWidthAnimation() {
|
[[nodiscard]] QPixmap Widget::grabNonNarrowScrollFrame() {
|
||||||
if (!_widthAnimationCache.isNull()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto scrollGeometry = _scroll->geometry();
|
auto scrollGeometry = _scroll->geometry();
|
||||||
auto grabGeometry = QRect(
|
auto grabGeometry = QRect(
|
||||||
scrollGeometry.x(),
|
scrollGeometry.x(),
|
||||||
scrollGeometry.y(),
|
scrollGeometry.y(),
|
||||||
st::columnMinimalWidthLeft,
|
std::max(scrollGeometry.width(), st::columnMinimalWidthLeft),
|
||||||
scrollGeometry.height());
|
scrollGeometry.height());
|
||||||
_scroll->setGeometry(grabGeometry);
|
_scroll->setGeometry(grabGeometry);
|
||||||
_inner->resize(st::columnMinimalWidthLeft, _inner->height());
|
_inner->resize(grabGeometry.width(), _inner->height());
|
||||||
_inner->setNarrowRatio(0.);
|
_inner->setNarrowRatio(0.);
|
||||||
Ui::SendPendingMoveResizeEvents(_scroll);
|
Ui::SendPendingMoveResizeEvents(_scroll);
|
||||||
auto image = QImage(
|
auto image = QImage(
|
||||||
|
@ -1565,11 +1584,18 @@ void Widget::startWidthAnimation() {
|
||||||
QPainter p(&image);
|
QPainter p(&image);
|
||||||
Ui::RenderWidget(p, _scroll);
|
Ui::RenderWidget(p, _scroll);
|
||||||
}
|
}
|
||||||
_widthAnimationCache = Ui::PixmapFromImage(std::move(image));
|
|
||||||
if (scrollGeometry != grabGeometry) {
|
if (scrollGeometry != grabGeometry) {
|
||||||
_scroll->setGeometry(scrollGeometry);
|
_scroll->setGeometry(scrollGeometry);
|
||||||
updateControlsGeometry();
|
updateControlsGeometry();
|
||||||
}
|
}
|
||||||
|
return Ui::PixmapFromImage(std::move(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::startWidthAnimation() {
|
||||||
|
if (!_widthAnimationCache.isNull()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_widthAnimationCache = grabNonNarrowScrollFrame();
|
||||||
_scroll->hide();
|
_scroll->hide();
|
||||||
updateStoriesVisibility();
|
updateStoriesVisibility();
|
||||||
}
|
}
|
||||||
|
@ -1578,9 +1604,6 @@ void Widget::stopWidthAnimation() {
|
||||||
_widthAnimationCache = QPixmap();
|
_widthAnimationCache = QPixmap();
|
||||||
if (!_showAnimation) {
|
if (!_showAnimation) {
|
||||||
_scroll->setVisible(!_suggestions);
|
_scroll->setVisible(!_suggestions);
|
||||||
if (_suggestions) {
|
|
||||||
_suggestions->show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
updateStoriesVisibility();
|
updateStoriesVisibility();
|
||||||
update();
|
update();
|
||||||
|
@ -3226,7 +3249,15 @@ void Widget::paintEvent(QPaintEvent *e) {
|
||||||
|
|
||||||
auto belowTop = _scroll->y() + _scroll->height();
|
auto belowTop = _scroll->y() + _scroll->height();
|
||||||
if (!_widthAnimationCache.isNull()) {
|
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()
|
belowTop = _scroll->y()
|
||||||
+ (_widthAnimationCache.height() / style::DevicePixelRatio());
|
+ (_widthAnimationCache.height() / style::DevicePixelRatio());
|
||||||
}
|
}
|
||||||
|
@ -3302,12 +3333,17 @@ bool Widget::cancelSearch() {
|
||||||
setFocus();
|
setFocus();
|
||||||
clearingInChat = true;
|
clearingInChat = true;
|
||||||
}
|
}
|
||||||
|
const auto clearSearchFocus = !_searchInChat && _searchHasFocus;
|
||||||
|
if (!_suggestions && clearSearchFocus) {
|
||||||
|
// Don't create suggestions in unfocus case.
|
||||||
|
setFocus();
|
||||||
|
}
|
||||||
_lastSearchPeer = nullptr;
|
_lastSearchPeer = nullptr;
|
||||||
_lastSearchId = _lastSearchMigratedId = 0;
|
_lastSearchId = _lastSearchMigratedId = 0;
|
||||||
_inner->clearFilter();
|
_inner->clearFilter();
|
||||||
clearSearchField();
|
clearSearchField();
|
||||||
applySearchUpdate();
|
applySearchUpdate();
|
||||||
if (!_searchInChat && _searchHasFocus) {
|
if (_suggestions && clearSearchFocus) {
|
||||||
setFocus();
|
setFocus();
|
||||||
}
|
}
|
||||||
return clearingQuery || clearingInChat;
|
return clearingQuery || clearingInChat;
|
||||||
|
|
|
@ -105,6 +105,7 @@ public:
|
||||||
void jumpToTop(bool belowPinned = false);
|
void jumpToTop(bool belowPinned = false);
|
||||||
void raiseWithTooltip();
|
void raiseWithTooltip();
|
||||||
|
|
||||||
|
[[nodiscard]] QPixmap grabNonNarrowScrollFrame();
|
||||||
void startWidthAnimation();
|
void startWidthAnimation();
|
||||||
void stopWidthAnimation();
|
void stopWidthAnimation();
|
||||||
|
|
||||||
|
@ -277,6 +278,7 @@ private:
|
||||||
object_ptr<Ui::ElasticScroll> _scroll;
|
object_ptr<Ui::ElasticScroll> _scroll;
|
||||||
QPointer<InnerWidget> _inner;
|
QPointer<InnerWidget> _inner;
|
||||||
std::unique_ptr<Suggestions> _suggestions;
|
std::unique_ptr<Suggestions> _suggestions;
|
||||||
|
std::vector<std::unique_ptr<Suggestions>> _hidingSuggestions;
|
||||||
class BottomButton;
|
class BottomButton;
|
||||||
object_ptr<BottomButton> _updateTelegram = { nullptr };
|
object_ptr<BottomButton> _updateTelegram = { nullptr };
|
||||||
object_ptr<BottomButton> _loadMoreChats = { 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) {
|
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) {
|
void Suggestions::resizeEvent(QResizeEvent *e) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "base/object_ptr.h"
|
#include "base/object_ptr.h"
|
||||||
#include "dialogs/ui/top_peers_strip.h"
|
#include "dialogs/ui/top_peers_strip.h"
|
||||||
|
#include "ui/effects/animations.h"
|
||||||
#include "ui/rp_widget.h"
|
#include "ui/rp_widget.h"
|
||||||
|
|
||||||
namespace Main {
|
namespace Main {
|
||||||
|
@ -44,6 +45,10 @@ public:
|
||||||
void selectJump(Qt::Key direction, int pageSize = 0);
|
void selectJump(Qt::Key direction, int pageSize = 0);
|
||||||
void chooseRow();
|
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 {
|
[[nodiscard]] rpl::producer<not_null<PeerData*>> topPeerChosen() const {
|
||||||
return _topPeerChosen.events();
|
return _topPeerChosen.events();
|
||||||
}
|
}
|
||||||
|
@ -81,6 +86,11 @@ private:
|
||||||
rpl::event_stream<not_null<PeerData*>> _topPeerChosen;
|
rpl::event_stream<not_null<PeerData*>> _topPeerChosen;
|
||||||
rpl::event_stream<not_null<PeerData*>> _recentPeerChosen;
|
rpl::event_stream<not_null<PeerData*>> _recentPeerChosen;
|
||||||
|
|
||||||
|
Ui::Animations::Simple _shownAnimation;
|
||||||
|
Fn<void()> _showFinished;
|
||||||
|
bool _hidden = false;
|
||||||
|
QPixmap _cache;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<TopPeersList> TopPeersContent(
|
[[nodiscard]] rpl::producer<TopPeersList> TopPeersContent(
|
||||||
|
|
Loading…
Add table
Reference in a new issue