Support active selection in recommendations.

This commit is contained in:
John Preston 2024-04-19 18:05:45 +04:00
parent 705bd9693d
commit 4f365c73ad
4 changed files with 90 additions and 25 deletions

View File

@ -734,9 +734,9 @@ auto PeerListRow::generateNameWords() const
return peer()->nameWords(); return peer()->nameWords();
} }
QPoint PeerListRow::computeNamePosition( const style::PeerListItem &PeerListRow::computeSt(
const style::PeerListItem &st) const { const style::PeerListItem &st) const {
return st.namePosition; return st;
} }
void PeerListRow::invalidatePixmapsCache() { void PeerListRow::invalidatePixmapsCache() {
@ -1693,7 +1693,9 @@ crl::time PeerListContent::paintRow(
const auto row = getRow(index); const auto row = getRow(index);
Assert(row != nullptr); Assert(row != nullptr);
row->lazyInitialize(_st.item); const auto &st = row->computeSt(_st.item);
row->lazyInitialize(st);
const auto outerWidth = width(); const auto outerWidth = width();
auto refreshStatusAt = row->refreshStatusTime(); auto refreshStatusAt = row->refreshStatusTime();
@ -1721,8 +1723,8 @@ crl::time PeerListContent::paintRow(
const auto opacity = row->opacity(); const auto opacity = row->opacity();
const auto &bg = selected const auto &bg = selected
? _st.item.button.textBgOver ? st.button.textBgOver
: _st.item.button.textBg; : st.button.textBg;
if (opacity < 1.) { if (opacity < 1.) {
p.setOpacity(opacity); p.setOpacity(opacity);
} }
@ -1736,34 +1738,34 @@ crl::time PeerListContent::paintRow(
row->paintRipple(p, 0, 0, outerWidth); row->paintRipple(p, 0, 0, outerWidth);
row->paintUserpic( row->paintUserpic(
p, p,
_st.item, st,
_st.item.photoPosition.x(), st.photoPosition.x(),
_st.item.photoPosition.y(), st.photoPosition.y(),
outerWidth); outerWidth);
p.setPen(st::contactsNameFg); p.setPen(st::contactsNameFg);
const auto skipRight = _st.item.photoPosition.x(); const auto skipRight = st.photoPosition.x();
const auto rightActionSize = row->rightActionSize(); const auto rightActionSize = row->rightActionSize();
const auto rightActionMargins = rightActionSize.isEmpty() const auto rightActionMargins = rightActionSize.isEmpty()
? QMargins() ? QMargins()
: row->rightActionMargins(); : row->rightActionMargins();
const auto &name = row->name(); const auto &name = row->name();
const auto namePosition = row->computeNamePosition(_st.item); const auto namePosition = st.namePosition;
const auto namex = namePosition.x(); const auto namex = namePosition.x();
const auto namey = namePosition.y(); const auto namey = namePosition.y();
auto namew = outerWidth - namex - skipRight; auto namew = outerWidth - namex - skipRight;
if (!rightActionSize.isEmpty() if (!rightActionSize.isEmpty()
&& (namey < rightActionMargins.top() + rightActionSize.height()) && (namey < rightActionMargins.top() + rightActionSize.height())
&& (namey + _st.item.nameStyle.font->height && (namey + st.nameStyle.font->height
> rightActionMargins.top())) { > rightActionMargins.top())) {
namew -= rightActionMargins.left() namew -= rightActionMargins.left()
+ rightActionSize.width() + rightActionSize.width()
+ rightActionMargins.right() + rightActionMargins.right()
- skipRight; - skipRight;
} }
const auto statusx = _st.item.statusPosition.x(); const auto statusx = st.statusPosition.x();
const auto statusy = _st.item.statusPosition.y(); const auto statusy = st.statusPosition.y();
auto statusw = outerWidth - statusx - skipRight; auto statusw = outerWidth - statusx - skipRight;
if (!rightActionSize.isEmpty() if (!rightActionSize.isEmpty()
&& (statusy < rightActionMargins.top() + rightActionSize.height()) && (statusy < rightActionMargins.top() + rightActionSize.height())
@ -1785,7 +1787,7 @@ crl::time PeerListContent::paintRow(
width(), width(),
selected); selected);
auto nameCheckedRatio = row->disabled() ? 0. : row->checkedRatio(); auto nameCheckedRatio = row->disabled() ? 0. : row->checkedRatio();
p.setPen(anim::pen(_st.item.nameFg, _st.item.nameFgChecked, nameCheckedRatio)); p.setPen(anim::pen(st.nameFg, st.nameFgChecked, nameCheckedRatio));
name.drawLeftElided(p, namex, namey, namew, width()); name.drawLeftElided(p, namex, namey, namew, width());
p.setFont(st::contactsStatusFont); p.setFont(st::contactsStatusFont);
@ -1804,17 +1806,17 @@ crl::time PeerListContent::paintRow(
if (highlightedWidth > availableWidth) { if (highlightedWidth > availableWidth) {
highlightedPart = st::contactsStatusFont->elided(highlightedPart, availableWidth); highlightedPart = st::contactsStatusFont->elided(highlightedPart, availableWidth);
} }
p.setPen(_st.item.statusFgActive); p.setPen(st.statusFgActive);
p.drawTextLeft(statusx, statusy, width(), highlightedPart); p.drawTextLeft(statusx, statusy, width(), highlightedPart);
} else { } else {
grayedPart = st::contactsStatusFont->elided(grayedPart, availableWidth - highlightedWidth); grayedPart = st::contactsStatusFont->elided(grayedPart, availableWidth - highlightedWidth);
p.setPen(_st.item.statusFgActive); p.setPen(st.statusFgActive);
p.drawTextLeft(statusx, statusy, width(), highlightedPart); p.drawTextLeft(statusx, statusy, width(), highlightedPart);
p.setPen(selected ? _st.item.statusFgOver : _st.item.statusFg); p.setPen(selected ? st.statusFgOver : st.statusFg);
p.drawTextLeft(statusx + highlightedWidth, statusy, width(), grayedPart); p.drawTextLeft(statusx + highlightedWidth, statusy, width(), grayedPart);
} }
} else { } else {
row->paintStatusText(p, _st.item, statusx, statusy, statusw, width(), selected); row->paintStatusText(p, st, statusx, statusy, statusw, width(), selected);
} }
row->elementsPaint( row->elementsPaint(

View File

@ -100,7 +100,7 @@ public:
-> const base::flat_set<QChar> &; -> const base::flat_set<QChar> &;
[[nodiscard]] virtual auto generateNameWords() const [[nodiscard]] virtual auto generateNameWords() const
-> const base::flat_set<QString> &; -> const base::flat_set<QString> &;
[[nodiscard]] virtual QPoint computeNamePosition( [[nodiscard]] virtual const style::PeerListItem &computeSt(
const style::PeerListItem &st) const; const style::PeerListItem &st) const;
virtual void preloadUserpic(); virtual void preloadUserpic();

View File

@ -622,7 +622,23 @@ recentPeersList: PeerList(defaultPeerList) {
padding: margins(0px, 4px, 0px, 4px); padding: margins(0px, 4px, 0px, 4px);
item: recentPeersItem; item: recentPeersItem;
} }
recentPeersSpecialNamePosition: point(64px, 19px); recentPeersItemActive: PeerListItem(recentPeersItem) {
nameFg: dialogsNameFgActive;
nameFgChecked: dialogsNameFgActive;
button: OutlineButton(defaultPeerListButton) {
textBg: dialogsBgActive;
textBgOver: dialogsBgActive;
ripple: RippleAnimation(defaultRippleAnimation) {
color: dialogsRippleBgActive;
}
}
statusFg: dialogsTextFgActive;
statusFgOver: dialogsTextFgActive;
statusFgActive: dialogsTextFgActive;
}
recentPeersSpecialName: PeerListItem(recentPeersItem) {
namePosition: point(64px, 19px);
}
dialogsSearchTabs: SettingsSlider(defaultSettingsSlider) { dialogsSearchTabs: SettingsSlider(defaultSettingsSlider) {
height: 33px; height: 33px;

View File

@ -71,7 +71,8 @@ public:
bool actionSelected) override; bool actionSelected) override;
bool rightActionDisabled() const override; bool rightActionDisabled() const override;
QPoint computeNamePosition(const style::PeerListItem &st) const override; const style::PeerListItem &computeSt(
const style::PeerListItem &st) const override;
private: private:
const not_null<History*> _history; const not_null<History*> _history;
@ -120,6 +121,20 @@ private:
}; };
class ChannelRow final : public PeerListRow {
public:
using PeerListRow::PeerListRow;
void setActive(bool active);
const style::PeerListItem &computeSt(
const style::PeerListItem &st) const override;
private:
bool _active = false;
};
class MyChannelsController final class MyChannelsController final
: public PeerListController : public PeerListController
, public base::has_weak_ptr { , public base::has_weak_ptr {
@ -186,6 +201,7 @@ private:
const not_null<Window::SessionController*> _window; const not_null<Window::SessionController*> _window;
rpl::variable<int> _count; rpl::variable<int> _count;
History *_activeHistory = nullptr;
bool _requested = false; bool _requested = false;
rpl::event_stream<not_null<PeerData*>> _chosen; rpl::event_stream<not_null<PeerData*>> _chosen;
rpl::lifetime _lifetime; rpl::lifetime _lifetime;
@ -367,10 +383,20 @@ bool RecentRow::rightActionDisabled() const {
return true; return true;
} }
QPoint RecentRow::computeNamePosition(const style::PeerListItem &st) const { const style::PeerListItem &RecentRow::computeSt(
const style::PeerListItem &st) const {
return (peer()->isSelf() || peer()->isRepliesChat()) return (peer()->isSelf() || peer()->isRepliesChat())
? st::recentPeersSpecialNamePosition ? st::recentPeersSpecialName
: st.namePosition; : st;
}
void ChannelRow::setActive(bool active) {
_active = active;
}
const style::PeerListItem &ChannelRow::computeSt(
const style::PeerListItem &st) const {
return _active ? st::recentPeersItemActive : st::recentPeersItem;
} }
RecentsController::RecentsController( RecentsController::RecentsController(
@ -763,10 +789,31 @@ void RecommendationsController::fill() {
} }
delegate()->peerListRefreshRows(); delegate()->peerListRefreshRows();
_count = delegate()->peerListFullRowsCount(); _count = delegate()->peerListFullRowsCount();
_window->activeChatValue() | rpl::start_with_next([=](const Key &key) {
const auto history = key.history();
if (_activeHistory == history) {
return;
} else if (_activeHistory) {
const auto id = _activeHistory->peer->id.value;
if (const auto row = delegate()->peerListFindRow(id)) {
static_cast<ChannelRow*>(row)->setActive(false);
delegate()->peerListUpdateRow(row);
}
}
_activeHistory = history;
if (_activeHistory) {
const auto id = _activeHistory->peer->id.value;
if (const auto row = delegate()->peerListFindRow(id)) {
static_cast<ChannelRow*>(row)->setActive(true);
delegate()->peerListUpdateRow(row);
}
}
}, _lifetime);
} }
void RecommendationsController::appendRow(not_null<ChannelData*> channel) { void RecommendationsController::appendRow(not_null<ChannelData*> channel) {
auto row = std::make_unique<PeerListRow>(channel); auto row = std::make_unique<ChannelRow>(channel);
if (channel->membersCountKnown()) { if (channel->membersCountKnown()) {
row->setCustomStatus((channel->isBroadcast() row->setCustomStatus((channel->isBroadcast()
? tr::lng_chat_status_subscribers ? tr::lng_chat_status_subscribers