Added scroll support while dragging gift in gifts section.

This commit is contained in:
23rd
2025-09-28 22:36:35 +03:00
committed by John Preston
parent d1c98eb22a
commit cc2f459f26
@@ -36,6 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/scroll_area.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/ui_utility.h"
#include "ui/effects/animations.h"
#include "lang/lang_keys.h"
#include "main/main_app_config.h"
#include "main/main_session.h"
@@ -55,6 +56,7 @@ namespace {
constexpr auto kPreloadPages = 2;
constexpr auto kPerPage = 50;
constexpr auto kScrollFactor = 0.05;
[[nodiscard]] GiftDescriptor DescriptorForGift(
not_null<PeerData*> to,
@@ -108,7 +110,8 @@ public:
QWidget *parent,
not_null<Window::SessionController*> window,
not_null<PeerData*> peer,
rpl::producer<Descriptor> descriptor);
rpl::producer<Descriptor> descriptor,
Ui::ScrollArea *scroll = nullptr);
[[nodiscard]] not_null<PeerData*> peer() const {
return _peer;
@@ -181,6 +184,7 @@ public:
not_null<Window::SessionController*> window,
not_null<PeerData*> peer,
rpl::producer<Descriptor> descriptor,
Ui::ScrollArea *scroll,
int addingToCollectionId,
Entries all);
@@ -227,6 +231,7 @@ private:
const not_null<Window::SessionController*> _window;
const not_null<PeerData*> _peer;
Ui::ScrollArea * const _scroll;
const int _addingToCollectionId = 0;
const GiftButtonMode _mode;
@@ -272,6 +277,7 @@ private:
base::flat_map<int, ShiftAnimation> _shiftAnimations;
int _selected = -1;
Ui::Animations::Basic _scrollAnimation;
base::unique_qptr<Ui::PopupMenu> _menu;
protected:
@@ -279,6 +285,9 @@ protected:
private:
void cancelDragging();
void updateScrollCallback();
void checkForScrollAnimation();
[[nodiscard]] int deltaFromEdge();
};
@@ -286,12 +295,14 @@ InnerWidget::InnerWidget(
QWidget *parent,
not_null<Window::SessionController*> window,
not_null<PeerData*> peer,
rpl::producer<Descriptor> descriptor)
rpl::producer<Descriptor> descriptor,
Ui::ScrollArea *scroll)
: InnerWidget(
parent,
window,
peer,
std::move(descriptor),
scroll,
0,
{ .total = peer->peerGiftsCount() }) {
}
@@ -301,11 +312,13 @@ InnerWidget::InnerWidget(
not_null<Window::SessionController*> window,
not_null<PeerData*> peer,
rpl::producer<Descriptor> descriptor,
Ui::ScrollArea *scroll,
int addingToCollectionId,
Entries all)
: BoxContentDivider(parent)
, _window(window)
, _peer(peer)
, _scroll(scroll)
, _addingToCollectionId(addingToCollectionId)
, _mode(_addingToCollectionId
? GiftButtonMode::Selection
@@ -319,7 +332,8 @@ InnerWidget::InnerWidget(
.peer = _peer,
.collectionId = addingToCollectionId,
})
, _api(&_peer->session().mtp()) {
, _api(&_peer->session().mtp())
, _scrollAnimation([=] { updateScrollCallback(); }) {
_singleMin = _delegate.buttonSize();
if (peer->canManageGifts()) {
@@ -1243,6 +1257,7 @@ void InnerWidget::editCollectionGifts(int id) {
_window,
_peer,
state->descriptor.value(),
nullptr,
id,
(_all.filter == Filter()) ? _all : Entries()),
style::margins());
@@ -1871,6 +1886,8 @@ void InnerWidget::mouseMoveEvent(QMouseEvent *e) {
update();
}
checkForScrollAnimation();
}
void InnerWidget::mouseReleaseEvent(QMouseEvent *e) {
@@ -2100,6 +2117,7 @@ void InnerWidget::cancelDragging() {
if (mouseGrabber() == this) {
releaseMouse();
}
_scrollAnimation.stop();
_dragging = {};
_shiftAnimations.clear();
if (_draggedView) {
@@ -2108,6 +2126,56 @@ void InnerWidget::cancelDragging() {
refreshButtons();
}
void InnerWidget::updateScrollCallback() {
if (!_scroll) {
return;
}
const auto delta = deltaFromEdge();
const auto oldTop = _scroll->scrollTop();
_scroll->scrollToY(oldTop + delta);
const auto newTop = _scroll->scrollTop();
if (newTop == 0 || newTop == _scroll->scrollTopMax()) {
_scrollAnimation.stop();
}
}
void InnerWidget::checkForScrollAnimation() {
const auto delta = deltaFromEdge();
if (!_scroll || !delta || _scrollAnimation.animating()) {
return;
}
_scrollAnimation.start();
}
int InnerWidget::deltaFromEdge() {
if (!_dragging.enabled || _dragging.index < 0 || !_scroll) {
return 0;
}
const auto mousePos = QCursor::pos();
const auto scrollGlobalRect = QRect(
_scroll->mapToGlobal(QPoint(0, 0)),
_scroll->size());
const auto scrollTop = scrollGlobalRect.top();
const auto scrollBottom = scrollGlobalRect.bottom();
const auto scrollZone = 50;
const auto topDistance = mousePos.y() - scrollTop;
const auto bottomDistance = scrollBottom - mousePos.y();
if (topDistance < scrollZone) {
const auto effectiveDistance = std::max(1, scrollZone - topDistance);
return -int(effectiveDistance * kScrollFactor);
} else if (bottomDistance < scrollZone) {
const auto effectiveDistance
= std::max(1, scrollZone - bottomDistance);
return int(effectiveDistance * kScrollFactor);
}
return 0;
}
Memento::Memento(not_null<Controller*> controller)
: ContentMemento(Tag{
controller->giftsPeer(),
@@ -2151,7 +2219,8 @@ Widget::Widget(QWidget *parent, not_null<Controller*> controller)
this,
controller->parentController(),
controller->giftsPeer(),
_descriptor.value()));
_descriptor.value(),
scroll()));
_emptyCollectionShown = _inner->collectionEmptyValue();
_inner->notifyEnabled(
) | rpl::take(1) | rpl::start_with_next([=](bool enabled) {