Support touchscreen pinned chats reordering.

This commit is contained in:
John Preston 2024-05-30 23:22:03 +04:00
parent 4df5372dab
commit 4953246c5d
3 changed files with 90 additions and 28 deletions

View file

@ -79,6 +79,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_window.h"
#include "styles/style_menu_icons.h"
#include <QtWidgets/QApplication>
namespace Dialogs {
namespace {
@ -1316,7 +1318,7 @@ void InnerWidget::paintSearchInTopic(
}
void InnerWidget::mouseMoveEvent(QMouseEvent *e) {
if (_chatPreviewTouchGlobal) {
if (_chatPreviewTouchGlobal || _touchDragStartGlobal) {
return;
}
const auto globalPosition = e->globalPos();
@ -1336,7 +1338,6 @@ void InnerWidget::mouseMoveEvent(QMouseEvent *e) {
void InnerWidget::cancelChatPreview() {
_chatPreviewTimer.cancel();
_chatPreviewWillBeFor = {};
_chatPreviewTouchLocal = {};
_chatPreviewTouchGlobal = {};
}
@ -1622,8 +1623,14 @@ void InnerWidget::checkReorderPinnedStart(QPoint localPosition) {
< style::ConvertScale(kStartReorderThreshold)) {
return;
}
cancelChatPreview();
_dragging = _pressed;
startReorderPinned(localPosition);
}
void InnerWidget::startReorderPinned(QPoint localPosition) {
Expects(_dragging != nullptr);
cancelChatPreview();
if (updateReorderIndexGetCount() < 2) {
_dragging = nullptr;
} else {
@ -1682,6 +1689,7 @@ void InnerWidget::finishReorderPinned() {
if (wasDragging) {
savePinnedOrder();
_dragging = nullptr;
_touchDragStartGlobal = {};
}
_draggingIndex = -1;
@ -1694,6 +1702,22 @@ void InnerWidget::finishReorderPinned() {
}
}
bool InnerWidget::finishReorderOnRelease() {
if (!_dragging) {
return false;
}
updateReorderIndexGetCount();
if (_draggingIndex >= 0) {
_pinnedRows[_draggingIndex].yadd.start(0.);
_pinnedRows[_draggingIndex].animStartTime = crl::now();
if (!_pinnedShiftAnimation.animating()) {
_pinnedShiftAnimation.start();
}
}
finishReorderPinned();
return true;
}
void InnerWidget::stopReorderPinned() {
_pinnedShiftAnimation.stop();
finishReorderPinned();
@ -1845,18 +1869,7 @@ void InnerWidget::mousePressReleased(
_chatPreviewTimer.cancel();
_pressButton = Qt::NoButton;
auto wasDragging = (_dragging != nullptr);
if (wasDragging) {
updateReorderIndexGetCount();
if (_draggingIndex >= 0) {
_pinnedRows[_draggingIndex].yadd.start(0.);
_pinnedRows[_draggingIndex].animStartTime = crl::now();
if (!_pinnedShiftAnimation.animating()) {
_pinnedShiftAnimation.start();
}
}
finishReorderPinned();
}
const auto wasDragging = finishReorderOnRelease();
auto collapsedPressed = _collapsedPressed;
setCollapsedPressed(-1);
@ -2547,14 +2560,14 @@ void InnerWidget::parentGeometryChanged() {
}
}
void InnerWidget::processTouchEvent(not_null<QTouchEvent*> e) {
bool InnerWidget::processTouchEvent(not_null<QTouchEvent*> e) {
const auto point = e->touchPoints().empty()
? std::optional<QPoint>()
: e->touchPoints().front().screenPos().toPoint();
switch (e->type()) {
case QEvent::TouchBegin: {
if (!point) {
return;
return false;
}
selectByMouse(*point);
const auto onlyUserpic = true;
@ -2562,24 +2575,69 @@ void InnerWidget::processTouchEvent(not_null<QTouchEvent*> e) {
_chatPreviewTouchGlobal = point;
_chatPreviewWillBeFor = computeChatPreviewRow();
_chatPreviewTimer.callOnce(kChatPreviewDelay);
} else if (!_dragging) {
_touchDragStartGlobal = point;
_touchDragPinnedTimer.callOnce(QApplication::startDragTime());
}
} break;
case QEvent::TouchUpdate: {
if (!_chatPreviewTouchGlobal || !point) {
return;
if (!point) {
return false;
}
const auto delta = (*_chatPreviewTouchGlobal - *point);
if (delta.manhattanLength() > _st->photoSize) {
cancelChatPreview();
if (_chatPreviewTouchGlobal) {
const auto delta = (*_chatPreviewTouchGlobal - *point);
if (delta.manhattanLength() > _st->photoSize) {
cancelChatPreview();
}
}
if (_touchDragStartGlobal && _dragging) {
updateReorderPinned(mapFromGlobal(*point));
return _dragging != nullptr;
} else if (_touchDragStartGlobal) {
const auto delta = (*_touchDragStartGlobal - *point);
if (delta.manhattanLength() > QApplication::startDragDistance()) {
if (_touchDragPinnedTimer.isActive()) {
_touchDragPinnedTimer.cancel();
_touchDragStartGlobal = {};
_touchDragNowGlobal = {};
} else {
dragPinnedFromTouch();
}
} else {
_touchDragNowGlobal = point;
}
}
} break;
case QEvent::TouchEnd:
case QEvent::TouchCancel: if (_chatPreviewTouchGlobal) {
cancelChatPreview();
case QEvent::TouchCancel: {
if (_chatPreviewTouchGlobal) {
cancelChatPreview();
}
if (_touchDragStartGlobal) {
_touchDragStartGlobal = {};
return finishReorderOnRelease();
}
} break;
}
return false;
}
void InnerWidget::dragPinnedFromTouch() {
Expects(_touchDragStartGlobal.has_value());
const auto global = *_touchDragStartGlobal;
_touchDragPinnedTimer.cancel();
selectByMouse(global);
if (!_selected || _dragging || _state != WidgetState::Default) {
return;
}
_dragStart = mapFromGlobal(global);
_dragging = _selected;
const auto now = mapFromGlobal(_touchDragNowGlobal.value_or(global));
startReorderPinned(now);
updateReorderPinned(now);
}
void InnerWidget::applySearchState(SearchState state) {

View file

@ -174,7 +174,7 @@ public:
void parentGeometryChanged();
void processTouchEvent(not_null<QTouchEvent*> e);
bool processTouchEvent(not_null<QTouchEvent*> e);
[[nodiscard]] rpl::producer<> touchCancelRequests() const {
return _touchCancelRequests.events();
}
@ -404,15 +404,18 @@ private:
[[nodiscard]] const std::vector<Key> &pinnedChatsOrder() const;
void checkReorderPinnedStart(QPoint localPosition);
void startReorderPinned(QPoint localPosition);
int updateReorderIndexGetCount();
bool updateReorderPinned(QPoint localPosition);
void finishReorderPinned();
bool finishReorderOnRelease();
void stopReorderPinned();
int countPinnedIndex(Row *ofRow);
void savePinnedOrder();
bool pinnedShiftAnimationCallback(crl::time now);
void handleChatListEntryRefreshes();
void moveCancelSearchButtons();
void dragPinnedFromTouch();
void saveChatsFilterScrollState(FilterId filterId);
void restoreChatsFilterScrollState(FilterId filterId);
@ -525,8 +528,10 @@ private:
base::Timer _chatPreviewTimer;
Key _chatPreviewWillBeFor;
Key _chatPreviewKey;
std::optional<QPoint> _chatPreviewTouchLocal;
std::optional<QPoint> _chatPreviewTouchGlobal;
base::Timer _touchDragPinnedTimer;
std::optional<QPoint> _touchDragStartGlobal;
std::optional<QPoint> _touchDragNowGlobal;
rpl::event_stream<> _touchCancelRequests;
rpl::variable<ChildListShown> _childListShown;

View file

@ -658,8 +658,7 @@ void Widget::setupScrollUpButton() {
void Widget::setupTouchChatPreview() {
_scroll->setCustomTouchProcess([=](not_null<QTouchEvent*> e) {
_inner->processTouchEvent(e);
return false;
return _inner->processTouchEvent(e);
});
_inner->touchCancelRequests() | rpl::start_with_next([=] {
QTouchEvent ev(QEvent::TouchCancel);