Add PaintContext for Dialogs::Ui::RowPainter.

This commit is contained in:
John Preston 2022-09-29 11:52:18 +04:00
parent 4724ef91f6
commit 1401b19994
12 changed files with 374 additions and 346 deletions

View file

@ -314,7 +314,7 @@ StickersBox::CounterWidget::CounterWidget(
: RpWidget(parent) { : RpWidget(parent) {
setAttribute(Qt::WA_TransparentForMouseEvents); setAttribute(Qt::WA_TransparentForMouseEvents);
_st.sizeId = Dialogs::Ui::UnreadBadgeInStickersBox; _st.sizeId = Dialogs::Ui::UnreadBadgeSize::StickersBox;
_st.textTop = st::stickersFeaturedBadgeTextTop; _st.textTop = st::stickersFeaturedBadgeTextTop;
_st.size = st::stickersFeaturedBadgeSize; _st.size = st::stickersFeaturedBadgeSize;
_st.padding = st::stickersFeaturedBadgePadding; _st.padding = st::stickersFeaturedBadgePadding;

View file

@ -176,7 +176,7 @@ InnerWidget::InnerWidget(
session().data().sendActionManager().animationUpdated( session().data().sendActionManager().animationUpdated(
) | rpl::start_with_next([=]( ) | rpl::start_with_next([=](
const Data::SendActionManager::AnimationUpdate &update) { const Data::SendActionManager::AnimationUpdate &update) {
const auto updateRect = Ui::RowPainter::sendActionAnimationRect( const auto updateRect = Ui::RowPainter::SendActionAnimationRect(
update.left, update.left,
update.width, update.width,
update.height, update.height,
@ -481,16 +481,17 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
const auto key = row->key(); const auto key = row->key();
const auto isActive = (key == active); const auto isActive = (key == active);
const auto isSelected = (key == selected); const auto isSelected = (key == selected);
Ui::RowPainter::paint( Ui::RowPainter::Paint(p, row, validateVideoUserpic(row), {
p, .folder = _openedFolder,
row, .forum = _openedForum,
validateVideoUserpic(row), .filter = _filterId,
_filterId, .now = ms,
fullWidth, .width = fullWidth,
isActive, .active = isActive,
isSelected, .selected = isSelected,
ms, .paused = videoPaused,
videoPaused); .narrow = (fullWidth < st::columnMinimalWidthLeft),
});
if (xadd || yadd) { if (xadd || yadd) {
p.translate(-xadd, -yadd); p.translate(-xadd, -yadd);
} }
@ -601,16 +602,17 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
: (from == (isPressed() : (from == (isPressed()
? _filteredPressed ? _filteredPressed
: _filteredSelected)); : _filteredSelected));
Ui::RowPainter::paint( Ui::RowPainter::Paint(p, row, validateVideoUserpic(row), {
p, .folder = _openedFolder,
_filterResults[from], .forum = _openedForum,
validateVideoUserpic(row), .filter = _filterId,
_filterId, .now = ms,
fullWidth, .width = fullWidth,
active, .active = active,
selected, .selected = selected,
ms, .paused = videoPaused,
videoPaused); .narrow = (fullWidth < st::columnMinimalWidthLeft),
});
p.translate(0, st::dialogsRowHeight); p.translate(0, st::dialogsRowHeight);
} }
} }
@ -639,14 +641,13 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
const auto selected = (from == (isPressed() const auto selected = (from == (isPressed()
? _peerSearchPressed ? _peerSearchPressed
: _peerSearchSelected)); : _peerSearchSelected));
paintPeerSearchResult( paintPeerSearchResult(p, result.get(), {
p, .now = ms,
result.get(), .width = fullWidth,
fullWidth, .active = active,
active, .selected = selected,
selected, .paused = videoPaused,
ms, });
videoPaused);
p.translate(0, st::dialogsRowHeight); p.translate(0, st::dialogsRowHeight);
} }
} }
@ -702,15 +703,19 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
: (from == (isPressed() : (from == (isPressed()
? _searchedPressed ? _searchedPressed
: _searchedSelected)); : _searchedSelected));
Ui::RowPainter::paint( Ui::RowPainter::Paint(p, result.get(), {
p, .folder = _openedFolder,
result.get(), .forum = _openedForum,
fullWidth, .filter = _filterId,
active, .now = ms,
selected, .width = fullWidth,
ms, .active = active,
videoPaused, .selected = selected,
showUnreadInSearchResults); .paused = videoPaused,
.search = true,
.narrow = (fullWidth < st::columnMinimalWidthLeft),
.displayUnreadInfo = showUnreadInSearchResults,
});
p.translate(0, st::dialogsRowHeight); p.translate(0, st::dialogsRowHeight);
} }
} }
@ -798,15 +803,17 @@ bool InnerWidget::isSearchResultActive(
void InnerWidget::paintPeerSearchResult( void InnerWidget::paintPeerSearchResult(
Painter &p, Painter &p,
not_null<const PeerSearchResult*> result, not_null<const PeerSearchResult*> result,
int fullWidth, const Ui::PaintContext &context) {
bool active, QRect fullRect(0, 0, context.width, st::dialogsRowHeight);
bool selected, p.fillRect(
crl::time now, fullRect,
bool paused) { (context.active
QRect fullRect(0, 0, fullWidth, st::dialogsRowHeight); ? st::dialogsBgActive
p.fillRect(fullRect, active ? st::dialogsBgActive : (selected ? st::dialogsBgOver : st::dialogsBg)); : context.selected
if (!active) { ? st::dialogsBgOver
result->row.paintRipple(p, 0, 0, fullWidth); : st::dialogsBg));
if (!context.active) {
result->row.paintRipple(p, 0, 0, context.width);
} }
auto peer = result->peer; auto peer = result->peer;
@ -814,7 +821,7 @@ void InnerWidget::paintPeerSearchResult(
userpicPeer->paintUserpicLeft(p, result->row.userpicView(), st::dialogsPadding.x(), st::dialogsPadding.y(), width(), st::dialogsPhotoSize); userpicPeer->paintUserpicLeft(p, result->row.userpicView(), st::dialogsPadding.x(), st::dialogsPadding.y(), width(), st::dialogsPhotoSize);
auto nameleft = st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPhotoPadding; auto nameleft = st::dialogsPadding.x() + st::dialogsPhotoSize + st::dialogsPhotoPadding;
auto namewidth = fullWidth - nameleft - st::dialogsPadding.x(); auto namewidth = context.width - nameleft - st::dialogsPadding.x();
QRect rectForName(nameleft, st::dialogsPadding.y() + st::dialogsNameTop, namewidth, st::msgNameFont->height); QRect rectForName(nameleft, st::dialogsPadding.y() + st::dialogsNameTop, namewidth, st::msgNameFont->height);
if (result->name.isEmpty()) { if (result->name.isEmpty()) {
@ -825,52 +832,52 @@ void InnerWidget::paintPeerSearchResult(
} }
// draw chat icon // draw chat icon
if (auto chatTypeIcon = Ui::ChatTypeIcon(peer, active, selected)) { if (const auto chatTypeIcon = Ui::ChatTypeIcon(peer, context)) {
chatTypeIcon->paint(p, rectForName.topLeft(), fullWidth); chatTypeIcon->paint(p, rectForName.topLeft(), context.width);
rectForName.setLeft(rectForName.left() + st::dialogsChatTypeSkip); rectForName.setLeft(rectForName.left() + st::dialogsChatTypeSkip);
} }
const auto badgeWidth = result->badge.drawGetWidth( const auto badgeWidth = result->badge.drawGetWidth(
p, p,
rectForName, rectForName,
result->name.maxWidth(), result->name.maxWidth(),
fullWidth, context.width,
{ {
.peer = peer, .peer = peer,
.verified = (active .verified = (context.active
? &st::dialogsVerifiedIconActive ? &st::dialogsVerifiedIconActive
: selected : context.selected
? &st::dialogsVerifiedIconOver ? &st::dialogsVerifiedIconOver
: &st::dialogsVerifiedIcon), : &st::dialogsVerifiedIcon),
.premium = (active .premium = (context.active
? &st::dialogsPremiumIconActive ? &st::dialogsPremiumIconActive
: selected : context.selected
? &st::dialogsPremiumIconOver ? &st::dialogsPremiumIconOver
: &st::dialogsPremiumIcon), : &st::dialogsPremiumIcon),
.scam = (active .scam = (context.active
? &st::dialogsScamFgActive ? &st::dialogsScamFgActive
: selected : context.selected
? &st::dialogsScamFgOver ? &st::dialogsScamFgOver
: &st::dialogsScamFg), : &st::dialogsScamFg),
.premiumFg = (active .premiumFg = (context.active
? &st::dialogsVerifiedIconBgActive ? &st::dialogsVerifiedIconBgActive
: selected : context.selected
? &st::dialogsVerifiedIconBgOver ? &st::dialogsVerifiedIconBgOver
: &st::dialogsVerifiedIconBg), : &st::dialogsVerifiedIconBg),
.preview = (active .preview = (context.active
? st::dialogsScamFgActive ? st::dialogsScamFgActive
: selected : context.selected
? st::windowBgRipple ? st::windowBgRipple
: st::windowBgOver)->c, : st::windowBgOver)->c,
.customEmojiRepaint = [=] { updateSearchResult(peer); }, .customEmojiRepaint = [=] { updateSearchResult(peer); },
.now = now, .now = context.now,
.paused = paused, .paused = context.paused,
}); });
rectForName.setWidth(rectForName.width() - badgeWidth); rectForName.setWidth(rectForName.width() - badgeWidth);
QRect tr(nameleft, st::dialogsPadding.y() + st::msgNameFont->height + st::dialogsSkip, namewidth, st::dialogsTextFont->height); QRect tr(nameleft, st::dialogsPadding.y() + st::msgNameFont->height + st::dialogsSkip, namewidth, st::dialogsTextFont->height);
p.setFont(st::dialogsTextFont); p.setFont(st::dialogsTextFont);
QString username = peer->userName(); QString username = peer->userName();
if (!active && username.startsWith(_peerSearchQuery, Qt::CaseInsensitive)) { if (!context.active && username.startsWith(_peerSearchQuery, Qt::CaseInsensitive)) {
auto first = '@' + username.mid(0, _peerSearchQuery.size()); auto first = '@' + username.mid(0, _peerSearchQuery.size());
auto second = username.mid(_peerSearchQuery.size()); auto second = username.mid(_peerSearchQuery.size());
auto w = st::dialogsTextFont->width(first); auto w = st::dialogsTextFont->width(first);
@ -884,11 +891,11 @@ void InnerWidget::paintPeerSearchResult(
p.drawText(tr.left() + w, tr.top() + st::dialogsTextFont->ascent, st::dialogsTextFont->elided(second, tr.width() - w)); p.drawText(tr.left() + w, tr.top() + st::dialogsTextFont->ascent, st::dialogsTextFont->elided(second, tr.width() - w));
} }
} else { } else {
p.setPen(active ? st::dialogsTextFgActive : st::dialogsTextFgService); p.setPen(context.active ? st::dialogsTextFgActive : st::dialogsTextFgService);
p.drawText(tr.left(), tr.top() + st::dialogsTextFont->ascent, st::dialogsTextFont->elided('@' + username, tr.width())); p.drawText(tr.left(), tr.top() + st::dialogsTextFont->ascent, st::dialogsTextFont->elided('@' + username, tr.width()));
} }
p.setPen(active ? st::dialogsTextFgActive : st::dialogsNameFg); p.setPen(context.active ? st::dialogsTextFgActive : st::dialogsNameFg);
result->name.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width()); result->name.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
} }
@ -974,7 +981,7 @@ void InnerWidget::paintSearchInPeer(
const auto paintUserpic = [&](Painter &p, int x, int y, int size) { const auto paintUserpic = [&](Painter &p, int x, int y, int size) {
peer->paintUserpicLeft(p, userpic, x, y, width(), size); peer->paintUserpicLeft(p, userpic, x, y, width(), size);
}; };
const auto icon = Ui::ChatTypeIcon(peer, false, false); const auto icon = Ui::ChatTypeIcon(peer);
paintSearchInFilter(p, paintUserpic, top, icon, text); paintSearchInFilter(p, paintUserpic, top, icon, text);
} }

