Support chat preview on touchscreens.

This commit is contained in:
John Preston 2024-05-30 22:33:24 +04:00
parent 40fbd415ef
commit 4df5372dab
5 changed files with 67 additions and 1 deletions

View file

@ -1316,6 +1316,9 @@ void InnerWidget::paintSearchInTopic(
}
void InnerWidget::mouseMoveEvent(QMouseEvent *e) {
if (_chatPreviewTouchGlobal) {
return;
}
const auto globalPosition = e->globalPos();
if (!_lastMousePosition) {
_lastMousePosition = globalPosition;
@ -1333,6 +1336,8 @@ void InnerWidget::mouseMoveEvent(QMouseEvent *e) {
void InnerWidget::cancelChatPreview() {
_chatPreviewTimer.cancel();
_chatPreviewWillBeFor = {};
_chatPreviewTouchLocal = {};
_chatPreviewTouchGlobal = {};
}
void InnerWidget::clearIrrelevantState() {
@ -2396,10 +2401,14 @@ void InnerWidget::fillArchiveSearchMenu(not_null<Ui::PopupMenu*> menu) {
void InnerWidget::showChatPreview(bool onlyUserpic) {
const auto key = base::take(_chatPreviewWillBeFor);
const auto touchGlobal = base::take(_chatPreviewTouchGlobal);
cancelChatPreview();
if (!pressShowsPreview(onlyUserpic) || key != computeChatPreviewRow()) {
return;
}
if (onlyUserpic && touchGlobal) {
_touchCancelRequests.fire({});
}
ClickHandler::unpressed();
mousePressReleased(QCursor::pos(), Qt::NoButton, Qt::NoModifier);
@ -2538,6 +2547,41 @@ void InnerWidget::parentGeometryChanged() {
}
}
void 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;
}
selectByMouse(*point);
const auto onlyUserpic = true;
if (pressShowsPreview(onlyUserpic)) {
_chatPreviewTouchGlobal = point;
_chatPreviewWillBeFor = computeChatPreviewRow();
_chatPreviewTimer.callOnce(kChatPreviewDelay);
}
} break;
case QEvent::TouchUpdate: {
if (!_chatPreviewTouchGlobal || !point) {
return;
}
const auto delta = (*_chatPreviewTouchGlobal - *point);
if (delta.manhattanLength() > _st->photoSize) {
cancelChatPreview();
}
} break;
case QEvent::TouchEnd:
case QEvent::TouchCancel: if (_chatPreviewTouchGlobal) {
cancelChatPreview();
} break;
}
}
void InnerWidget::applySearchState(SearchState state) {
if (_searchState == state) {
return;

View file

@ -174,6 +174,11 @@ public:
void parentGeometryChanged();
void processTouchEvent(not_null<QTouchEvent*> e);
[[nodiscard]] rpl::producer<> touchCancelRequests() const {
return _touchCancelRequests.events();
}
protected:
void visibleTopBottomUpdated(
int visibleTop,
@ -520,6 +525,9 @@ private:
base::Timer _chatPreviewTimer;
Key _chatPreviewWillBeFor;
Key _chatPreviewKey;
std::optional<QPoint> _chatPreviewTouchLocal;
std::optional<QPoint> _chatPreviewTouchGlobal;
rpl::event_stream<> _touchCancelRequests;
rpl::variable<ChildListShown> _childListShown;
float64 _narrowRatio = 0.;

View file

@ -473,6 +473,7 @@ Widget::Widget(
updateSearchFromVisibility(true);
setupSupportMode();
setupScrollUpButton();
setupTouchChatPreview();
const auto overscrollBg = [=] {
return anim::color(
@ -655,6 +656,18 @@ void Widget::setupScrollUpButton() {
updateScrollUpVisibility();
}
void Widget::setupTouchChatPreview() {
_scroll->setCustomTouchProcess([=](not_null<QTouchEvent*> e) {
_inner->processTouchEvent(e);
return false;
});
_inner->touchCancelRequests() | rpl::start_with_next([=] {
QTouchEvent ev(QEvent::TouchCancel);
ev.setTimestamp(crl::now());
QGuiApplication::sendEvent(_scroll, &ev);
}, _inner->lifetime());
}
void Widget::setupMoreChatsBar() {
if (_layout == Layout::Child) {
return;

View file

@ -179,6 +179,7 @@ private:
[[nodiscard]] const std::vector<Data::ReactionId> &searchInTags() const;
void setupSupportMode();
void setupTouchChatPreview();
void setupConnectingWidget();
void setupMainMenuToggle();
void setupMoreChatsBar();

@ -1 +1 @@
Subproject commit 495ea0af50da469fb30769ac2d78251e4279a746
Subproject commit 33aac93b160d4cd30119c8859de722e28512902b