Improve lock/unlock icon behavior.

This commit is contained in:
John Preston 2023-07-13 20:49:08 +04:00
parent 5d234d3103
commit 5368507259
5 changed files with 111 additions and 33 deletions

View file

@ -221,19 +221,20 @@ dialogsMenuToggleUnreadMuted: icon {
dialogsLock: IconButton(dialogsMenuToggle) { dialogsLock: IconButton(dialogsMenuToggle) {
icon: icon {{ "dialogs/dialogs_lock", dialogsMenuIconFg }}; icon: icon {{ "dialogs/dialogs_lock", dialogsMenuIconFg }};
iconOver: icon {{ "dialogs/dialogs_lock", dialogsMenuIconFgOver }}; iconOver: icon {{ "dialogs/dialogs_lock", dialogsMenuIconFgOver }};
ripple: emptyRippleAnimation;
} }
dialogsUnlockIcon: icon {{ "dialogs/dialogs_unlock", dialogsMenuIconFg }}; dialogsUnlockIcon: icon {{ "dialogs/dialogs_unlock", dialogsMenuIconFg }};
dialogsUnlockIconOver: icon {{ "dialogs/dialogs_unlock", dialogsMenuIconFgOver }}; dialogsUnlockIconOver: icon {{ "dialogs/dialogs_unlock", dialogsMenuIconFgOver }};
dialogsCalendar: IconButton { dialogsCalendar: IconButton {
width: 29px; width: 32px;
height: 32px; height: 35px;
icon: icon {{ "dialogs/dialogs_calendar", dialogsMenuIconFg }}; icon: icon {{ "dialogs/dialogs_calendar", dialogsMenuIconFg }};
iconOver: icon {{ "dialogs/dialogs_calendar", dialogsMenuIconFgOver }}; iconOver: icon {{ "dialogs/dialogs_calendar", dialogsMenuIconFgOver }};
iconPosition: point(0px, 5px); iconPosition: point(1px, 6px);
} }
dialogsSearchFrom: IconButton(dialogsCalendar) { dialogsSearchFrom: IconButton(dialogsCalendar) {
width: 26px; width: 29px;
icon: icon {{ "dialogs/dialogs_search_from", dialogsMenuIconFg }}; icon: icon {{ "dialogs/dialogs_search_from", dialogsMenuIconFg }};
iconOver: icon {{ "dialogs/dialogs_search_from", dialogsMenuIconFgOver }}; iconOver: icon {{ "dialogs/dialogs_search_from", dialogsMenuIconFgOver }};
} }
@ -276,12 +277,12 @@ dialogsCancelSearchInPeer: IconButton(dialogsMenuToggle) {
rippleAreaSize: 34px; rippleAreaSize: 34px;
} }
dialogsCancelSearch: CrossButton { dialogsCancelSearch: CrossButton {
width: 32px; width: 35px;
height: 32px; height: 35px;
cross: CrossAnimation { cross: CrossAnimation {
size: 32px; size: 35px;
skip: 10px; skip: 12px;
stroke: 1.5; stroke: 1.5;
minScale: 0.3; minScale: 0.3;
} }

View file

@ -814,14 +814,20 @@ void Widget::setupStories() {
using Phase = Ui::ElasticScrollMovement; using Phase = Ui::ElasticScrollMovement;
_stories->setExpandedHeight( _stories->setExpandedHeight(
_aboveScrollAdded, _aboveScrollAdded,
(movement == Phase::Momentum || movement == Phase::Returning) ((movement == Phase::Momentum || movement == Phase::Returning)
&& (explicitlyExpanded < above)); && (explicitlyExpanded < above)));
if (position.overscroll > 0 if (position.overscroll > 0
|| (position.value || (position.value
> (_storiesExplicitExpandScrollTop > (_storiesExplicitExpandScrollTop
+ st::dialogsRowHeight))) { + st::dialogsRowHeight))) {
storiesToggleExplicitExpand(false); storiesToggleExplicitExpand(false);
} }
updateLockUnlockPosition();
}, lifetime());
_stories->collapsedGeometryChanged(
) | rpl::start_with_next([=] {
updateLockUnlockPosition();
}, lifetime()); }, lifetime());
_stories->clicks( _stories->clicks(
@ -857,6 +863,10 @@ void Widget::setupStories() {
_stories->emptyValue() | rpl::skip(1) | rpl::start_with_next([=] { _stories->emptyValue() | rpl::skip(1) | rpl::start_with_next([=] {
updateStoriesVisibility(); updateStoriesVisibility();
}, lifetime()); }, lifetime());
_stories->widthValue() | rpl::start_with_next([=] {
updateLockUnlockPosition();
}, lifetime());
} }
void Widget::storiesToggleExplicitExpand(bool expand) { void Widget::storiesToggleExplicitExpand(bool expand) {
@ -977,6 +987,23 @@ void Widget::updateControlsVisibility(bool fast) {
if (_childList && _filter->hasFocus()) { if (_childList && _filter->hasFocus()) {
setInnerFocus(); 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( void Widget::changeOpenedSubsection(
@ -1388,6 +1415,8 @@ void Widget::updateStoriesVisibility() {
if (_aboveScrollAdded > 0 && _updateScrollGeometryCached) { if (_aboveScrollAdded > 0 && _updateScrollGeometryCached) {
_updateScrollGeometryCached(); _updateScrollGeometryCached();
} }
updateLockUnlockVisibility();
updateLockUnlockPosition();
} }
} }
@ -2253,6 +2282,7 @@ void Widget::applyFilterUpdate(bool force) {
_cancelSearch->toggle(!filterText.isEmpty(), anim::type::normal); _cancelSearch->toggle(!filterText.isEmpty(), anim::type::normal);
updateLoadMoreChatsVisibility(); updateLoadMoreChatsVisibility();
updateJumpToDateVisibility(); updateJumpToDateVisibility();
updateLockUnlockPosition();
if (filterText.isEmpty()) { if (filterText.isEmpty()) {
_peerSearchCache.clear(); _peerSearchCache.clear();
@ -2458,6 +2488,7 @@ bool Widget::setSearchInChat(Key chat, PeerData *from) {
updateSearchFromVisibility(); updateSearchFromVisibility();
clearSearchCache(); clearSearchCache();
} }
updateLockUnlockPosition();
if (_searchInChat && _layout == Layout::Main) { if (_searchInChat && _layout == Layout::Main) {
controller()->closeFolder(); controller()->closeFolder();
} }
@ -2580,9 +2611,18 @@ void Widget::updateLockUnlockVisibility() {
if (_showAnimation) { if (_showAnimation) {
return; 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) { if (_lockUnlock->isHidden() != hidden) {
_lockUnlock->setVisible(!hidden); _lockUnlock->setVisible(!hidden);
if (!hidden) {
updateLockUnlockPosition();
}
updateControlsGeometry(); updateControlsGeometry();
} }
} }
@ -2685,7 +2725,6 @@ void Widget::updateControlsGeometry() {
_searchForNarrowFilters->moveToLeft(searchLeft, st::dialogsFilterPadding.y()); _searchForNarrowFilters->moveToLeft(searchLeft, st::dialogsFilterPadding.y());
auto right = filterLeft + filterWidth; auto right = filterLeft + filterWidth;
_lockUnlock->moveToLeft(right + st::dialogsFilterPadding.x(), st::dialogsFilterPadding.y());
_cancelSearch->moveToLeft(right - _cancelSearch->width(), _filter->y()); _cancelSearch->moveToLeft(right - _cancelSearch->width(), _filter->y());
right -= _jumpToDate->width(); _jumpToDate->moveToLeft(right, _filter->y()); right -= _jumpToDate->width(); _jumpToDate->moveToLeft(right, _filter->y());
right -= _chooseFromUser->width(); _chooseFromUser->moveToLeft(right, _filter->y()); right -= _chooseFromUser->width(); _chooseFromUser->moveToLeft(right, _filter->y());
@ -2709,6 +2748,8 @@ void Widget::updateControlsGeometry() {
st::lineWidth); st::lineWidth);
} }
updateLockUnlockPosition();
auto bottomSkip = 0; auto bottomSkip = 0;
const auto putBottomButton = [&](auto &button) { const auto putBottomButton = [&](auto &button) {
if (button && !button->isHidden()) { if (button && !button->isHidden()) {

View file

@ -224,6 +224,7 @@ private:
void updateScrollUpVisibility(); void updateScrollUpVisibility();
void startScrollUpButtonAnimation(bool shown); void startScrollUpButtonAnimation(bool shown);
void updateScrollUpPosition(); void updateScrollUpPosition();
void updateLockUnlockPosition();
MTP::Sender _api; MTP::Sender _api;

View file

@ -15,6 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <QtWidgets/QApplication> #include <QtWidgets/QApplication>
#include "base/debug_log.h"
namespace Dialogs::Stories { namespace Dialogs::Stories {
namespace { namespace {
@ -36,6 +38,7 @@ constexpr auto kExpandCatchUpDuration = crl::time(200);
struct List::Layout { struct List::Layout {
int itemsCount = 0; int itemsCount = 0;
QPointF geometryShift;
float64 expandedRatio = 0.; float64 expandedRatio = 0.;
float64 ratio = 0.; float64 ratio = 0.;
float64 thumbnailLeft = 0.; float64 thumbnailLeft = 0.;
@ -147,12 +150,13 @@ rpl::producer<> List::loadMoreRequests() const {
void List::requestExpanded(bool expanded) { void List::requestExpanded(bool expanded) {
if (_expanded != expanded) { if (_expanded != expanded) {
_expanded = expanded; _expanded = expanded;
_expandedAnimation.start( const auto from = _expanded ? 0. : 1.;
[=] { checkForFullState(); update(); }, const auto till = _expanded ? 1. : 0.;
_expanded ? 0. : 1., _expandedAnimation.start([=] {
_expanded ? 1. : 0., checkForFullState();
st::slideWrapDuration, update();
anim::sineInOut); _collapsedGeometryChanged.fire({});
}, from, till, st::slideWrapDuration, anim::sineInOut);
} }
_toggleExpandedRequests.fire_copy(_expanded); _toggleExpandedRequests.fire_copy(_expanded);
} }
@ -185,13 +189,15 @@ void List::updateExpanding(int expandingHeight, int expandedHeight) {
} }
List::Layout List::computeLayout() { 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 &st = _st.small;
const auto &full = _st.full; 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 expandedRatio = _lastRatio;
const auto collapsedRatio = expandedRatio * kFrictionRatio; const auto collapsedRatio = expandedRatio * kFrictionRatio;
const auto ratio = expandedRatio * expanded const auto ratio = expandedRatio * expanded
@ -234,6 +240,13 @@ List::Layout List::computeLayout() {
const auto photoLeft = lerp(st.photoLeft, full.photoLeft); const auto photoLeft = lerp(st.photoLeft, full.photoLeft);
return Layout{ return Layout{
.itemsCount = itemsCount, .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, .expandedRatio = expandedRatio,
.ratio = ratio, .ratio = ratio,
.thumbnailLeft = thumbnailLeft, .thumbnailLeft = thumbnailLeft,
@ -287,15 +300,7 @@ void List::paintEvent(QPaintEvent *e) {
auto p = QPainter(this); auto p = QPainter(this);
if (_state == State::Changing) { if (_state == State::Changing) {
const auto left = anim::interpolate( p.translate(layout.geometryShift);
_changingGeometryFrom.x(),
_geometryFull.x(),
layout.ratio);
const auto top = anim::interpolate(
_changingGeometryFrom.y(),
_geometryFull.y(),
layout.ratio);
p.translate(QPoint(left, top) - pos());
} }
const auto drawSmall = (expandRatio < 1.); const auto drawSmall = (expandRatio < 1.);
@ -672,6 +677,28 @@ void List::setLayoutConstraints(
update(); 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() { void List::updateGeometry() {
switch (_state) { switch (_state) {
case State::Small: setGeometry(countSmallGeometry()); break; case State::Small: setGeometry(countSmallGeometry()); break;
@ -686,7 +713,7 @@ void List::updateGeometry() {
QRect List::countSmallGeometry() const { QRect List::countSmallGeometry() const {
const auto &st = _st.small; const auto &st = _st.small;
const auto layout = const_cast<List*>(this)->computeLayout(); const auto layout = computeLayout(0.);
const auto count = layout.endIndexSmall const auto count = layout.endIndexSmall
- std::max(layout.startIndexSmall, layout.smallSkip); - std::max(layout.startIndexSmall, layout.smallSkip);
const auto width = st.left const auto width = st.left

View file

@ -70,6 +70,12 @@ public:
QPoint positionSmall, QPoint positionSmall,
style::align alignSmall, style::align alignSmall,
QRect geometryFull = QRect()); QRect geometryFull = QRect());
struct CollapsedGeometry {
QRect geometry;
float64 expanded = 0.;
};
[[nodiscard]] CollapsedGeometry collapsedGeometryCurrent() const;
[[nodiscard]] rpl::producer<> collapsedGeometryChanged() const;
[[nodiscard]] bool empty() const { [[nodiscard]] bool empty() const {
return _empty.current(); return _empty.current();
@ -130,6 +136,7 @@ private:
void updateExpanding(int expandingHeight, int expandedHeight); void updateExpanding(int expandingHeight, int expandedHeight);
[[nodiscard]] Layout computeLayout(); [[nodiscard]] Layout computeLayout();
[[nodiscard]] Layout computeLayout(float64 expanded) const;
const style::DialogsStoriesList &_st; const style::DialogsStoriesList &_st;
Content _content; Content _content;
@ -139,6 +146,7 @@ private:
rpl::event_stream<bool> _toggleExpandedRequests; rpl::event_stream<bool> _toggleExpandedRequests;
rpl::event_stream<> _entered; rpl::event_stream<> _entered;
rpl::event_stream<> _loadMoreRequests; rpl::event_stream<> _loadMoreRequests;
rpl::event_stream<> _collapsedGeometryChanged;
QPoint _positionSmall; QPoint _positionSmall;
style::align _alignSmall = {}; style::align _alignSmall = {};