View file

@ -43,6 +43,7 @@ class Forum;
namespace Dialogs::Ui { namespace Dialogs::Ui {
using namespace ::Ui; using namespace ::Ui;
class VideoUserpic; class VideoUserpic;
struct PaintContext;
} // namespace Dialogs::Ui } // namespace Dialogs::Ui
namespace Dialogs { namespace Dialogs {
@ -297,11 +298,7 @@ private:
void paintPeerSearchResult( void paintPeerSearchResult(
Painter &p, Painter &p,
not_null<const PeerSearchResult*> result, not_null<const PeerSearchResult*> result,
int fullWidth, const Ui::PaintContext &context);
bool active,
bool selected,
crl::time now,
bool paused);
void paintSearchInChat(Painter &p) const; void paintSearchInChat(Painter &p) const;
void paintSearchInPeer( void paintSearchInPeer(
Painter &p, Painter &p,

View file

@ -55,15 +55,30 @@ const auto kPsaBadgePrefix = "cloud_lng_badge_psa_";
|| history->peer->asUser()->onlineTill > 0); || history->peer->asUser()->onlineTill > 0);
} }
void PaintRowTopRight(QPainter &p, const QString &text, QRect &rectForName, bool active, bool selected) { void PaintRowTopRight(
QPainter &p,
const QString &text,
QRect &rectForName,
const PaintContext &context) {
const auto width = st::dialogsDateFont->width(text); const auto width = st::dialogsDateFont->width(text);
rectForName.setWidth(rectForName.width() - width - st::dialogsDateSkip); rectForName.setWidth(rectForName.width() - width - st::dialogsDateSkip);
p.setFont(st::dialogsDateFont); p.setFont(st::dialogsDateFont);
p.setPen(active ? st::dialogsDateFgActive : (selected ? st::dialogsDateFgOver : st::dialogsDateFg)); p.setPen(context.active
p.drawText(rectForName.left() + rectForName.width() + st::dialogsDateSkip, rectForName.top() + st::msgNameFont->height - st::msgDateFont->descent, text); ? st::dialogsDateFgActive
: context.selected
? st::dialogsDateFgOver
: st::dialogsDateFg);
p.drawText(
rectForName.left() + rectForName.width() + st::dialogsDateSkip,
rectForName.top() + st::msgNameFont->height - st::msgDateFont->descent,
text);
} }
void PaintRowDate(QPainter &p, QDateTime date, QRect &rectForName, bool active, bool selected) { void PaintRowDate(
QPainter &p,
QDateTime date,
QRect &rectForName,
const PaintContext &context) {
const auto now = QDateTime::currentDateTime(); const auto now = QDateTime::currentDateTime();
const auto &lastTime = date; const auto &lastTime = date;
const auto nowDate = now.date(); const auto nowDate = now.date();
@ -81,18 +96,17 @@ void PaintRowDate(QPainter &p, QDateTime date, QRect &rectForName, bool active,
return QLocale().toString(lastDate, cDateFormat()); return QLocale().toString(lastDate, cDateFormat());
} }
}(); }();
PaintRowTopRight(p, dt, rectForName, active, selected); PaintRowTopRight(p, dt, rectForName, context);
} }
void PaintNarrowCounter( void PaintNarrowCounter(
QPainter &p, QPainter &p,
const PaintContext &context,
bool displayUnreadCounter, bool displayUnreadCounter,
bool displayUnreadMark, bool displayUnreadMark,
bool displayMentionBadge, bool displayMentionBadge,
bool displayReactionBadge, bool displayReactionBadge,
int unreadCount, int unreadCount,
bool selected,
bool active,
bool unreadMuted, bool unreadMuted,
bool mentionOrReactionMuted) { bool mentionOrReactionMuted) {
auto skipBeforeMention = 0; auto skipBeforeMention = 0;
@ -111,8 +125,8 @@ void PaintNarrowCounter(
- st::dialogsUnreadHeight; - st::dialogsUnreadHeight;
UnreadBadgeStyle st; UnreadBadgeStyle st;
st.active = active; st.active = context.active;
st.selected = selected; st.selected = context.selected;
st.muted = unreadMuted; st.muted = unreadMuted;
const auto badge = PaintUnreadBadge( const auto badge = PaintUnreadBadge(
p, p,
@ -134,10 +148,10 @@ void PaintNarrowCounter(
UnreadBadgeStyle st; UnreadBadgeStyle st;
st.sizeId = displayMentionBadge st.sizeId = displayMentionBadge
? UnreadBadgeInDialogs ? UnreadBadgeSize::Dialogs
: UnreadBadgeReactionInDialogs; : UnreadBadgeSize::ReactionInDialogs;
st.active = active; st.active = context.active;
st.selected = selected; st.selected = context.selected;
st.muted = mentionOrReactionMuted; st.muted = mentionOrReactionMuted;
st.padding = 0; st.padding = 0;
st.textTop = 0; st.textTop = 0;
@ -163,17 +177,15 @@ void PaintNarrowCounter(
int PaintWideCounter( int PaintWideCounter(
QPainter &p, QPainter &p,
const PaintContext &context,
int texttop, int texttop,
int availableWidth, int availableWidth,
int fullWidth,
bool displayUnreadCounter, bool displayUnreadCounter,
bool displayUnreadMark, bool displayUnreadMark,
bool displayMentionBadge, bool displayMentionBadge,
bool displayReactionBadge, bool displayReactionBadge,
bool displayPinnedIcon, bool displayPinnedIcon,
int unreadCount, int unreadCount,
bool active,
bool selected,
bool unreadMuted, bool unreadMuted,
bool mentionOrReactionMuted) { bool mentionOrReactionMuted) {
const auto initial = availableWidth; const auto initial = availableWidth;
@ -181,7 +193,7 @@ int PaintWideCounter(
const auto counter = (unreadCount > 0) const auto counter = (unreadCount > 0)
? QString::number(unreadCount) ? QString::number(unreadCount)
: QString(); : QString();
const auto unreadRight = fullWidth const auto unreadRight = context.width
- st::dialogsPadding.x(); - st::dialogsPadding.x();
const auto unreadTop = texttop const auto unreadTop = texttop
+ st::dialogsTextFont->ascent + st::dialogsTextFont->ascent
@ -189,8 +201,8 @@ int PaintWideCounter(
- (st::dialogsUnreadHeight - st::dialogsUnreadFont->height) / 2; - (st::dialogsUnreadHeight - st::dialogsUnreadFont->height) / 2;
UnreadBadgeStyle st; UnreadBadgeStyle st;
st.active = active; st.active = context.active;
st.selected = selected; st.selected = context.selected;
st.muted = unreadMuted; st.muted = unreadMuted;
const auto badge = PaintUnreadBadge( const auto badge = PaintUnreadBadge(
p, p,
@ -200,21 +212,21 @@ int PaintWideCounter(
st); st);
availableWidth -= badge.width() + st.padding; availableWidth -= badge.width() + st.padding;
} else if (displayPinnedIcon) { } else if (displayPinnedIcon) {
const auto &icon = active const auto &icon = context.active
? st::dialogsPinnedIconActive ? st::dialogsPinnedIconActive
: selected : context.selected
? st::dialogsPinnedIconOver ? st::dialogsPinnedIconOver
: st::dialogsPinnedIcon; : st::dialogsPinnedIcon;
icon.paint( icon.paint(
p, p,
fullWidth - st::dialogsPadding.x() - icon.width(), context.width - st::dialogsPadding.x() - icon.width(),
texttop, texttop,
fullWidth); context.width);
availableWidth -= icon.width() + st::dialogsUnreadPadding; availableWidth -= icon.width() + st::dialogsUnreadPadding;
} }
if (displayMentionBadge || displayReactionBadge) { if (displayMentionBadge || displayReactionBadge) {
const auto counter = QString(); const auto counter = QString();
const auto unreadRight = fullWidth const auto unreadRight = context.width
- st::dialogsPadding.x() - st::dialogsPadding.x()
- (initial - availableWidth); - (initial - availableWidth);
const auto unreadTop = texttop const auto unreadTop = texttop
@ -224,10 +236,10 @@ int PaintWideCounter(
UnreadBadgeStyle st; UnreadBadgeStyle st;
st.sizeId = displayMentionBadge st.sizeId = displayMentionBadge
? UnreadBadgeInDialogs ? UnreadBadgeSize::Dialogs
: UnreadBadgeReactionInDialogs; : UnreadBadgeSize::ReactionInDialogs;
st.active = active; st.active = context.active;
st.selected = selected; st.selected = context.selected;
st.muted = mentionOrReactionMuted; st.muted = mentionOrReactionMuted;
st.padding = 0; st.padding = 0;
st.textTop = 0; st.textTop = 0;
@ -257,62 +269,54 @@ int PaintWideCounter(
void PaintListEntryText( void PaintListEntryText(
Painter &p, Painter &p,
QRect rect,
bool active,
bool selected,
not_null<const Row*> row, not_null<const Row*> row,
crl::time now, const PaintContext &context,
bool paused) { QRect rect) {
if (rect.isEmpty()) { if (rect.isEmpty()) {
return; return;
} }
row->validateListEntryCache(); row->validateListEntryCache();
p.setFont(st::dialogsTextFont); p.setFont(st::dialogsTextFont);
p.setPen(active p.setPen(context.active
? st::dialogsTextFgActive ? st::dialogsTextFgActive
: selected : context.selected
? st::dialogsTextFgOver ? st::dialogsTextFgOver
: st::dialogsTextFg); : st::dialogsTextFg);
row->listEntryCache().draw(p, { row->listEntryCache().draw(p, {
.position = rect.topLeft(), .position = rect.topLeft(),
.availableWidth = rect.width(), .availableWidth = rect.width(),
.palette = &(row->folder() .palette = &(row->folder()
? (active ? (context.active
? st::dialogsTextPaletteArchiveActive ? st::dialogsTextPaletteArchiveActive
: selected : context.selected
? st::dialogsTextPaletteArchiveOver ? st::dialogsTextPaletteArchiveOver
: st::dialogsTextPaletteArchive) : st::dialogsTextPaletteArchive)
: (active : (context.active
? st::dialogsTextPaletteActive ? st::dialogsTextPaletteActive
: selected : context.selected
? st::dialogsTextPaletteOver ? st::dialogsTextPaletteOver
: st::dialogsTextPalette)), : st::dialogsTextPalette)),
.spoiler = Text::DefaultSpoilerCache(), .spoiler = Text::DefaultSpoilerCache(),
.now = now, .now = context.now,
.paused = paused, .paused = context.paused,
.elisionLines = rect.height() / st::dialogsTextFont->height, .elisionLines = rect.height() / st::dialogsTextFont->height,
}); });
} }
enum class Flag { enum class Flag {
Active = 0x01,
Selected = 0x02,
SearchResult = 0x04,
SavedMessages = 0x08, SavedMessages = 0x08,
RepliesMessages = 0x10, RepliesMessages = 0x10,
AllowUserOnline = 0x20, AllowUserOnline = 0x20,
VideoPaused = 0x40,
}; };
inline constexpr bool is_flag_type(Flag) { return true; } inline constexpr bool is_flag_type(Flag) { return true; }
template <typename PaintItemCallback, typename PaintCounterCallback> template <typename PaintItemCallback, typename PaintCounterCallback>
void paintRow( void PaintRow(
Painter &p, Painter &p,
not_null<const BasicRow*> row, not_null<const BasicRow*> row,
not_null<Entry*> entry, not_null<Entry*> entry,
Dialogs::Key chat, Dialogs::Key chat,
VideoUserpic *videoUserpic, VideoUserpic *videoUserpic,
FilterId filterId,
PeerData *from, PeerData *from,
Ui::PeerBadge &fromBadge, Ui::PeerBadge &fromBadge,
Fn<void()> customEmojiRepaint, Fn<void()> customEmojiRepaint,
@ -321,9 +325,8 @@ void paintRow(
HistoryItem *item, HistoryItem *item,
const Data::Draft *draft, const Data::Draft *draft,
QDateTime date, QDateTime date,
int fullWidth, const PaintContext &context,
base::flags<Flag> flags, base::flags<Flag> flags,
crl::time ms,
PaintItemCallback &&paintItemCallback, PaintItemCallback &&paintItemCallback,
PaintCounterCallback &&paintCounterCallback) { PaintCounterCallback &&paintCounterCallback) {
const auto supportMode = entry->session().supportMode(); const auto supportMode = entry->session().supportMode();
@ -331,19 +334,17 @@ void paintRow(
draft = nullptr; draft = nullptr;
} }
auto active = (flags & Flag::Active); auto fullRect = QRect(0, 0, context.width, st::dialogsRowHeight);
auto selected = (flags & Flag::Selected); auto bg = context.active
auto fullRect = QRect(0, 0, fullWidth, st::dialogsRowHeight);
auto bg = active
? st::dialogsBgActive ? st::dialogsBgActive
: (selected : context.selected
? st::dialogsBgOver ? st::dialogsBgOver
: st::dialogsBg); : st::dialogsBg;
auto ripple = active auto ripple = context.active
? st::dialogsRippleBgActive ? st::dialogsRippleBgActive
: st::dialogsRippleBg; : st::dialogsRippleBg;
p.fillRect(fullRect, bg); p.fillRect(fullRect, bg);
row->paintRipple(p, 0, 0, fullWidth, &ripple->c); row->paintRipple(p, 0, 0, context.width, &ripple->c);
const auto history = chat.history(); const auto history = chat.history();
@ -352,14 +353,14 @@ void paintRow(
p, p,
st::dialogsPadding.x(), st::dialogsPadding.x(),
st::dialogsPadding.y(), st::dialogsPadding.y(),
fullWidth, context.width,
st::dialogsPhotoSize); st::dialogsPhotoSize);
} else if (flags & Flag::RepliesMessages) { } else if (flags & Flag::RepliesMessages) {
EmptyUserpic::PaintRepliesMessages( EmptyUserpic::PaintRepliesMessages(
p, p,
st::dialogsPadding.x(), st::dialogsPadding.x(),
st::dialogsPadding.y(), st::dialogsPadding.y(),
fullWidth, context.width,
st::dialogsPhotoSize); st::dialogsPhotoSize);
} else if (from) { } else if (from) {
row->paintUserpic( row->paintUserpic(
@ -367,16 +368,16 @@ void paintRow(
from, from,
videoUserpic, videoUserpic,
(flags & Flag::AllowUserOnline) ? history : nullptr, (flags & Flag::AllowUserOnline) ? history : nullptr,
ms, context.now,
active, context.active,
fullWidth, context.width,
(flags & Flag::VideoPaused)); context.paused);
} else if (hiddenSenderInfo) { } else if (hiddenSenderInfo) {
hiddenSenderInfo->emptyUserpic.paint( hiddenSenderInfo->emptyUserpic.paint(
p, p,
st::dialogsPadding.x(), st::dialogsPadding.x(),
st::dialogsPadding.y(), st::dialogsPadding.y(),
fullWidth, context.width,
st::dialogsPhotoSize); st::dialogsPhotoSize);
} else { } else {
entry->paintUserpicLeft( entry->paintUserpicLeft(
@ -384,21 +385,21 @@ void paintRow(
row->userpicView(), row->userpicView(),
st::dialogsPadding.x(), st::dialogsPadding.x(),
st::dialogsPadding.y(), st::dialogsPadding.y(),
fullWidth, context.width,
st::dialogsPhotoSize); st::dialogsPhotoSize);
} }
auto nameleft = st::dialogsPadding.x() auto nameleft = st::dialogsPadding.x()
+ st::dialogsPhotoSize + st::dialogsPhotoSize
+ st::dialogsPhotoPadding; + st::dialogsPhotoPadding;
if (fullWidth <= nameleft) { if (context.width <= nameleft) {
if (!draft && item && !item->isEmpty()) { if (!draft && item && !item->isEmpty()) {
paintCounterCallback(); paintCounterCallback();
} }
return; return;
} }
auto namewidth = fullWidth - nameleft - st::dialogsPadding.x(); auto namewidth = context.width - nameleft - st::dialogsPadding.x();
auto rectForName = QRect( auto rectForName = QRect(
nameleft, nameleft,
st::dialogsPadding.y() + st::dialogsNameTop, st::dialogsPadding.y() + st::dialogsNameTop,
@ -406,7 +407,7 @@ void paintRow(
st::msgNameFont->height); st::msgNameFont->height);
const auto promoted = (history && history->useTopPromotion()) const auto promoted = (history && history->useTopPromotion())
&& !(flags & Flag::SearchResult); && !context.search;
if (promoted) { if (promoted) {
const auto type = history->topPromotionType(); const auto type = history->topPromotionType();
const auto custom = type.isEmpty() const auto custom = type.isEmpty()
@ -417,10 +418,10 @@ void paintRow(
: custom.isEmpty() : custom.isEmpty()
? tr::lng_badge_psa_default(tr::now) ? tr::lng_badge_psa_default(tr::now)
: custom; : custom;
PaintRowTopRight(p, text, rectForName, active, selected); PaintRowTopRight(p, text, rectForName, context);
} else if (from) { } else if (from) {
if (const auto chatTypeIcon = ChatTypeIcon(from, active, selected)) { if (const auto chatTypeIcon = ChatTypeIcon(from, context)) {
chatTypeIcon->paint(p, rectForName.topLeft(), fullWidth); chatTypeIcon->paint(p, rectForName.topLeft(), context.width);
rectForName.setLeft(rectForName.left() + st::dialogsChatTypeSkip); rectForName.setLeft(rectForName.left() + st::dialogsChatTypeSkip);
} }
} }
@ -436,33 +437,57 @@ void paintRow(
history->topPromotionMessage(), history->topPromotionMessage(),
DialogTextOptions()); DialogTextOptions());
} }
p.setPen(active ? st::dialogsTextFgActive : (selected ? st::dialogsTextFgOver : st::dialogsTextFg)); p.setPen(context.active
? st::dialogsTextFgActive
: context.selected
? st::dialogsTextFgOver
: st::dialogsTextFg);
history->cloudDraftTextCache.draw(p, { history->cloudDraftTextCache.draw(p, {
.position = { nameleft, texttop }, .position = { nameleft, texttop },
.availableWidth = availableWidth, .availableWidth = availableWidth,
.spoiler = Text::DefaultSpoilerCache(), .spoiler = Text::DefaultSpoilerCache(),
.now = ms, .now = context.now,
.paused = bool(flags & Flag::VideoPaused), .paused = context.paused,
.elisionLines = 1, .elisionLines = 1,
}); });
} else if (draft } else if (draft
|| (supportMode || (supportMode
&& entry->session().supportHelper().isOccupiedBySomeone(history))) { && entry->session().supportHelper().isOccupiedBySomeone(history))) {
if (!promoted) { if (!promoted) {
PaintRowDate(p, date, rectForName, active, selected); PaintRowDate(p, date, rectForName, context);
} }
auto availableWidth = namewidth; auto availableWidth = namewidth;
if (entry->isPinnedDialog(filterId) && (filterId || !entry->fixedOnTopIndex())) { if (entry->isPinnedDialog(context.filter)
auto &icon = (active ? st::dialogsPinnedIconActive : (selected ? st::dialogsPinnedIconOver : st::dialogsPinnedIcon)); && (context.filter || !entry->fixedOnTopIndex())) {
icon.paint(p, fullWidth - st::dialogsPadding.x() - icon.width(), texttop, fullWidth); auto &icon = context.active
? st::dialogsPinnedIconActive
: context.selected
? st::dialogsPinnedIconOver
: st::dialogsPinnedIcon;
icon.paint(
p,
context.width - st::dialogsPadding.x() - icon.width(),
texttop,
context.width);
availableWidth -= icon.width() + st::dialogsUnreadPadding; availableWidth -= icon.width() + st::dialogsUnreadPadding;
} }
p.setFont(st::dialogsTextFont); p.setFont(st::dialogsTextFont);
auto &color = active ? st::dialogsTextFgServiceActive : (selected ? st::dialogsTextFgServiceOver : st::dialogsTextFgService); auto &color = context.active
? st::dialogsTextFgServiceActive
: context.selected
? st::dialogsTextFgServiceOver
: st::dialogsTextFgService;
if (!ShowSendActionInDialogs(history) if (!ShowSendActionInDialogs(history)
|| !history->sendActionPainter()->paint(p, nameleft, texttop, availableWidth, fullWidth, color, ms)) { || !history->sendActionPainter()->paint(
p,
nameleft,
texttop,
availableWidth,
context.width,
color,
context.paused)) {
if (history->cloudDraftTextCache.isEmpty()) { if (history->cloudDraftTextCache.isEmpty()) {
using namespace TextUtilities; using namespace TextUtilities;
auto draftWrapped = Text::PlainLink( auto draftWrapped = Text::PlainLink(
@ -494,86 +519,111 @@ void paintRow(
DialogTextOptions(), DialogTextOptions(),
context); context);
} }
p.setPen(active ? st::dialogsTextFgActive : (selected ? st::dialogsTextFgOver : st::dialogsTextFg)); p.setPen(context.active
? st::dialogsTextFgActive
: context.selected
? st::dialogsTextFgOver
: st::dialogsTextFg);
history->cloudDraftTextCache.draw(p, { history->cloudDraftTextCache.draw(p, {
.position = { nameleft, texttop }, .position = { nameleft, texttop },
.availableWidth = availableWidth, .availableWidth = availableWidth,
.palette = &(supportMode .palette = &(supportMode
? (active ? (context.active
? st::dialogsTextPaletteTakenActive ? st::dialogsTextPaletteTakenActive
: selected : context.selected
? st::dialogsTextPaletteTakenOver ? st::dialogsTextPaletteTakenOver
: st::dialogsTextPaletteTaken) : st::dialogsTextPaletteTaken)
: (active : (context.active
? st::dialogsTextPaletteDraftActive ? st::dialogsTextPaletteDraftActive
: selected : context.selected
? st::dialogsTextPaletteDraftOver ? st::dialogsTextPaletteDraftOver
: st::dialogsTextPaletteDraft)), : st::dialogsTextPaletteDraft)),
.spoiler = Text::DefaultSpoilerCache(), .spoiler = Text::DefaultSpoilerCache(),
.now = ms, .now = context.now,
.paused = bool(flags & Flag::VideoPaused), .paused = context.paused,
.elisionLines = 1, .elisionLines = 1,
}); });
} }
} else if (!item) { } else if (!item) {
auto availableWidth = namewidth; auto availableWidth = namewidth;
if (entry->isPinnedDialog(filterId) && (filterId || !entry->fixedOnTopIndex())) { if (entry->isPinnedDialog(context.filter)
auto &icon = (active ? st::dialogsPinnedIconActive : (selected ? st::dialogsPinnedIconOver : st::dialogsPinnedIcon)); && (context.filter || !entry->fixedOnTopIndex())) {
icon.paint(p, fullWidth - st::dialogsPadding.x() - icon.width(), texttop, fullWidth); auto &icon = context.active
? st::dialogsPinnedIconActive
: context.selected
? st::dialogsPinnedIconOver
: st::dialogsPinnedIcon;
icon.paint(p, context.width - st::dialogsPadding.x() - icon.width(), texttop, context.width);
availableWidth -= icon.width() + st::dialogsUnreadPadding; availableWidth -= icon.width() + st::dialogsUnreadPadding;
} }
auto &color = active ? st::dialogsTextFgServiceActive : (selected ? st::dialogsTextFgServiceOver : st::dialogsTextFgService); auto &color = context.active
? st::dialogsTextFgServiceActive
: context.selected
? st::dialogsTextFgServiceOver
: st::dialogsTextFgService;
p.setFont(st::dialogsTextFont); p.setFont(st::dialogsTextFont);
if (!ShowSendActionInDialogs(history) if (!ShowSendActionInDialogs(history)
|| !history->sendActionPainter()->paint(p, nameleft, texttop, availableWidth, fullWidth, color, ms)) { || !history->sendActionPainter()->paint(
p,
nameleft,
texttop,
availableWidth,
context.width,
color,
context.now)) {
// Empty history // Empty history
} }
} else if (!item->isEmpty()) { } else if (!item->isEmpty()) {
if (history && !promoted) { if (history && !promoted) {
PaintRowDate(p, date, rectForName, active, selected); PaintRowDate(p, date, rectForName, context);
} }
paintItemCallback(nameleft, namewidth); paintItemCallback(nameleft, namewidth);
} else if (entry->isPinnedDialog(filterId) && (filterId || !entry->fixedOnTopIndex())) { } else if (entry->isPinnedDialog(context.filter)
auto &icon = (active ? st::dialogsPinnedIconActive : (selected ? st::dialogsPinnedIconOver : st::dialogsPinnedIcon)); && (context.filter || !entry->fixedOnTopIndex())) {
icon.paint(p, fullWidth - st::dialogsPadding.x() - icon.width(), texttop, fullWidth); auto &icon = context.active
? st::dialogsPinnedIconActive
: context.selected
? st::dialogsPinnedIconOver
: st::dialogsPinnedIcon;
icon.paint(p, context.width - st::dialogsPadding.x() - icon.width(), texttop, context.width);
} }
auto sendStateIcon = [&]() -> const style::icon* { auto sendStateIcon = [&]() -> const style::icon* {
if (draft) { if (draft) {
if (draft->saveRequestId) { if (draft->saveRequestId) {
return &(active return &(context.active
? st::dialogsSendingIconActive ? st::dialogsSendingIconActive
: (selected : context.selected
? st::dialogsSendingIconOver ? st::dialogsSendingIconOver
: st::dialogsSendingIcon)); : st::dialogsSendingIcon);
} }
} else if (item && !item->isEmpty() && item->needCheck()) { } else if (item && !item->isEmpty() && item->needCheck()) {
if (!item->isSending() && !item->hasFailed()) { if (!item->isSending() && !item->hasFailed()) {
if (item->unread()) { if (item->unread()) {
return &(active return &(context.active
? st::dialogsSentIconActive ? st::dialogsSentIconActive
: (selected : context.selected
? st::dialogsSentIconOver ? st::dialogsSentIconOver
: st::dialogsSentIcon)); : st::dialogsSentIcon);
} }
return &(active return &(context.active
? st::dialogsReceivedIconActive ? st::dialogsReceivedIconActive
: (selected : context.selected
? st::dialogsReceivedIconOver ? st::dialogsReceivedIconOver
: st::dialogsReceivedIcon)); : st::dialogsReceivedIcon);
} }
return &(active return &(context.active
? st::dialogsSendingIconActive ? st::dialogsSendingIconActive
: (selected : context.selected
? st::dialogsSendingIconOver ? st::dialogsSendingIconOver
: st::dialogsSendingIcon)); : st::dialogsSendingIcon);
} }
return nullptr; return nullptr;
}(); }();
if (sendStateIcon && history) { if (sendStateIcon && history) {
rectForName.setWidth(rectForName.width() - st::dialogsSendStateSkip); rectForName.setWidth(rectForName.width() - st::dialogsSendStateSkip);
sendStateIcon->paint(p, rectForName.topLeft() + QPoint(rectForName.width(), 0), fullWidth); sendStateIcon->paint(p, rectForName.topLeft() + QPoint(rectForName.width(), 0), context.width);
} }
p.setFont(st::msgNameFont); p.setFont(st::msgNameFont);
@ -585,69 +635,69 @@ void paintRow(
if (textWidth > rectForName.width()) { if (textWidth > rectForName.width()) {
text = st::msgNameFont->elided(text, rectForName.width()); text = st::msgNameFont->elided(text, rectForName.width());
} }
p.setPen(active p.setPen(context.active
? st::dialogsNameFgActive ? st::dialogsNameFgActive
: selected : context.selected
? st::dialogsNameFgOver ? st::dialogsNameFgOver
: st::dialogsNameFg); : st::dialogsNameFg);
p.drawTextLeft(rectForName.left(), rectForName.top(), fullWidth, text); p.drawTextLeft(rectForName.left(), rectForName.top(), context.width, text);
} else if (from) { } else if (from) {
if (history && !(flags & Flag::SearchResult)) { if (history && !context.search) {
const auto badgeWidth = fromBadge.drawGetWidth( const auto badgeWidth = fromBadge.drawGetWidth(
p, p,
rectForName, rectForName,
fromName.maxWidth(), fromName.maxWidth(),
fullWidth, context.width,
{ {
.peer = from, .peer = from,
.verified = (active .verified = (context.active
? &st::dialogsVerifiedIconActive ? &st::dialogsVerifiedIconActive
: selected : context.selected
? &st::dialogsVerifiedIconOver ? &st::dialogsVerifiedIconOver
: &st::dialogsVerifiedIcon), : &st::dialogsVerifiedIcon),
.premium = (active .premium = (context.active
? &st::dialogsPremiumIconActive ? &st::dialogsPremiumIconActive
: selected : context.selected
? &st::dialogsPremiumIconOver ? &st::dialogsPremiumIconOver
: &st::dialogsPremiumIcon), : &st::dialogsPremiumIcon),
.scam = (active .scam = (context.active
? &st::dialogsScamFgActive ? &st::dialogsScamFgActive
: selected : context.selected
? &st::dialogsScamFgOver ? &st::dialogsScamFgOver
: &st::dialogsScamFg), : &st::dialogsScamFg),
.premiumFg = (active .premiumFg = (context.active
? &st::dialogsVerifiedIconBgActive ? &st::dialogsVerifiedIconBgActive
: selected : context.selected
? &st::dialogsVerifiedIconBgOver ? &st::dialogsVerifiedIconBgOver
: &st::dialogsVerifiedIconBg), : &st::dialogsVerifiedIconBg),
.preview = (active .preview = (context.active
? st::dialogsScamFgActive ? st::dialogsScamFgActive
: selected : context.selected
? st::windowBgRipple ? st::windowBgRipple
: st::windowBgOver)->c, : st::windowBgOver)->c,
.customEmojiRepaint = customEmojiRepaint, .customEmojiRepaint = customEmojiRepaint,
.now = ms, .now = context.now,
.paused = bool(flags & Flag::VideoPaused), .paused = context.paused,
}); });
rectForName.setWidth(rectForName.width() - badgeWidth); rectForName.setWidth(rectForName.width() - badgeWidth);
} }
p.setPen(active p.setPen(context.active
? st::dialogsNameFgActive ? st::dialogsNameFgActive
: selected : context.selected
? st::dialogsNameFgOver ? st::dialogsNameFgOver
: st::dialogsNameFg); : st::dialogsNameFg);
fromName.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width()); fromName.drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
} else if (hiddenSenderInfo) { } else if (hiddenSenderInfo) {
p.setPen(active p.setPen(context.active
? st::dialogsNameFgActive ? st::dialogsNameFgActive
: selected : context.selected
? st::dialogsNameFgOver ? st::dialogsNameFgOver
: st::dialogsNameFg); : st::dialogsNameFg);
hiddenSenderInfo->nameText().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width()); hiddenSenderInfo->nameText().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
} else { } else {
p.setPen(active p.setPen(context.active
? st::dialogsNameFgActive ? st::dialogsNameFgActive
: selected : context.selected
? st::dialogsArchiveFgOver ? st::dialogsArchiveFgOver
: st::dialogsArchiveFg); : st::dialogsArchiveFg);
auto text = entry->chatListName(); // TODO feed name with emoji auto text = entry->chatListName(); // TODO feed name with emoji
@ -655,7 +705,7 @@ void paintRow(
if (textWidth > rectForName.width()) { if (textWidth > rectForName.width()) {
text = st::msgNameFont->elided(text, rectForName.width()); text = st::msgNameFont->elided(text, rectForName.width());
} }
p.drawTextLeft(rectForName.left(), rectForName.top(), fullWidth, text); p.drawTextLeft(rectForName.left(), rectForName.top(), context.width, text);
} }
} }
@ -667,7 +717,7 @@ class UnreadBadgeStyleData : public Data::AbstractStructure {
public: public:
UnreadBadgeStyleData(); UnreadBadgeStyleData();
UnreadBadgeSizeData sizes[UnreadBadgeSizesCount]; UnreadBadgeSizeData sizes[static_cast<int>(UnreadBadgeSize::kCount)];
style::color bg[6] = { style::color bg[6] = {
st::dialogsUnreadBg, st::dialogsUnreadBg,
st::dialogsUnreadBgOver, st::dialogsUnreadBgOver,
@ -722,11 +772,11 @@ void PaintUnreadBadge(QPainter &p, const QRect &rect, const UnreadBadgeStyle &st
unreadBadgeStyle.createIfNull(); unreadBadgeStyle.createIfNull();
auto badgeData = unreadBadgeStyle->sizes; auto badgeData = unreadBadgeStyle->sizes;
if (st.sizeId > 0) { if (st.sizeId > UnreadBadgeSize()) {
Assert(st.sizeId < UnreadBadgeSizesCount); Assert(st.sizeId < UnreadBadgeSize::kCount);
badgeData = &unreadBadgeStyle->sizes[st.sizeId]; badgeData = &unreadBadgeStyle->sizes[static_cast<int>(st.sizeId)];
} }
auto bg = (st.sizeId == UnreadBadgeReactionInDialogs) const auto bg = (st.sizeId == UnreadBadgeSize::ReactionInDialogs)
? unreadBadgeStyle->reactionBg[index] ? unreadBadgeStyle->reactionBg[index]
: unreadBadgeStyle->bg[index]; : unreadBadgeStyle->bg[index];
if (badgeData->left[index].isNull()) { if (badgeData->left[index].isNull()) {
@ -762,25 +812,26 @@ void PaintUnreadBadge(QPainter &p, const QRect &rect, const UnreadBadgeStyle &st
const style::icon *ChatTypeIcon( const style::icon *ChatTypeIcon(
not_null<PeerData*> peer, not_null<PeerData*> peer,
bool active, const PaintContext &context) {
bool selected) {
if (peer->isChat() || peer->isMegagroup()) { if (peer->isChat() || peer->isMegagroup()) {
return &(active return &(context.active
? st::dialogsChatIconActive ? st::dialogsChatIconActive
: (selected ? st::dialogsChatIconOver : st::dialogsChatIcon)); : context.selected
? st::dialogsChatIconOver
: st::dialogsChatIcon);
} else if (peer->isChannel()) { } else if (peer->isChannel()) {
return &(active return &(context.active
? st::dialogsChannelIconActive ? st::dialogsChannelIconActive
: (selected : context.selected
? st::dialogsChannelIconOver ? st::dialogsChannelIconOver
: st::dialogsChannelIcon)); : st::dialogsChannelIcon);
} else if (const auto user = peer->asUser()) { } else if (const auto user = peer->asUser()) {
if (ShowUserBotIcon(user)) { if (ShowUserBotIcon(user)) {
return &(active return &(context.active
? st::dialogsBotIconActive ? st::dialogsBotIconActive
: (selected : context.selected
? st::dialogsBotIconOver ? st::dialogsBotIconOver
: st::dialogsBotIcon)); : st::dialogsBotIcon);
} }
} }
return nullptr; return nullptr;
@ -841,16 +892,11 @@ QRect PaintUnreadBadge(
return badge; return badge;
} }
void RowPainter::paint( void RowPainter::Paint(
Painter &p, Painter &p,
not_null<const Row*> row, not_null<const Row*> row,
VideoUserpic *videoUserpic, VideoUserpic *videoUserpic,
FilterId filterId, const PaintContext &context) {
int fullWidth,
bool active,
bool selected,
crl::time ms,
bool paused) {
const auto entry = row->entry(); const auto entry = row->entry();
const auto history = row->history(); const auto history = row->history();
const auto topic = row->topic(); const auto topic = row->topic();
@ -907,46 +953,41 @@ void RowPainter::paint(
&& !displayMentionBadge && !displayMentionBadge
&& !displayReactionBadge && !displayReactionBadge
&& !displayUnreadMark && !displayUnreadMark
&& entry->isPinnedDialog(filterId) && entry->isPinnedDialog(context.filter)
&& (filterId || !entry->fixedOnTopIndex()); && (context.filter || !entry->fixedOnTopIndex());
const auto from = history const auto from = history
? (history->peer->migrateTo() ? (history->peer->migrateTo()
? history->peer->migrateTo() ? history->peer->migrateTo()
: history->peer.get()) : history->peer.get())
: nullptr; : nullptr;
const auto allowUserOnline = (fullWidth >= st::columnMinimalWidthLeft) const auto allowUserOnline = !context.narrow
|| (!displayUnreadCounter && !displayUnreadMark); || (!displayUnreadCounter && !displayUnreadMark);
const auto flags = (active ? Flag::Active : Flag(0)) const auto flags = (allowUserOnline ? Flag::AllowUserOnline : Flag(0))
| (selected ? Flag::Selected : Flag(0))
| (allowUserOnline ? Flag::AllowUserOnline : Flag(0))
| (peer && peer->isSelf() ? Flag::SavedMessages : Flag(0)) | (peer && peer->isSelf() ? Flag::SavedMessages : Flag(0))
| (peer && peer->isRepliesChat() ? Flag::RepliesMessages : Flag(0)) | (peer && peer->isRepliesChat() ? Flag::RepliesMessages : Flag(0));
| (paused ? Flag::VideoPaused : Flag(0));
const auto paintItemCallback = [&](int nameleft, int namewidth) { const auto paintItemCallback = [&](int nameleft, int namewidth) {
const auto texttop = st::dialogsPadding.y() const auto texttop = st::dialogsPadding.y()
+ st::msgNameFont->height + st::msgNameFont->height
+ st::dialogsSkip; + st::dialogsSkip;
const auto availableWidth = PaintWideCounter( const auto availableWidth = PaintWideCounter(
p, p,
context,
texttop, texttop,
namewidth, namewidth,
fullWidth,
displayUnreadCounter, displayUnreadCounter,
displayUnreadMark, displayUnreadMark,
displayMentionBadge, displayMentionBadge,
displayReactionBadge, displayReactionBadge,
displayPinnedIcon, displayPinnedIcon,
unreadCount, unreadCount,
active,
selected,
unreadMuted, unreadMuted,
mentionOrReactionMuted); mentionOrReactionMuted);
const auto &color = active const auto &color = context.active
? st::dialogsTextFgServiceActive ? st::dialogsTextFgServiceActive
: (selected : context.selected
? st::dialogsTextFgServiceOver ? st::dialogsTextFgServiceOver
: st::dialogsTextFgService); : st::dialogsTextFgService;
const auto rect = QRect( const auto rect = QRect(
nameleft, nameleft,
texttop, texttop,
@ -958,9 +999,9 @@ void RowPainter::paint(
rect.x(), rect.x(),
rect.y(), rect.y(),
rect.width(), rect.width(),
fullWidth, context.width,
color, color,
ms) context.now)
: false; : false;
const auto view = actionWasPainted const auto view = actionWasPainted
? nullptr ? nullptr
@ -970,7 +1011,7 @@ void RowPainter::paint(
? &topic->lastItemDialogsView ? &topic->lastItemDialogsView
: nullptr; : nullptr;
if (const auto folder = row->folder()) { if (const auto folder = row->folder()) {
PaintListEntryText(p, rect, active, selected, row, ms, paused); PaintListEntryText(p, row, context, rect);
} else if (view) { } else if (view) {
if (!view->prepared(item)) { if (!view->prepared(item)) {
view->prepare( view->prepare(
@ -978,29 +1019,27 @@ void RowPainter::paint(
[=] { entry->updateChatListEntry(); }, [=] { entry->updateChatListEntry(); },
{}); {});
} }
view->paint(p, rect, active, selected, ms, paused); view->paint(p, rect, context);
} }
}; };
const auto paintCounterCallback = [&] { const auto paintCounterCallback = [&] {
PaintNarrowCounter( PaintNarrowCounter(
p, p,
context,
displayUnreadCounter, displayUnreadCounter,
displayUnreadMark, displayUnreadMark,
displayMentionBadge, displayMentionBadge,
displayReactionBadge, displayReactionBadge,
unreadCount, unreadCount,
selected,
active,
unreadMuted, unreadMuted,
mentionOrReactionMuted); mentionOrReactionMuted);
}; };
paintRow( PaintRow(
p, p,
row, row,
entry, entry,
row->key(), row->key(),
videoUserpic, videoUserpic,
filterId,
from, from,
entry->chatListBadge(), entry->chatListBadge(),
[=] { history->updateChatListEntry(); }, [=] { history->updateChatListEntry(); },
@ -1009,22 +1048,16 @@ void RowPainter::paint(
item, item,
cloudDraft, cloudDraft,
displayDate, displayDate,
fullWidth, context,
flags, flags,
ms,
paintItemCallback, paintItemCallback,
paintCounterCallback); paintCounterCallback);
} }
void RowPainter::paint( void RowPainter::Paint(
Painter &p, Painter &p,
not_null<const FakeRow*> row, not_null<const FakeRow*> row,
int fullWidth, const PaintContext &context) {
bool active,
bool selected,
crl::time ms,
bool paused,
bool displayUnreadInfo) {
auto item = row->item(); auto item = row->item();
auto history = item->history(); auto history = item->history();
auto cloudDraft = nullptr; auto cloudDraft = nullptr;
@ -1059,16 +1092,16 @@ void RowPainter::paint(
return {}; return {};
}(); }();
const auto unreadCount = displayUnreadInfo const auto unreadCount = context.displayUnreadInfo
? history->chatListUnreadCount() ? history->chatListUnreadCount()
: 0; : 0;
const auto unreadMark = displayUnreadInfo const auto unreadMark = context.displayUnreadInfo
&& history->chatListUnreadMark(); && history->chatListUnreadMark();
const auto unreadMuted = history->chatListMutedBadge(); const auto unreadMuted = history->chatListMutedBadge();
const auto mentionOrReactionMuted = (history->folder() != nullptr); const auto mentionOrReactionMuted = (history->folder() != nullptr);
const auto displayMentionBadge = displayUnreadInfo const auto displayMentionBadge = context.displayUnreadInfo
&& history->unreadMentions().has(); && history->unreadMentions().has();
const auto displayReactionBadge = displayUnreadInfo const auto displayReactionBadge = context.displayUnreadInfo
&& !displayMentionBadge && !displayMentionBadge
&& history->unreadReactions().has(); && history->unreadReactions().has();
const auto displayUnreadCounter = (unreadCount > 0); const auto displayUnreadCounter = (unreadCount > 0);
@ -1083,17 +1116,15 @@ void RowPainter::paint(
+ st::dialogsSkip; + st::dialogsSkip;
const auto availableWidth = PaintWideCounter( const auto availableWidth = PaintWideCounter(
p, p,
context,
texttop, texttop,
namewidth, namewidth,
fullWidth,
displayUnreadCounter, displayUnreadCounter,
displayUnreadMark, displayUnreadMark,
displayMentionBadge, displayMentionBadge,
displayReactionBadge, displayReactionBadge,
displayPinnedIcon, displayPinnedIcon,
unreadCount, unreadCount,
active,
selected,
unreadMuted, unreadMuted,
mentionOrReactionMuted); mentionOrReactionMuted);
@ -1106,18 +1137,17 @@ void RowPainter::paint(
if (!view.prepared(item)) { if (!view.prepared(item)) {
view.prepare(item, row->repaint(), previewOptions); view.prepare(item, row->repaint(), previewOptions);
} }
row->itemView().paint(p, itemRect, active, selected, ms, paused); row->itemView().paint(p, itemRect, context);
}; };
const auto paintCounterCallback = [&] { const auto paintCounterCallback = [&] {
PaintNarrowCounter( PaintNarrowCounter(
p, p,
context,
displayUnreadCounter, displayUnreadCounter,
displayUnreadMark, displayUnreadMark,
displayMentionBadge, displayMentionBadge,
displayReactionBadge, displayReactionBadge,
unreadCount, unreadCount,
selected,
active,
unreadMuted, unreadMuted,
mentionOrReactionMuted); mentionOrReactionMuted);
}; };
@ -1125,19 +1155,14 @@ void RowPainter::paint(
&& !row->searchInChat(); && !row->searchInChat();
const auto showRepliesMessages = history->peer->isRepliesChat() const auto showRepliesMessages = history->peer->isRepliesChat()
&& !row->searchInChat(); && !row->searchInChat();
const auto flags = (active ? Flag::Active : Flag(0)) const auto flags = (showSavedMessages ? Flag::SavedMessages : Flag(0))
| (selected ? Flag::Selected : Flag(0)) | (showRepliesMessages ? Flag::RepliesMessages : Flag(0));
| Flag::SearchResult PaintRow(
| (showSavedMessages ? Flag::SavedMessages : Flag(0))
| (showRepliesMessages ? Flag::RepliesMessages : Flag(0))
| (paused ? Flag::VideoPaused : Flag(0));
paintRow(
p, p,
row, row,
history, history,
history, history,
nullptr, nullptr,
FilterId(),
from, from,
row->badge(), row->badge(),
row->repaint(), row->repaint(),
@ -1146,14 +1171,13 @@ void RowPainter::paint(
item, item,
cloudDraft, cloudDraft,
ItemDateTime(item), ItemDateTime(item),
fullWidth, context,
flags, flags,
ms,
paintItemCallback, paintItemCallback,
paintCounterCallback); paintCounterCallback);
} }
QRect RowPainter::sendActionAnimationRect( QRect RowPainter::SendActionAnimationRect(
int animationLeft, int animationLeft,
int animationWidth, int animationWidth,
int animationHeight, int animationHeight,

View file

@ -10,6 +10,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Ui { namespace Ui {
} // namespace Ui } // namespace Ui
namespace Data {
class Forum;
class Folder;
} // namespace Data
namespace Dialogs { namespace Dialogs {
class Row; class Row;
class FakeRow; class FakeRow;
@ -22,39 +27,41 @@ using namespace ::Ui;
class VideoUserpic; class VideoUserpic;
struct PaintContext {
Data::Folder *folder = nullptr;
Data::Forum *forum = nullptr;
FilterId filter = 0;
crl::time now = 0;
int width = 0;
bool active = false;
bool selected = false;
bool paused = false;
bool search = false;
bool narrow = false;
bool displayUnreadInfo = false;
};
const style::icon *ChatTypeIcon( const style::icon *ChatTypeIcon(
not_null<PeerData*> peer, not_null<PeerData*> peer,
bool active, const PaintContext &context = {});
bool selected);
class RowPainter { class RowPainter {
public: public:
static void paint( static void Paint(
Painter &p, Painter &p,
not_null<const Row*> row, not_null<const Row*> row,
VideoUserpic *videoUserpic, VideoUserpic *videoUserpic,
FilterId filterId, const PaintContext &context);
int fullWidth, static void Paint(
bool active,
bool selected,
crl::time ms,
bool paused);
static void paint(
Painter &p, Painter &p,
not_null<const FakeRow*> row, not_null<const FakeRow*> row,
int fullWidth, const PaintContext &context);
bool active, static QRect SendActionAnimationRect(
bool selected,
crl::time ms,
bool paused,
bool displayUnreadInfo);
static QRect sendActionAnimationRect(
int animationLeft, int animationLeft,
int animationWidth, int animationWidth,
int animationHeight, int animationHeight,
int fullWidth, int fullWidth,
bool textUpdated); bool textUpdated);
}; };
void PaintCollapsedRow( void PaintCollapsedRow(
@ -66,16 +73,16 @@ void PaintCollapsedRow(
int fullWidth, int fullWidth,
bool selected); bool selected);
enum UnreadBadgeSize { enum class UnreadBadgeSize {
UnreadBadgeInDialogs = 0, Dialogs,
UnreadBadgeInMainMenu, MainMenu,
UnreadBadgeInHistoryToDown, HistoryToDown,
UnreadBadgeInStickersPanel, StickersPanel,
UnreadBadgeInStickersBox, StickersBox,
UnreadBadgeInTouchBar, TouchBar,
UnreadBadgeReactionInDialogs, ReactionInDialogs,
UnreadBadgeSizesCount kCount,
}; };
struct UnreadBadgeStyle { struct UnreadBadgeStyle {
UnreadBadgeStyle(); UnreadBadgeStyle();
@ -87,13 +94,15 @@ struct UnreadBadgeStyle {
int textTop = 0; int textTop = 0;
int size = 0; int size = 0;
int padding = 0; int padding = 0;
UnreadBadgeSize sizeId = UnreadBadgeInDialogs; UnreadBadgeSize sizeId = UnreadBadgeSize::Dialogs;
style::font font; style::font font;
}; };
[[nodiscard]] QSize CountUnreadBadgeSize( [[nodiscard]] QSize CountUnreadBadgeSize(
const QString &unreadCount, const QString &unreadCount,
const UnreadBadgeStyle &st, const UnreadBadgeStyle &st,
int allowDigits = 0); int allowDigits = 0);
QRect PaintUnreadBadge( QRect PaintUnreadBadge(
QPainter &p, QPainter &p,
const QString &t, const QString &t,
@ -102,6 +111,4 @@ QRect PaintUnreadBadge(
const UnreadBadgeStyle &st, const UnreadBadgeStyle &st,
int allowDigits = 0); int allowDigits = 0);
void clearUnreadBadgesCache();
} // namespace Dialogs::Ui } // namespace Dialogs::Ui

View file

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_item.h" #include "history/history_item.h"
#include "history/view/history_view_item_preview.h" #include "history/view/history_view_item_preview.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "dialogs/ui/dialogs_layout.h"
#include "ui/text/text_options.h" #include "ui/text/text_options.h"
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/image/image.h" #include "ui/image/image.h"
@ -175,22 +176,19 @@ void MessageView::prepare(
void MessageView::paint( void MessageView::paint(
Painter &p, Painter &p,
const QRect &geometry, const QRect &geometry,
bool active, const PaintContext &context) const {
bool selected,
crl::time now,
bool paused) const {
if (geometry.isEmpty()) { if (geometry.isEmpty()) {
return; return;
} }
p.setFont(st::dialogsTextFont); p.setFont(st::dialogsTextFont);
p.setPen(active p.setPen(context.active
? st::dialogsTextFgActive ? st::dialogsTextFgActive
: selected : context.selected
? st::dialogsTextFgOver ? st::dialogsTextFgOver
: st::dialogsTextFg); : st::dialogsTextFg);
const auto palette = &(active const auto palette = &(context.active
? st::dialogsTextPaletteActive ? st::dialogsTextPaletteActive
: selected : context.selected
? st::dialogsTextPaletteOver ? st::dialogsTextPaletteOver
: st::dialogsTextPalette); : st::dialogsTextPalette);
@ -229,8 +227,8 @@ void MessageView::paint(
.availableWidth = rect.width(), .availableWidth = rect.width(),
.palette = palette, .palette = palette,
.spoiler = Text::DefaultSpoilerCache(), .spoiler = Text::DefaultSpoilerCache(),
.now = now, .now = context.now,
.paused = paused, .paused = context.paused,
.elisionLines = rect.height() / st::dialogsTextFont->height, .elisionLines = rect.height() / st::dialogsTextFont->height,
}); });
} }

View file

@ -26,6 +26,8 @@ namespace Dialogs::Ui {
using namespace ::Ui; using namespace ::Ui;
struct PaintContext;
[[nodiscard]] TextWithEntities DialogsPreviewText(TextWithEntities text); [[nodiscard]] TextWithEntities DialogsPreviewText(TextWithEntities text);
class MessageView final { class MessageView final {
@ -48,10 +50,7 @@ public:
void paint( void paint(
Painter &p, Painter &p,
const QRect &geometry, const QRect &geometry,
bool active, const PaintContext &context) const;
bool selected,
crl::time now,
bool paused) const;
private: private:
struct LoadingContext; struct LoadingContext;

View file

@ -99,16 +99,12 @@ void Row::elementsPaint(
bool selected, bool selected,
int selectedElement) { int selectedElement) {
_outerWidth = outerWidth; _outerWidth = outerWidth;
using Row = Dialogs::Ui::RowPainter; Dialogs::Ui::RowPainter::Paint(p, _fakeRow.get(), {
Row::paint( .now = crl::now(),
p, .width = outerWidth,
_fakeRow.get(), .selected = selected,
outerWidth, .paused = p.inactive(),
false, });
selected,
crl::now(),
p.inactive(),
false);
} }
class ListController final : public PeerListController { class ListController final : public PeerListController {

View file

@ -99,7 +99,7 @@ QImage UnreadBadge(not_null<PeerData*> peer) {
? QString() ? QString()
: QString::number(count); : QString::number(count);
Dialogs::Ui::UnreadBadgeStyle unreadSt; Dialogs::Ui::UnreadBadgeStyle unreadSt;
unreadSt.sizeId = Dialogs::Ui::UnreadBadgeInTouchBar; unreadSt.sizeId = Dialogs::Ui::UnreadBadgeSize::TouchBar;
unreadSt.muted = history->mute(); unreadSt.muted = history->mute();
// Use constant values to draw badge regardless of cConfigScale(). // Use constant values to draw badge regardless of cConfigScale().
unreadSt.size = kUnreadBadgeSize * cRetinaFactor(); unreadSt.size = kUnreadBadgeSize * cRetinaFactor();

View file

@ -969,7 +969,7 @@ Dialogs::Ui::UnreadBadgeStyle Style() {
auto result = Dialogs::Ui::UnreadBadgeStyle(); auto result = Dialogs::Ui::UnreadBadgeStyle();
result.font = st::mainMenuBadgeFont; result.font = st::mainMenuBadgeFont;
result.size = st::mainMenuBadgeSize; result.size = st::mainMenuBadgeSize;
result.sizeId = Dialogs::Ui::UnreadBadgeInMainMenu; result.sizeId = Dialogs::Ui::UnreadBadgeSize::MainMenu;
return result; return result;
} }

View file

@ -149,7 +149,7 @@ void HistoryDownButton::paintEvent(QPaintEvent *e) {
st.align = style::al_center; st.align = style::al_center;
st.font = st::historyToDownBadgeFont; st.font = st::historyToDownBadgeFont;
st.size = st::historyToDownBadgeSize; st.size = st::historyToDownBadgeSize;
st.sizeId = Dialogs::Ui::UnreadBadgeInHistoryToDown; st.sizeId = Dialogs::Ui::UnreadBadgeSize::HistoryToDown;
Dialogs::Ui::PaintUnreadBadge(p, unreadString, width(), 0, st, 4); Dialogs::Ui::PaintUnreadBadge(p, unreadString, width(), 0, st, 4);
} }
} }

View file

@ -845,7 +845,7 @@ void Notification::updateNotifyDisplay() {
Ui::Emoji::Draw(p, emoji, Ui::Emoji::GetSizeNormal(), rectForName.left(), top); Ui::Emoji::Draw(p, emoji, Ui::Emoji::GetSizeNormal(), rectForName.left(), top);
rectForName.setLeft(rectForName.left() + size + st::msgNameFont->spacew); rectForName.setLeft(rectForName.left() + size + st::msgNameFont->spacew);
} }
if (const auto chatTypeIcon = Dialogs::Ui::ChatTypeIcon(_history->peer, false, false)) { if (const auto chatTypeIcon = Dialogs::Ui::ChatTypeIcon(_history->peer)) {
chatTypeIcon->paint(p, rectForName.topLeft(), w); chatTypeIcon->paint(p, rectForName.topLeft(), w);
rectForName.setLeft(rectForName.left() + st::dialogsChatTypeSkip); rectForName.setLeft(rectForName.left() + st::dialogsChatTypeSkip);
} }