mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-18 07:07:08 +02:00
Add touchscreen preview to recent / channels.
This commit is contained in:
parent
0fffeac8da
commit
a1049ec7ce
10 changed files with 154 additions and 24 deletions
|
@ -1556,10 +1556,12 @@ void PeerListContent::handleMouseMove(QPoint globalPosition) {
|
|||
if (_trackPressStart
|
||||
&& ((*_trackPressStart - globalPosition).manhattanLength()
|
||||
> QApplication::startDragDistance())) {
|
||||
_trackPressStart = std::nullopt;
|
||||
_trackPressStart = {};
|
||||
_controller->rowTrackPressCancel();
|
||||
}
|
||||
selectByMouse(globalPosition);
|
||||
if (!_controller->rowTrackPressSkipMouseSelection()) {
|
||||
selectByMouse(globalPosition);
|
||||
}
|
||||
}
|
||||
|
||||
void PeerListContent::pressLeftToContextMenu(bool shown) {
|
||||
|
@ -1571,13 +1573,24 @@ void PeerListContent::pressLeftToContextMenu(bool shown) {
|
|||
}
|
||||
}
|
||||
|
||||
bool PeerListContent::trackRowPressFromGlobal(QPoint globalPosition) {
|
||||
selectByMouse(globalPosition);
|
||||
if (const auto row = getRow(_selected.index)) {
|
||||
if (_controller->rowTrackPress(row)) {
|
||||
_trackPressStart = globalPosition;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PeerListContent::mousePressEvent(QMouseEvent *e) {
|
||||
_pressButton = e->button();
|
||||
selectByMouse(e->globalPos());
|
||||
setPressed(_selected);
|
||||
_trackPressStart = {};
|
||||
if (auto row = getRow(_selected.index)) {
|
||||
auto updateCallback = [this, row, hint = _selected.index] {
|
||||
if (const auto row = getRow(_selected.index)) {
|
||||
const auto updateCallback = [this, row, hint = _selected.index] {
|
||||
updateRow(row, hint);
|
||||
};
|
||||
if (_selected.element) {
|
||||
|
|
|
@ -347,7 +347,9 @@ public:
|
|||
virtual void peerListSortRows(Fn<bool(const PeerListRow &a, const PeerListRow &b)> compare) = 0;
|
||||
virtual int peerListPartitionRows(Fn<bool(const PeerListRow &a)> border) = 0;
|
||||
virtual std::shared_ptr<Main::SessionShow> peerListUiShow() = 0;
|
||||
|
||||
virtual void peerListPressLeftToContextMenu(bool shown) = 0;
|
||||
virtual bool peerListTrackRowPressFromGlobal(QPoint globalPosition) = 0;
|
||||
|
||||
template <typename PeerDataRange>
|
||||
void peerListAddSelectedPeers(PeerDataRange &&range) {
|
||||
|
@ -484,6 +486,9 @@ public:
|
|||
}
|
||||
virtual void rowTrackPressCancel() {
|
||||
}
|
||||
virtual bool rowTrackPressSkipMouseSelection() {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void loadMoreRows() {
|
||||
}
|
||||
|
@ -663,6 +668,7 @@ public:
|
|||
|
||||
void mouseLeftGeometry();
|
||||
void pressLeftToContextMenu(bool shown);
|
||||
bool trackRowPressFromGlobal(QPoint globalPosition);
|
||||
|
||||
void setSearchMode(PeerListSearchMode mode);
|
||||
void changeCheckState(
|
||||
|
@ -1000,9 +1006,13 @@ public:
|
|||
not_null<PeerListRow*> row,
|
||||
bool highlightRow,
|
||||
Fn<void(not_null<Ui::PopupMenu*>)> destroyed = nullptr) override;
|
||||
|
||||
void peerListPressLeftToContextMenu(bool shown) override {
|
||||
_content->pressLeftToContextMenu(shown);
|
||||
}
|
||||
bool peerListTrackRowPressFromGlobal(QPoint globalPosition) override {
|
||||
return _content->trackRowPressFromGlobal(globalPosition);
|
||||
}
|
||||
|
||||
protected:
|
||||
not_null<PeerListContent*> content() const {
|
||||
|
|
|
@ -1526,7 +1526,7 @@ void InnerWidget::mousePressEvent(QMouseEvent *e) {
|
|||
if (alt && showChatPreview()) {
|
||||
return;
|
||||
} else if (!alt && isUserpicPress()) {
|
||||
scheduleChatPreview();
|
||||
scheduleChatPreview(e->globalPos());
|
||||
}
|
||||
|
||||
if (base::in_range(_collapsedSelected, 0, _collapsedRows.size())) {
|
||||
|
@ -2440,12 +2440,16 @@ void InnerWidget::chatPreviewShown(bool shown, RowDescriptor row) {
|
|||
}
|
||||
}
|
||||
|
||||
bool InnerWidget::scheduleChatPreview() {
|
||||
bool InnerWidget::scheduleChatPreview(QPoint positionOverride) {
|
||||
const auto row = computeChatPreviewRow();
|
||||
const auto callback = crl::guard(this, [=](bool shown) {
|
||||
chatPreviewShown(shown, row);
|
||||
});
|
||||
_chatPreviewScheduled = _controller->scheduleChatPreview(row, callback);
|
||||
_chatPreviewScheduled = _controller->scheduleChatPreview(
|
||||
row,
|
||||
callback,
|
||||
nullptr,
|
||||
positionOverride);
|
||||
return _chatPreviewScheduled;
|
||||
}
|
||||
|
||||
|
@ -2544,8 +2548,7 @@ bool InnerWidget::processTouchEvent(not_null<QTouchEvent*> e) {
|
|||
return false;
|
||||
}
|
||||
selectByMouse(*point);
|
||||
const auto onlyUserpic = true;
|
||||
if (isUserpicPress() && scheduleChatPreview()) {
|
||||
if (isUserpicPressOnWide() && scheduleChatPreview(*point)) {
|
||||
_chatPreviewTouchGlobal = point;
|
||||
} else if (!_dragging) {
|
||||
_touchDragStartGlobal = point;
|
||||
|
|
|
@ -126,7 +126,7 @@ public:
|
|||
[[nodiscard]] bool isUserpicPress() const;
|
||||
[[nodiscard]] bool isUserpicPressOnWide() const;
|
||||
void cancelChatPreview();
|
||||
bool scheduleChatPreview();
|
||||
bool scheduleChatPreview(QPoint positionOverride);
|
||||
bool showChatPreview();
|
||||
void chatPreviewShown(bool shown, RowDescriptor row = {});
|
||||
bool chooseRow(
|
||||
|
|
|
@ -99,10 +99,17 @@ public:
|
|||
|
||||
bool rowTrackPress(not_null<PeerListRow*> row) override;
|
||||
void rowTrackPressCancel() override;
|
||||
bool rowTrackPressSkipMouseSelection() override;
|
||||
|
||||
bool processTouchEvent(not_null<QTouchEvent*> e);
|
||||
void setupTouchChatPreview(not_null<Ui::ElasticScroll*> scroll);
|
||||
|
||||
private:
|
||||
const not_null<Window::SessionController*> _window;
|
||||
|
||||
std::optional<QPoint> _chatPreviewTouchGlobal;
|
||||
rpl::event_stream<> _touchCancelRequests;
|
||||
|
||||
};
|
||||
|
||||
class RecentsController final : public ControllerWithPreviews {
|
||||
|
@ -426,22 +433,81 @@ bool ControllerWithPreviews::rowTrackPress(not_null<PeerListRow*> row) {
|
|||
delegate()->peerListPressLeftToContextMenu(shown);
|
||||
});
|
||||
if (base::IsAltPressed()) {
|
||||
_window->showChatPreview({ history, FullMsgId() }, callback);
|
||||
_window->showChatPreview(
|
||||
{ history, FullMsgId() },
|
||||
callback,
|
||||
nullptr,
|
||||
_chatPreviewTouchGlobal);
|
||||
return false;
|
||||
}
|
||||
const auto point = delegate()->peerListLastRowMousePosition();
|
||||
const auto &st = computeListSt().item;
|
||||
if (point && point->x() < st.photoPosition.x() + st.photoSize) {
|
||||
_window->scheduleChatPreview({ history, FullMsgId() }, callback);
|
||||
_window->scheduleChatPreview(
|
||||
{ history, FullMsgId() },
|
||||
callback,
|
||||
nullptr,
|
||||
_chatPreviewTouchGlobal);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ControllerWithPreviews::rowTrackPressCancel() {
|
||||
_chatPreviewTouchGlobal = {};
|
||||
_window->cancelScheduledPreview();
|
||||
}
|
||||
|
||||
bool ControllerWithPreviews::rowTrackPressSkipMouseSelection() {
|
||||
return _chatPreviewTouchGlobal.has_value();
|
||||
}
|
||||
|
||||
bool ControllerWithPreviews::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 false;
|
||||
}
|
||||
_chatPreviewTouchGlobal = point;
|
||||
if (!delegate()->peerListTrackRowPressFromGlobal(*point)) {
|
||||
_chatPreviewTouchGlobal = {};
|
||||
}
|
||||
} break;
|
||||
|
||||
case QEvent::TouchUpdate: {
|
||||
if (!point) {
|
||||
return false;
|
||||
}
|
||||
if (_chatPreviewTouchGlobal) {
|
||||
const auto delta = (*_chatPreviewTouchGlobal - *point);
|
||||
if (delta.manhattanLength() > computeListSt().item.photoSize) {
|
||||
rowTrackPressCancel();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case QEvent::TouchEnd:
|
||||
case QEvent::TouchCancel: {
|
||||
if (_chatPreviewTouchGlobal) {
|
||||
rowTrackPressCancel();
|
||||
}
|
||||
} break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ControllerWithPreviews::setupTouchChatPreview(
|
||||
not_null<Ui::ElasticScroll*> scroll) {
|
||||
_touchCancelRequests.events() | rpl::start_with_next([=] {
|
||||
QTouchEvent ev(QEvent::TouchCancel);
|
||||
ev.setTimestamp(crl::now());
|
||||
QGuiApplication::sendEvent(scroll, &ev);
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
RecentsController::RecentsController(
|
||||
not_null<Window::SessionController*> window,
|
||||
RecentPeersList list)
|
||||
|
@ -1030,6 +1096,7 @@ void Suggestions::setupChats() {
|
|||
}, _topPeers->lifetime());
|
||||
|
||||
_chatsScroll->setVisible(_tab.current() == Tab::Chats);
|
||||
_chatsScroll->setCustomTouchProcess(_recentProcessTouch);
|
||||
}
|
||||
|
||||
void Suggestions::handlePressForChatPreview(
|
||||
|
@ -1063,6 +1130,11 @@ void Suggestions::setupChannels() {
|
|||
anim::type::instant);
|
||||
|
||||
_channelsScroll->setVisible(_tab.current() == Tab::Channels);
|
||||
_channelsScroll->setCustomTouchProcess([=](not_null<QTouchEvent*> e) {
|
||||
const auto myChannels = _myChannelsProcessTouch(e);
|
||||
const auto recommendations = _recommendationsProcessTouch(e);
|
||||
return myChannels || recommendations;
|
||||
});
|
||||
}
|
||||
|
||||
void Suggestions::selectJump(Qt::Key direction, int pageSize) {
|
||||
|
@ -1371,6 +1443,9 @@ object_ptr<Ui::SlideWrap<>> Suggestions::setupRecentPeers(
|
|||
controller->setStyleOverrides(&st::recentPeersList);
|
||||
|
||||
_recentCount = controller->count();
|
||||
_recentProcessTouch = [=](not_null<QTouchEvent*> e) {
|
||||
return controller->processTouchEvent(e);
|
||||
};
|
||||
|
||||
controller->chosen(
|
||||
) | rpl::start_with_next([=](not_null<PeerData*> peer) {
|
||||
|
@ -1419,6 +1494,7 @@ object_ptr<Ui::SlideWrap<>> Suggestions::setupRecentPeers(
|
|||
|
||||
delegate->setContent(raw);
|
||||
controller->setDelegate(delegate);
|
||||
controller->setupTouchChatPreview(_chatsScroll.get());
|
||||
|
||||
return object_ptr<Ui::SlideWrap<>>(this, std::move(content));
|
||||
}
|
||||
|
@ -1474,6 +1550,9 @@ object_ptr<Ui::SlideWrap<>> Suggestions::setupMyChannels() {
|
|||
controller->setStyleOverrides(&st::recentPeersList);
|
||||
|
||||
_myChannelsCount = controller->count();
|
||||
_myChannelsProcessTouch = [=](not_null<QTouchEvent*> e) {
|
||||
return controller->processTouchEvent(e);
|
||||
};
|
||||
|
||||
controller->chosen(
|
||||
) | rpl::start_with_next([=](not_null<PeerData*> peer) {
|
||||
|
@ -1535,6 +1614,7 @@ object_ptr<Ui::SlideWrap<>> Suggestions::setupMyChannels() {
|
|||
|
||||
delegate->setContent(raw);
|
||||
controller->setDelegate(delegate);
|
||||
controller->setupTouchChatPreview(_channelsScroll.get());
|
||||
|
||||
return object_ptr<Ui::SlideWrap<>>(this, std::move(content));
|
||||
}
|
||||
|
@ -1549,6 +1629,9 @@ object_ptr<Ui::SlideWrap<>> Suggestions::setupRecommendations() {
|
|||
controller->setStyleOverrides(&st::recentPeersList);
|
||||
|
||||
_recommendationsCount = controller->count();
|
||||
_recommendationsProcessTouch = [=](not_null<QTouchEvent*> e) {
|
||||
return controller->processTouchEvent(e);
|
||||
};
|
||||
|
||||
_tab.value() | rpl::filter(
|
||||
rpl::mappers::_1 == Tab::Channels
|
||||
|
@ -1603,6 +1686,7 @@ object_ptr<Ui::SlideWrap<>> Suggestions::setupRecommendations() {
|
|||
|
||||
delegate->setContent(raw);
|
||||
controller->setDelegate(delegate);
|
||||
controller->setupTouchChatPreview(_channelsScroll.get());
|
||||
|
||||
return object_ptr<Ui::SlideWrap<>>(this, std::move(content));
|
||||
}
|
||||
|
|
|
@ -139,6 +139,7 @@ private:
|
|||
Fn<JumpResult(Qt::Key, int)> _recentSelectJump;
|
||||
Fn<uint64(QPoint)> _recentUpdateFromParentDrag;
|
||||
Fn<void()> _recentDragLeft;
|
||||
Fn<bool(not_null<QTouchEvent*>)> _recentProcessTouch;
|
||||
const not_null<Ui::SlideWrap<Ui::RpWidget>*> _recentPeers;
|
||||
const not_null<Ui::SlideWrap<Ui::RpWidget>*> _emptyRecent;
|
||||
|
||||
|
@ -150,6 +151,7 @@ private:
|
|||
Fn<JumpResult(Qt::Key, int)> _myChannelsSelectJump;
|
||||
Fn<uint64(QPoint)> _myChannelsUpdateFromParentDrag;
|
||||
Fn<void()> _myChannelsDragLeft;
|
||||
Fn<bool(not_null<QTouchEvent*>)> _myChannelsProcessTouch;
|
||||
const not_null<Ui::SlideWrap<Ui::RpWidget>*> _myChannels;
|
||||
|
||||
rpl::variable<int> _recommendationsCount;
|
||||
|
@ -157,6 +159,7 @@ private:
|
|||
Fn<JumpResult(Qt::Key, int)> _recommendationsSelectJump;
|
||||
Fn<uint64(QPoint)> _recommendationsUpdateFromParentDrag;
|
||||
Fn<void()> _recommendationsDragLeft;
|
||||
Fn<bool(not_null<QTouchEvent*>)> _recommendationsProcessTouch;
|
||||
const not_null<Ui::SlideWrap<Ui::RpWidget>*> _recommendations;
|
||||
|
||||
const not_null<Ui::SlideWrap<Ui::RpWidget>*> _emptyChannels;
|
||||
|
|
|
@ -34,7 +34,8 @@ ChatPreviewManager::ChatPreviewManager(
|
|||
bool ChatPreviewManager::show(
|
||||
Dialogs::RowDescriptor row,
|
||||
Fn<void(bool shown)> callback,
|
||||
QPointer<QWidget> parentOverride) {
|
||||
QPointer<QWidget> parentOverride,
|
||||
std::optional<QPoint> positionOverride) {
|
||||
cancelScheduled();
|
||||
_topicLifetime.destroy();
|
||||
if (const auto topic = row.key.topic()) {
|
||||
|
@ -94,7 +95,7 @@ bool ChatPreviewManager::show(
|
|||
if (callback) {
|
||||
callback(true);
|
||||
}
|
||||
_menu->popup(QCursor::pos());
|
||||
_menu->popup(positionOverride.value_or(QCursor::pos()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -102,7 +103,8 @@ bool ChatPreviewManager::show(
|
|||
bool ChatPreviewManager::schedule(
|
||||
Dialogs::RowDescriptor row,
|
||||
Fn<void(bool shown)> callback,
|
||||
QPointer<QWidget> parentOverride) {
|
||||
QPointer<QWidget> parentOverride,
|
||||
std::optional<QPoint> positionOverride) {
|
||||
cancelScheduled();
|
||||
_topicLifetime.destroy();
|
||||
if (const auto topic = row.key.topic()) {
|
||||
|
@ -116,17 +118,23 @@ bool ChatPreviewManager::schedule(
|
|||
_scheduled = std::move(row);
|
||||
_scheduledCallback = std::move(callback);
|
||||
_scheduledParentOverride = std::move(parentOverride);
|
||||
_scheduledPositionOverride = positionOverride;
|
||||
_timer.callOnce(kChatPreviewDelay);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ChatPreviewManager::showScheduled() {
|
||||
show(base::take(_scheduled), base::take(_scheduledCallback));
|
||||
show(
|
||||
base::take(_scheduled),
|
||||
base::take(_scheduledCallback),
|
||||
nullptr,
|
||||
base::take(_scheduledPositionOverride));
|
||||
}
|
||||
|
||||
void ChatPreviewManager::cancelScheduled() {
|
||||
_scheduled = {};
|
||||
_scheduledCallback = nullptr;
|
||||
_scheduledPositionOverride = {};
|
||||
_timer.cancel();
|
||||
}
|
||||
|
||||
|
|
|
@ -26,11 +26,13 @@ public:
|
|||
bool show(
|
||||
Dialogs::RowDescriptor row,
|
||||
Fn<void(bool shown)> callback = nullptr,
|
||||
QPointer<QWidget> parentOverride = nullptr);
|
||||
QPointer<QWidget> parentOverride = nullptr,
|
||||
std::optional<QPoint> positionOverride = {});
|
||||
bool schedule(
|
||||
Dialogs::RowDescriptor row,
|
||||
Fn<void(bool shown)> callback = nullptr,
|
||||
QPointer<QWidget> parentOverride = nullptr);
|
||||
QPointer<QWidget> parentOverride = nullptr,
|
||||
std::optional<QPoint> positionOverride = {});
|
||||
void cancelScheduled();
|
||||
|
||||
private:
|
||||
|
@ -40,6 +42,7 @@ private:
|
|||
Dialogs::RowDescriptor _scheduled;
|
||||
Fn<void(bool)> _scheduledCallback;
|
||||
QPointer<QWidget> _scheduledParentOverride;
|
||||
std::optional<QPoint> _scheduledPositionOverride;
|
||||
base::Timer _timer;
|
||||
|
||||
rpl::lifetime _topicLifetime;
|
||||
|
|
|
@ -2979,21 +2979,25 @@ QString SessionController::premiumRef() const {
|
|||
bool SessionController::showChatPreview(
|
||||
Dialogs::RowDescriptor row,
|
||||
Fn<void(bool shown)> callback,
|
||||
QPointer<QWidget> parentOverride) {
|
||||
QPointer<QWidget> parentOverride,
|
||||
std::optional<QPoint> positionOverride) {
|
||||
return _chatPreviewManager->show(
|
||||
std::move(row),
|
||||
std::move(callback),
|
||||
std::move(parentOverride));
|
||||
std::move(parentOverride),
|
||||
positionOverride);
|
||||
}
|
||||
|
||||
bool SessionController::scheduleChatPreview(
|
||||
Dialogs::RowDescriptor row,
|
||||
Fn<void(bool shown)> callback,
|
||||
QPointer<QWidget> parentOverride) {
|
||||
QPointer<QWidget> parentOverride,
|
||||
std::optional<QPoint> positionOverride) {
|
||||
return _chatPreviewManager->schedule(
|
||||
std::move(row),
|
||||
std::move(callback),
|
||||
std::move(parentOverride));
|
||||
std::move(parentOverride),
|
||||
positionOverride);
|
||||
}
|
||||
|
||||
void SessionController::cancelScheduledPreview() {
|
||||
|
|
|
@ -604,11 +604,13 @@ public:
|
|||
bool showChatPreview(
|
||||
Dialogs::RowDescriptor row,
|
||||
Fn<void(bool shown)> callback = nullptr,
|
||||
QPointer<QWidget> parentOverride = nullptr);
|
||||
QPointer<QWidget> parentOverride = nullptr,
|
||||
std::optional<QPoint> positionOverride = {});
|
||||
bool scheduleChatPreview(
|
||||
Dialogs::RowDescriptor row,
|
||||
Fn<void(bool shown)> callback = nullptr,
|
||||
QPointer<QWidget> parentOverride = nullptr);
|
||||
QPointer<QWidget> parentOverride = nullptr,
|
||||
std::optional<QPoint> positionOverride = {});
|
||||
void cancelScheduledPreview();
|
||||
|
||||
[[nodiscard]] bool contentOverlapped(QWidget *w, QPaintEvent *e) const;
|
||||
|
|
Loading…
Add table
Reference in a new issue