diff --git a/lib/frontend/screens/chats/chat_list_screen.dart b/lib/frontend/screens/chats/chat_list_screen.dart index 6f8462e..0dabd5c 100644 --- a/lib/frontend/screens/chats/chat_list_screen.dart +++ b/lib/frontend/screens/chats/chat_list_screen.dart @@ -17,9 +17,11 @@ import '../../../main.dart' show api; class _StoriesScrollPhysics extends BouncingScrollPhysics { final bool Function() blockPositive; + final bool Function() allowPullOverscrollTop; const _StoriesScrollPhysics({ required this.blockPositive, + required this.allowPullOverscrollTop, ScrollPhysics? parent, }) : super(parent: parent); @@ -27,6 +29,7 @@ class _StoriesScrollPhysics extends BouncingScrollPhysics { _StoriesScrollPhysics applyTo(ScrollPhysics? ancestor) { return _StoriesScrollPhysics( blockPositive: blockPositive, + allowPullOverscrollTop: allowPullOverscrollTop, parent: buildParent(ancestor), ); } @@ -36,6 +39,11 @@ class _StoriesScrollPhysics extends BouncingScrollPhysics { if (blockPositive() && value > 0.0) { return value - max(0.0, position.pixels); } + if (!allowPullOverscrollTop() && + value < position.minScrollExtent && + position.pixels <= position.minScrollExtent) { + return value - position.minScrollExtent; + } return super.applyBoundaryConditions(position, value); } } @@ -69,6 +77,7 @@ class _ChatListScreenState extends State double _closeAnimBegin = 0.0; bool _storiesAnimClosing = false; bool _storiesDockedOpen = false; + bool _storiesOverscrollRevealArmed = true; DateTime _storiesRevealLayoutSettleUntil = DateTime.fromMillisecondsSinceEpoch(0); ProfileData? _profile; @@ -113,6 +122,15 @@ class _ChatListScreenState extends State return false; } + bool _allowStoriesPullOverscrollTop() { + if (_storiesDockedOpen || + _storiesRevealController.isAnimating || + _pullRatio > 0) { + return true; + } + return _storiesOverscrollRevealArmed; + } + late AnimationController _shimmerController; @override @@ -267,6 +285,7 @@ class _ChatListScreenState extends State _pullRatio = 0.0; _storiesDockedOpen = false; _storiesAnimClosing = false; + _storiesOverscrollRevealArmed = true; } else { _pullRatio = 1.0; _storiesDockedOpen = true; @@ -320,6 +339,7 @@ class _ChatListScreenState extends State _pullRatio = 0.0; _storiesDockedOpen = false; _storiesAnimClosing = false; + _storiesOverscrollRevealArmed = true; }); return; } @@ -335,6 +355,15 @@ class _ChatListScreenState extends State if (_currentNavIndex != 0) return false; if (!_scrollController.hasClients) return false; + if (n is ScrollEndNotification) { + if (_scrollController.offset <= 0.5) { + setState(() { + _storiesOverscrollRevealArmed = true; + }); + } + return false; + } + if (n is OverscrollNotification && n.overscroll > 0) { if ((_storiesDockedOpen || _storiesRevealController.isAnimating || @@ -375,6 +404,9 @@ class _ChatListScreenState extends State } if (offset < 0) { + if (!_allowStoriesPullOverscrollTop()) { + return; + } final dragRatio = (offset.abs() / 80.0).clamp(0.0, 1.0); if (_storiesRevealController.isAnimating) { return; @@ -397,9 +429,16 @@ class _ChatListScreenState extends State if (_storiesDockedOpen || _storiesRevealController.isAnimating) { return; } - if (_pullRatio > 0) { + final disarm = offset > 3 && _storiesOverscrollRevealArmed; + final clearPull = _pullRatio > 0; + if (disarm || clearPull) { setState(() { - _pullRatio = 0.0; + if (disarm) { + _storiesOverscrollRevealArmed = false; + } + if (clearPull) { + _pullRatio = 0.0; + } }); } } @@ -735,7 +774,9 @@ class _ChatListScreenState extends State } if (_scrollController.hasClients && _scrollController.offset <= 0) { if (pointerSignal.scrollDelta.dy < 0) { - _startStoriesAutoReveal(max(_pullRatio, 0.18)); + if (_allowStoriesPullOverscrollTop()) { + _startStoriesAutoReveal(max(_pullRatio, 0.18)); + } } else if (pointerSignal.scrollDelta.dy > 0 && _pullRatio > 0) { _startStoriesAutoClose(); } @@ -753,6 +794,7 @@ class _ChatListScreenState extends State controller: _scrollController, physics: _StoriesScrollPhysics( blockPositive: _shouldBlockPositiveScroll, + allowPullOverscrollTop: _allowStoriesPullOverscrollTop, parent: const AlwaysScrollableScrollPhysics(), ), slivers: [