Show chat previews in suggestions.

This commit is contained in:
John Preston 2024-05-31 16:49:59 +04:00
parent f9f51b4e41
commit 521c17b76c
3 changed files with 89 additions and 19 deletions

View file

@ -36,6 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_widgets.h" #include "styles/style_widgets.h"
#include <xxhash.h> // XXH64. #include <xxhash.h> // XXH64.
#include <QtWidgets/QApplication>
[[nodiscard]] PeerListRowId UniqueRowIdFromString(const QString &d) { [[nodiscard]] PeerListRowId UniqueRowIdFromString(const QString &d) {
return XXH64(d.data(), d.size() * sizeof(ushort), 0); return XXH64(d.data(), d.size() * sizeof(ushort), 0);
@ -1552,13 +1553,24 @@ void PeerListContent::handleMouseMove(QPoint globalPosition) {
&& *_lastMousePosition == globalPosition) { && *_lastMousePosition == globalPosition) {
return; return;
} }
if (_trackPressStart
&& ((*_trackPressStart - globalPosition).manhattanLength()
> QApplication::startDragDistance())) {
_trackPressStart = std::nullopt;
_controller->rowTrackPressCancel();
}
selectByMouse(globalPosition); selectByMouse(globalPosition);
} }
void PeerListContent::cancelPress() {
setPressed(Selected());
}
void PeerListContent::mousePressEvent(QMouseEvent *e) { void PeerListContent::mousePressEvent(QMouseEvent *e) {
_pressButton = e->button(); _pressButton = e->button();
selectByMouse(e->globalPos()); selectByMouse(e->globalPos());
setPressed(_selected); setPressed(_selected);
_trackPressStart = {};
if (auto row = getRow(_selected.index)) { if (auto row = getRow(_selected.index)) {
auto updateCallback = [this, row, hint = _selected.index] { auto updateCallback = [this, row, hint = _selected.index] {
updateRow(row, hint); updateRow(row, hint);
@ -1586,8 +1598,11 @@ void PeerListContent::mousePressEvent(QMouseEvent *e) {
row->addRipple(_st.item, maskGenerator, point, std::move(updateCallback)); row->addRipple(_st.item, maskGenerator, point, std::move(updateCallback));
} }
} }
if (_pressButton == Qt::LeftButton && _controller->rowTrackPress(row)) {
_trackPressStart = e->globalPos();
}
} }
if (anim::Disabled() && !_selected.element) { if (anim::Disabled() && !_trackPressStart && !_selected.element) {
mousePressReleased(e->button()); mousePressReleased(e->button());
} }
} }
@ -1597,6 +1612,9 @@ void PeerListContent::mouseReleaseEvent(QMouseEvent *e) {
} }
void PeerListContent::mousePressReleased(Qt::MouseButton button) { void PeerListContent::mousePressReleased(Qt::MouseButton button) {
_trackPressStart = {};
_controller->rowTrackPressCancel();
updateRow(_pressed.index); updateRow(_pressed.index);
updateRow(_selected.index); updateRow(_selected.index);

View file

@ -347,6 +347,7 @@ public:
virtual void peerListSortRows(Fn<bool(const PeerListRow &a, const PeerListRow &b)> compare) = 0; virtual void peerListSortRows(Fn<bool(const PeerListRow &a, const PeerListRow &b)> compare) = 0;
virtual int peerListPartitionRows(Fn<bool(const PeerListRow &a)> border) = 0; virtual int peerListPartitionRows(Fn<bool(const PeerListRow &a)> border) = 0;
virtual std::shared_ptr<Main::SessionShow> peerListUiShow() = 0; virtual std::shared_ptr<Main::SessionShow> peerListUiShow() = 0;
virtual void peerListCancelPress() = 0;
template <typename PeerDataRange> template <typename PeerDataRange>
void peerListAddSelectedPeers(PeerDataRange &&range) { void peerListAddSelectedPeers(PeerDataRange &&range) {
@ -478,6 +479,12 @@ public:
} }
} }
virtual bool rowTrackPress(not_null<PeerListRow*> row) {
return false;
}
virtual void rowTrackPressCancel() {
}
virtual void loadMoreRows() { virtual void loadMoreRows() {
} }
virtual void itemDeselectedHook(not_null<PeerData*> peer) { virtual void itemDeselectedHook(not_null<PeerData*> peer) {
@ -655,6 +662,7 @@ public:
void refreshRows(); void refreshRows();
void mouseLeftGeometry(); void mouseLeftGeometry();
void cancelPress();
void setSearchMode(PeerListSearchMode mode); void setSearchMode(PeerListSearchMode mode);
void changeCheckState( void changeCheckState(
@ -829,6 +837,7 @@ private:
bool _mouseSelection = false; bool _mouseSelection = false;
std::optional<QPoint> _lastMousePosition; std::optional<QPoint> _lastMousePosition;
Qt::MouseButton _pressButton = Qt::LeftButton; Qt::MouseButton _pressButton = Qt::LeftButton;
std::optional<QPoint> _trackPressStart;
rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests; rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests;
@ -991,6 +1000,9 @@ public:
not_null<PeerListRow*> row, not_null<PeerListRow*> row,
bool highlightRow, bool highlightRow,
Fn<void(not_null<Ui::PopupMenu*>)> destroyed = nullptr) override; Fn<void(not_null<Ui::PopupMenu*>)> destroyed = nullptr) override;
void peerListCancelPress() override {
_content->cancelPress();
}
protected: protected:
not_null<PeerListContent*> content() const { not_null<PeerListContent*> content() const {

View file

@ -86,8 +86,25 @@ private:
}; };
class ControllerWithPreviews : public PeerListController {
public:
explicit ControllerWithPreviews(
not_null<Window::SessionController*> window);
[[nodiscard]] not_null<Window::SessionController*> window() const {
return _window;
}
bool rowTrackPress(not_null<PeerListRow*> row) override;
void rowTrackPressCancel() override;
private:
const not_null<Window::SessionController*> _window;
};
class RecentsController final class RecentsController final
: public PeerListController : public ControllerWithPreviews
, public base::has_weak_ptr { , public base::has_weak_ptr {
public: public:
RecentsController( RecentsController(
@ -115,7 +132,6 @@ private:
void subscribeToEvents(); void subscribeToEvents();
[[nodiscard]] Fn<void()> removeAllCallback(); [[nodiscard]] Fn<void()> removeAllCallback();
const not_null<Window::SessionController*> _window;
RecentPeersList _recent; RecentPeersList _recent;
rpl::variable<int> _count; rpl::variable<int> _count;
rpl::event_stream<not_null<PeerData*>> _chosen; rpl::event_stream<not_null<PeerData*>> _chosen;
@ -138,7 +154,7 @@ private:
}; };
class MyChannelsController final class MyChannelsController final
: public PeerListController : public ControllerWithPreviews
, public base::has_weak_ptr { , public base::has_weak_ptr {
public: public:
explicit MyChannelsController( explicit MyChannelsController(
@ -163,7 +179,6 @@ private:
void appendRow(not_null<ChannelData*> channel); void appendRow(not_null<ChannelData*> channel);
void fill(bool force = false); void fill(bool force = false);
const not_null<Window::SessionController*> _window;
std::vector<not_null<History*>> _channels; std::vector<not_null<History*>> _channels;
rpl::variable<Ui::RpWidget*> _toggleExpanded = nullptr; rpl::variable<Ui::RpWidget*> _toggleExpanded = nullptr;
rpl::variable<int> _count = 0; rpl::variable<int> _count = 0;
@ -174,7 +189,7 @@ private:
}; };
class RecommendationsController final class RecommendationsController final
: public PeerListController : public ControllerWithPreviews
, public base::has_weak_ptr { , public base::has_weak_ptr {
public: public:
explicit RecommendationsController( explicit RecommendationsController(
@ -201,7 +216,6 @@ private:
void setupDivider(); void setupDivider();
void appendRow(not_null<ChannelData*> channel); void appendRow(not_null<ChannelData*> channel);
const not_null<Window::SessionController*> _window;
rpl::variable<int> _count; rpl::variable<int> _count;
History *_activeHistory = nullptr; History *_activeHistory = nullptr;
bool _requested = false; bool _requested = false;
@ -404,10 +418,36 @@ const style::PeerListItem &ChannelRow::computeSt(
return _active ? st::recentPeersItemActive : st::recentPeersItem; return _active ? st::recentPeersItemActive : st::recentPeersItem;
} }
ControllerWithPreviews::ControllerWithPreviews(
not_null<Window::SessionController*> window)
: _window(window) {
}
bool ControllerWithPreviews::rowTrackPress(not_null<PeerListRow*> row) {
const auto peer = row->peer();
const auto history = peer->owner().history(peer);
if (base::IsAltPressed()) {
_window->showChatPreview({ history, FullMsgId() });
delegate()->peerListCancelPress();
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() });
return true;
}
return false;
}
void ControllerWithPreviews::rowTrackPressCancel() {
_window->cancelScheduledPreview();
}
RecentsController::RecentsController( RecentsController::RecentsController(
not_null<Window::SessionController*> window, not_null<Window::SessionController*> window,
RecentPeersList list) RecentPeersList list)
: _window(window) : ControllerWithPreviews(window)
, _recent(std::move(list)) { , _recent(std::move(list)) {
} }
@ -429,7 +469,7 @@ void RecentsController::rowClicked(not_null<PeerListRow*> row) {
Fn<void()> RecentsController::removeAllCallback() { Fn<void()> RecentsController::removeAllCallback() {
const auto weak = base::make_weak(this); const auto weak = base::make_weak(this);
const auto session = &_window->session(); const auto session = &this->session();
return crl::guard(session, [=] { return crl::guard(session, [=] {
if (weak) { if (weak) {
_count = 0; _count = 0;
@ -450,7 +490,7 @@ base::unique_qptr<Ui::PopupMenu> RecentsController::rowContextMenu(
st::popupMenuWithIcons); st::popupMenuWithIcons);
const auto peer = row->peer(); const auto peer = row->peer();
const auto weak = base::make_weak(this); const auto weak = base::make_weak(this);
const auto session = &_window->session(); const auto session = &this->session();
const auto removeOne = crl::guard(session, [=] { const auto removeOne = crl::guard(session, [=] {
if (weak) { if (weak) {
const auto rowId = peer->id.value; const auto rowId = peer->id.value;
@ -463,7 +503,7 @@ base::unique_qptr<Ui::PopupMenu> RecentsController::rowContextMenu(
session->recentPeers().remove(peer); session->recentPeers().remove(peer);
}); });
FillEntryMenu(Ui::Menu::CreateAddActionCallback(result), { FillEntryMenu(Ui::Menu::CreateAddActionCallback(result), {
.controller = _window, .controller = window(),
.peer = peer, .peer = peer,
.removeOneText = tr::lng_recent_remove(tr::now), .removeOneText = tr::lng_recent_remove(tr::now),
.removeOne = removeOne, .removeOne = removeOne,
@ -475,7 +515,7 @@ base::unique_qptr<Ui::PopupMenu> RecentsController::rowContextMenu(
} }
Main::Session &RecentsController::session() const { Main::Session &RecentsController::session() const {
return _window->session(); return window()->session();
} }
QString RecentsController::savedMessagesChatStatus() const { QString RecentsController::savedMessagesChatStatus() const {
@ -496,7 +536,7 @@ void RecentsController::setupDivider() {
tr::lng_recent_clear(tr::now), tr::lng_recent_clear(tr::now),
st::searchedBarLink); st::searchedBarLink);
clear->setClickedCallback(RemoveAllConfirm( clear->setClickedCallback(RemoveAllConfirm(
_window, window(),
tr::lng_recent_clear_sure(tr::now), tr::lng_recent_clear_sure(tr::now),
removeAllCallback())); removeAllCallback()));
rpl::combine( rpl::combine(
@ -555,7 +595,7 @@ void RecentsController::subscribeToEvents() {
MyChannelsController::MyChannelsController( MyChannelsController::MyChannelsController(
not_null<Window::SessionController*> window) not_null<Window::SessionController*> window)
: _window(window) { : ControllerWithPreviews(window) {
} }
void MyChannelsController::prepare() { void MyChannelsController::prepare() {
@ -679,7 +719,7 @@ base::unique_qptr<Ui::PopupMenu> MyChannelsController::rowContextMenu(
const auto peer = row->peer(); const auto peer = row->peer();
const auto addAction = Ui::Menu::CreateAddActionCallback(result); const auto addAction = Ui::Menu::CreateAddActionCallback(result);
Window::FillDialogsEntryMenu( Window::FillDialogsEntryMenu(
_window, window(),
Dialogs::EntryState{ Dialogs::EntryState{
.key = peer->owner().history(peer), .key = peer->owner().history(peer),
.section = Dialogs::EntryState::Section::ContextMenu, .section = Dialogs::EntryState::Section::ContextMenu,
@ -689,7 +729,7 @@ base::unique_qptr<Ui::PopupMenu> MyChannelsController::rowContextMenu(
} }
Main::Session &MyChannelsController::session() const { Main::Session &MyChannelsController::session() const {
return _window->session(); return window()->session();
} }
void MyChannelsController::setupDivider() { void MyChannelsController::setupDivider() {
@ -760,7 +800,7 @@ void MyChannelsController::setupDivider() {
RecommendationsController::RecommendationsController( RecommendationsController::RecommendationsController(
not_null<Window::SessionController*> window) not_null<Window::SessionController*> window)
: _window(window) { : ControllerWithPreviews(window) {
} }
void RecommendationsController::prepare() { void RecommendationsController::prepare() {
@ -795,7 +835,7 @@ void RecommendationsController::fill() {
delegate()->peerListRefreshRows(); delegate()->peerListRefreshRows();
_count = delegate()->peerListFullRowsCount(); _count = delegate()->peerListFullRowsCount();
_window->activeChatValue() | rpl::start_with_next([=](const Key &key) { window()->activeChatValue() | rpl::start_with_next([=](const Key &key) {
const auto history = key.history(); const auto history = key.history();
if (_activeHistory == history) { if (_activeHistory == history) {
return; return;
@ -841,7 +881,7 @@ base::unique_qptr<Ui::PopupMenu> RecommendationsController::rowContextMenu(
} }
Main::Session &RecommendationsController::session() const { Main::Session &RecommendationsController::session() const {
return _window->session(); return window()->session();
} }
void RecommendationsController::setupDivider() { void RecommendationsController::setupDivider() {