From 5368507259d3c2ee31a174b356964f3b1a54f2e7 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 13 Jul 2023 20:49:08 +0400 Subject: [PATCH] Improve lock/unlock icon behavior. --- Telegram/SourceFiles/dialogs/dialogs.style | 17 ++--- .../SourceFiles/dialogs/dialogs_widget.cpp | 49 +++++++++++-- Telegram/SourceFiles/dialogs/dialogs_widget.h | 1 + .../dialogs/ui/dialogs_stories_list.cpp | 69 +++++++++++++------ .../dialogs/ui/dialogs_stories_list.h | 8 +++ 5 files changed, 111 insertions(+), 33 deletions(-) diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style index 6a20b6cf7..d8b405e7c 100644 --- a/Telegram/SourceFiles/dialogs/dialogs.style +++ b/Telegram/SourceFiles/dialogs/dialogs.style @@ -221,19 +221,20 @@ dialogsMenuToggleUnreadMuted: icon { dialogsLock: IconButton(dialogsMenuToggle) { icon: icon {{ "dialogs/dialogs_lock", dialogsMenuIconFg }}; iconOver: icon {{ "dialogs/dialogs_lock", dialogsMenuIconFgOver }}; + ripple: emptyRippleAnimation; } dialogsUnlockIcon: icon {{ "dialogs/dialogs_unlock", dialogsMenuIconFg }}; dialogsUnlockIconOver: icon {{ "dialogs/dialogs_unlock", dialogsMenuIconFgOver }}; dialogsCalendar: IconButton { - width: 29px; - height: 32px; + width: 32px; + height: 35px; icon: icon {{ "dialogs/dialogs_calendar", dialogsMenuIconFg }}; iconOver: icon {{ "dialogs/dialogs_calendar", dialogsMenuIconFgOver }}; - iconPosition: point(0px, 5px); + iconPosition: point(1px, 6px); } dialogsSearchFrom: IconButton(dialogsCalendar) { - width: 26px; + width: 29px; icon: icon {{ "dialogs/dialogs_search_from", dialogsMenuIconFg }}; iconOver: icon {{ "dialogs/dialogs_search_from", dialogsMenuIconFgOver }}; } @@ -276,12 +277,12 @@ dialogsCancelSearchInPeer: IconButton(dialogsMenuToggle) { rippleAreaSize: 34px; } dialogsCancelSearch: CrossButton { - width: 32px; - height: 32px; + width: 35px; + height: 35px; cross: CrossAnimation { - size: 32px; - skip: 10px; + size: 35px; + skip: 12px; stroke: 1.5; minScale: 0.3; } diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index bcf81a3b4..984d5b647 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -814,14 +814,20 @@ void Widget::setupStories() { using Phase = Ui::ElasticScrollMovement; _stories->setExpandedHeight( _aboveScrollAdded, - (movement == Phase::Momentum || movement == Phase::Returning) - && (explicitlyExpanded < above)); + ((movement == Phase::Momentum || movement == Phase::Returning) + && (explicitlyExpanded < above))); if (position.overscroll > 0 || (position.value > (_storiesExplicitExpandScrollTop + st::dialogsRowHeight))) { storiesToggleExplicitExpand(false); } + updateLockUnlockPosition(); + }, lifetime()); + + _stories->collapsedGeometryChanged( + ) | rpl::start_with_next([=] { + updateLockUnlockPosition(); }, lifetime()); _stories->clicks( @@ -857,6 +863,10 @@ void Widget::setupStories() { _stories->emptyValue() | rpl::skip(1) | rpl::start_with_next([=] { updateStoriesVisibility(); }, lifetime()); + + _stories->widthValue() | rpl::start_with_next([=] { + updateLockUnlockPosition(); + }, lifetime()); } void Widget::storiesToggleExplicitExpand(bool expand) { @@ -977,6 +987,23 @@ void Widget::updateControlsVisibility(bool fast) { if (_childList && _filter->hasFocus()) { setInnerFocus(); } + updateLockUnlockPosition(); +} + +void Widget::updateLockUnlockPosition() { + if (_lockUnlock->isHidden()) { + return; + } + const auto stories = (_stories && !_stories->isHidden()) + ? _stories->collapsedGeometryCurrent() + : Stories::List::CollapsedGeometry(); + const auto simple = _filter->x() + _filter->width(); + const auto right = stories.geometry.isEmpty() + ? simple + : anim::interpolate(stories.geometry.x(), simple, stories.expanded); + _lockUnlock->move( + right - _lockUnlock->width(), + st::dialogsFilterPadding.y()); } void Widget::changeOpenedSubsection( @@ -1388,6 +1415,8 @@ void Widget::updateStoriesVisibility() { if (_aboveScrollAdded > 0 && _updateScrollGeometryCached) { _updateScrollGeometryCached(); } + updateLockUnlockVisibility(); + updateLockUnlockPosition(); } } @@ -2253,6 +2282,7 @@ void Widget::applyFilterUpdate(bool force) { _cancelSearch->toggle(!filterText.isEmpty(), anim::type::normal); updateLoadMoreChatsVisibility(); updateJumpToDateVisibility(); + updateLockUnlockPosition(); if (filterText.isEmpty()) { _peerSearchCache.clear(); @@ -2458,6 +2488,7 @@ bool Widget::setSearchInChat(Key chat, PeerData *from) { updateSearchFromVisibility(); clearSearchCache(); } + updateLockUnlockPosition(); if (_searchInChat && _layout == Layout::Main) { controller()->closeFolder(); } @@ -2580,9 +2611,18 @@ void Widget::updateLockUnlockVisibility() { if (_showAnimation) { return; } - const auto hidden = !session().domain().local().hasLocalPasscode(); + const auto hidden = !session().domain().local().hasLocalPasscode() + || (_showAnimation != nullptr) + || _openedForum + || !_widthAnimationCache.isNull() + || _childList + || !_filter->getLastText().isEmpty() + || _searchInChat; if (_lockUnlock->isHidden() != hidden) { _lockUnlock->setVisible(!hidden); + if (!hidden) { + updateLockUnlockPosition(); + } updateControlsGeometry(); } } @@ -2685,7 +2725,6 @@ void Widget::updateControlsGeometry() { _searchForNarrowFilters->moveToLeft(searchLeft, st::dialogsFilterPadding.y()); auto right = filterLeft + filterWidth; - _lockUnlock->moveToLeft(right + st::dialogsFilterPadding.x(), st::dialogsFilterPadding.y()); _cancelSearch->moveToLeft(right - _cancelSearch->width(), _filter->y()); right -= _jumpToDate->width(); _jumpToDate->moveToLeft(right, _filter->y()); right -= _chooseFromUser->width(); _chooseFromUser->moveToLeft(right, _filter->y()); @@ -2709,6 +2748,8 @@ void Widget::updateControlsGeometry() { st::lineWidth); } + updateLockUnlockPosition(); + auto bottomSkip = 0; const auto putBottomButton = [&](auto &button) { if (button && !button->isHidden()) { diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.h b/Telegram/SourceFiles/dialogs/dialogs_widget.h index 245998392..48760b630 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.h @@ -224,6 +224,7 @@ private: void updateScrollUpVisibility(); void startScrollUpButtonAnimation(bool shown); void updateScrollUpPosition(); + void updateLockUnlockPosition(); MTP::Sender _api; diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_stories_list.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_stories_list.cpp index e7c0a6bfb..685cc767d 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_stories_list.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_stories_list.cpp @@ -15,6 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include +#include "base/debug_log.h" + namespace Dialogs::Stories { namespace { @@ -36,6 +38,7 @@ constexpr auto kExpandCatchUpDuration = crl::time(200); struct List::Layout { int itemsCount = 0; + QPointF geometryShift; float64 expandedRatio = 0.; float64 ratio = 0.; float64 thumbnailLeft = 0.; @@ -147,12 +150,13 @@ rpl::producer<> List::loadMoreRequests() const { void List::requestExpanded(bool expanded) { if (_expanded != expanded) { _expanded = expanded; - _expandedAnimation.start( - [=] { checkForFullState(); update(); }, - _expanded ? 0. : 1., - _expanded ? 1. : 0., - st::slideWrapDuration, - anim::sineInOut); + const auto from = _expanded ? 0. : 1.; + const auto till = _expanded ? 1. : 0.; + _expandedAnimation.start([=] { + checkForFullState(); + update(); + _collapsedGeometryChanged.fire({}); + }, from, till, st::slideWrapDuration, anim::sineInOut); } _toggleExpandedRequests.fire_copy(_expanded); } @@ -185,13 +189,15 @@ void List::updateExpanding(int expandingHeight, int expandedHeight) { } List::Layout List::computeLayout() { + updateExpanding( + _lastExpandedHeight * _expandCatchUpAnimation.value(1.), + _st.full.height); + return computeLayout(_expandedAnimation.value(_expanded ? 1. : 0.)); +} + +List::Layout List::computeLayout(float64 expanded) const { const auto &st = _st.small; const auto &full = _st.full; - const auto use = _lastExpandedHeight - * _expandCatchUpAnimation.value(1.); - updateExpanding(use, full.height); - - const auto expanded = _expandedAnimation.value(_expanded ? 1. : 0.); const auto expandedRatio = _lastRatio; const auto collapsedRatio = expandedRatio * kFrictionRatio; const auto ratio = expandedRatio * expanded @@ -234,6 +240,13 @@ List::Layout List::computeLayout() { const auto photoLeft = lerp(st.photoLeft, full.photoLeft); return Layout{ .itemsCount = itemsCount, + .geometryShift = QPointF( + (_state == State::Changing + ? (lerp(_changingGeometryFrom.x(), _geometryFull.x()) - x()) + : 0.), + (_state == State::Changing + ? (lerp(_changingGeometryFrom.y(), _geometryFull.y()) - y()) + : 0.)), .expandedRatio = expandedRatio, .ratio = ratio, .thumbnailLeft = thumbnailLeft, @@ -287,15 +300,7 @@ void List::paintEvent(QPaintEvent *e) { auto p = QPainter(this); if (_state == State::Changing) { - const auto left = anim::interpolate( - _changingGeometryFrom.x(), - _geometryFull.x(), - layout.ratio); - const auto top = anim::interpolate( - _changingGeometryFrom.y(), - _geometryFull.y(), - layout.ratio); - p.translate(QPoint(left, top) - pos()); + p.translate(layout.geometryShift); } const auto drawSmall = (expandRatio < 1.); @@ -672,6 +677,28 @@ void List::setLayoutConstraints( update(); } +List::CollapsedGeometry List::collapsedGeometryCurrent() const { + const auto expanded = _expandedAnimation.value(_expanded ? 1. : 0.); + if (expanded == 1.) { + return { QRect(), 1. }; + } + const auto layout = computeLayout(0.); + const auto small = countSmallGeometry(); + const auto index = layout.smallSkip - layout.startIndexSmall; + const auto shift = x() + layout.geometryShift.x(); + const auto left = int(base::SafeRound( + shift + layout.left + layout.single * index)); + const auto width = small.x() + small.width() - left; + return { + QRect(left, small.y(), width, small.height()), + expanded, + }; +} + +rpl::producer<> List::collapsedGeometryChanged() const { + return _collapsedGeometryChanged.events(); +} + void List::updateGeometry() { switch (_state) { case State::Small: setGeometry(countSmallGeometry()); break; @@ -686,7 +713,7 @@ void List::updateGeometry() { QRect List::countSmallGeometry() const { const auto &st = _st.small; - const auto layout = const_cast(this)->computeLayout(); + const auto layout = computeLayout(0.); const auto count = layout.endIndexSmall - std::max(layout.startIndexSmall, layout.smallSkip); const auto width = st.left diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_stories_list.h b/Telegram/SourceFiles/dialogs/ui/dialogs_stories_list.h index 85d7fd5e8..d0ecc1428 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_stories_list.h +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_stories_list.h @@ -70,6 +70,12 @@ public: QPoint positionSmall, style::align alignSmall, QRect geometryFull = QRect()); + struct CollapsedGeometry { + QRect geometry; + float64 expanded = 0.; + }; + [[nodiscard]] CollapsedGeometry collapsedGeometryCurrent() const; + [[nodiscard]] rpl::producer<> collapsedGeometryChanged() const; [[nodiscard]] bool empty() const { return _empty.current(); @@ -130,6 +136,7 @@ private: void updateExpanding(int expandingHeight, int expandedHeight); [[nodiscard]] Layout computeLayout(); + [[nodiscard]] Layout computeLayout(float64 expanded) const; const style::DialogsStoriesList &_st; Content _content; @@ -139,6 +146,7 @@ private: rpl::event_stream _toggleExpandedRequests; rpl::event_stream<> _entered; rpl::event_stream<> _loadMoreRequests; + rpl::event_stream<> _collapsedGeometryChanged; QPoint _positionSmall; style::align _alignSmall = {};