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

View File

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

View File

@ -622,7 +622,23 @@ recentPeersList: PeerList(defaultPeerList) {
padding: margins(0px, 4px, 0px, 4px);
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) {
height: 33px;

View File

@ -71,7 +71,8 @@ public:
bool actionSelected) override;
bool rightActionDisabled() const override;
QPoint computeNamePosition(const style::PeerListItem &st) const override;
const style::PeerListItem &computeSt(
const style::PeerListItem &st) const override;
private:
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
: public PeerListController
, public base::has_weak_ptr {
@ -186,6 +201,7 @@ private:
const not_null<Window::SessionController*> _window;
rpl::variable<int> _count;
History *_activeHistory = nullptr;
bool _requested = false;
rpl::event_stream<not_null<PeerData*>> _chosen;
rpl::lifetime _lifetime;
@ -367,10 +383,20 @@ bool RecentRow::rightActionDisabled() const {
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())
? st::recentPeersSpecialNamePosition
: st.namePosition;
? st::recentPeersSpecialName
: 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(
@ -763,10 +789,31 @@ void RecommendationsController::fill() {
}
delegate()->peerListRefreshRows();
_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) {
auto row = std::make_unique<PeerListRow>(channel);
auto row = std::make_unique<ChannelRow>(channel);
if (channel->membersCountKnown()) {
row->setCustomStatus((channel->isBroadcast()
? tr::lng_chat_status_subscribers