Custom colors in history_view_service_message module.

This commit is contained in:
John Preston 2021-09-03 13:17:07 +03:00
parent 1a4a9319f3
commit 2a2607d026
24 changed files with 520 additions and 367 deletions

View file

@ -237,7 +237,10 @@ InnerWidget::InnerWidget(
, _channel(channel) , _channel(channel)
, _history(channel->owner().history(channel)) , _history(channel->owner().history(channel))
, _api(&_channel->session().mtp()) , _api(&_channel->session().mtp())
, _pathGradient(HistoryView::MakePathShiftGradient([=] { update(); })) , _pathGradient(
HistoryView::MakePathShiftGradient(
controller->chatStyle(),
[=] { update(); }))
, _scrollDateCheck([=] { scrollDateCheck(); }) , _scrollDateCheck([=] { scrollDateCheck(); })
, _emptyText( , _emptyText(
st::historyAdminLogEmptyWidth st::historyAdminLogEmptyWidth
@ -906,8 +909,14 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
auto clip = e->rect(); auto clip = e->rect();
auto context = _controller->preparePaintContext({
.theme = _theme.get(),
.visibleAreaTop = _visibleTop,
.visibleAreaTopGlobal = mapToGlobal(QPoint(0, _visibleTop)).y(),
.clip = clip,
});
if (_items.empty() && _upLoaded && _downLoaded) { if (_items.empty() && _upLoaded && _downLoaded) {
paintEmpty(p); paintEmpty(p, context.st);
} else { } else {
_pathGradient->startFrame( _pathGradient->startFrame(
0, 0,
@ -923,12 +932,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
}); });
if (from != end) { if (from != end) {
auto top = itemTop(from->get()); auto top = itemTop(from->get());
auto context = _controller->preparePaintContext({ context.translate(0, -top);
.theme = _theme.get(),
.visibleAreaTop = _visibleTop,
.visibleAreaTopGlobal = mapToGlobal(QPoint(0, _visibleTop)).y(),
.clip = clip,
}).translated(0, -top);
p.translate(0, top); p.translate(0, top);
for (auto i = from; i != to; ++i) { for (auto i = from; i != to; ++i) {
const auto view = i->get(); const auto view = i->get();
@ -1000,10 +1004,11 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
const auto chatWide = const auto chatWide =
_controller->adaptive().isChatWide(); _controller->adaptive().isChatWide();
if (const auto date = view->Get<HistoryView::DateBadge>()) { if (const auto date = view->Get<HistoryView::DateBadge>()) {
date->paint(p, dateY, width, chatWide); date->paint(p, context.st, dateY, width, chatWide);
} else { } else {
HistoryView::ServiceMessagePainter::paintDate( HistoryView::ServiceMessagePainter::PaintDate(
p, p,
context.st,
view->dateTime(), view->dateTime(),
dateY, dateY,
width, width,
@ -1043,19 +1048,14 @@ auto InnerWidget::viewForItem(const HistoryItem *item) -> Element* {
return nullptr; return nullptr;
} }
void InnerWidget::paintEmpty(Painter &p) { void InnerWidget::paintEmpty(Painter &p, not_null<const Ui::ChatStyle*> st) {
auto rectWidth = st::historyAdminLogEmptyWidth; auto rectWidth = st::historyAdminLogEmptyWidth;
auto innerWidth = rectWidth - st::historyAdminLogEmptyPadding.left() - st::historyAdminLogEmptyPadding.right(); auto innerWidth = rectWidth - st::historyAdminLogEmptyPadding.left() - st::historyAdminLogEmptyPadding.right();
auto rectHeight = st::historyAdminLogEmptyPadding.top() + _emptyText.countHeight(innerWidth) + st::historyAdminLogEmptyPadding.bottom(); auto rectHeight = st::historyAdminLogEmptyPadding.top() + _emptyText.countHeight(innerWidth) + st::historyAdminLogEmptyPadding.bottom();
auto rect = QRect((width() - rectWidth) / 2, (height() - rectHeight) / 3, rectWidth, rectHeight); auto rect = QRect((width() - rectWidth) / 2, (height() - rectHeight) / 3, rectWidth, rectHeight);
HistoryView::ServiceMessagePainter::paintBubble( HistoryView::ServiceMessagePainter::PaintBubble(p, st, rect);
p,
rect.x(),
rect.y(),
rect.width(),
rect.height());
p.setPen(st::msgServiceFg); p.setPen(st->msgServiceFg());
_emptyText.draw(p, rect.x() + st::historyAdminLogEmptyPadding.left(), rect.y() + st::historyAdminLogEmptyPadding.top(), innerWidth, style::al_top); _emptyText.draw(p, rect.x() + st::historyAdminLogEmptyPadding.left(), rect.y() + st::historyAdminLogEmptyPadding.top(), innerWidth, style::al_top);
} }

View file

@ -36,6 +36,7 @@ enum class PointState : char;
namespace Ui { namespace Ui {
class PopupMenu; class PopupMenu;
class ChatStyle;
} // namespace Ui } // namespace Ui
namespace Window { namespace Window {
@ -213,7 +214,7 @@ private:
void updateSize(); void updateSize();
void updateMinMaxIds(); void updateMinMaxIds();
void updateEmptyText(); void updateEmptyText();
void paintEmpty(Painter &p); void paintEmpty(Painter &p, not_null<const Ui::ChatStyle*> st);
void clearAfterFilterChange(); void clearAfterFilterChange();
void clearAndRequestLog(); void clearAndRequestLog();
void addEvents(Direction direction, const QVector<MTPChannelAdminLogEvent> &events); void addEvents(Direction direction, const QVector<MTPChannelAdminLogEvent> &events);

View file

@ -159,7 +159,10 @@ HistoryInner::HistoryInner(
, _peer(history->peer) , _peer(history->peer)
, _history(history) , _history(history)
, _migrated(history->migrateFrom()) , _migrated(history->migrateFrom())
, _pathGradient(HistoryView::MakePathShiftGradient([=] { update(); })) , _pathGradient(
HistoryView::MakePathShiftGradient(
controller->chatStyle(),
[=] { update(); }))
, _scrollDateCheck([this] { scrollDateCheck(); }) , _scrollDateCheck([this] { scrollDateCheck(); })
, _scrollDateHideTimer([this] { scrollDateHideByTimer(); }) { , _scrollDateHideTimer([this] { scrollDateHideByTimer(); }) {
Instance = this; Instance = this;
@ -543,12 +546,16 @@ TextSelection HistoryInner::itemRenderSelection(
return TextSelection(); return TextSelection();
} }
void HistoryInner::paintEmpty(Painter &p, int width, int height) { void HistoryInner::paintEmpty(
Painter &p,
not_null<const Ui::ChatStyle*> st,
int width,
int height) {
if (!_emptyPainter) { if (!_emptyPainter) {
_emptyPainter = std::make_unique<HistoryView::EmptyPainter>( _emptyPainter = std::make_unique<HistoryView::EmptyPainter>(
_history); _history);
} }
_emptyPainter->paint(p, width, height); _emptyPainter->paint(p, st, width, height);
} }
void HistoryInner::paintEvent(QPaintEvent *e) { void HistoryInner::paintEvent(QPaintEvent *e) {
@ -563,37 +570,47 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
_userpicsCache.clear(); _userpicsCache.clear();
}); });
Painter p(this);
auto clip = e->rect();
const auto visibleAreaTopGlobal = mapToGlobal(
QPoint(0, _visibleAreaTop)).y();
auto context = _controller->preparePaintContext({
.theme = _theme.get(),
.visibleAreaTop = _visibleAreaTop,
.visibleAreaTopGlobal = visibleAreaTopGlobal,
.clip = clip,
});
_pathGradient->startFrame( _pathGradient->startFrame(
0, 0,
width(), width(),
std::min(st::msgMaxWidth / 2, width() / 2)); std::min(st::msgMaxWidth / 2, width() / 2));
Painter p(this);
auto clip = e->rect();
const auto historyDisplayedEmpty = _history->isDisplayedEmpty() const auto historyDisplayedEmpty = _history->isDisplayedEmpty()
&& (!_migrated || _migrated->isDisplayedEmpty()); && (!_migrated || _migrated->isDisplayedEmpty());
bool noHistoryDisplayed = _firstLoading || historyDisplayedEmpty; bool noHistoryDisplayed = _firstLoading || historyDisplayedEmpty;
if (!_firstLoading && _botAbout && !_botAbout->info->text.isEmpty() && _botAbout->height > 0) { if (!_firstLoading && _botAbout && !_botAbout->info->text.isEmpty() && _botAbout->height > 0) {
const auto st = context.st;
const auto stm = &st->messageStyle(false, false);
if (clip.y() < _botAbout->rect.y() + _botAbout->rect.height() && clip.y() + clip.height() > _botAbout->rect.y()) { if (clip.y() < _botAbout->rect.y() + _botAbout->rect.height() && clip.y() + clip.height() > _botAbout->rect.y()) {
p.setTextPalette(st::inTextPalette); p.setTextPalette(stm->textPalette);
Ui::FillRoundRect(p, _botAbout->rect, st::msgInBg, Ui::MessageInCorners, &st::msgInShadow); Ui::FillRoundRect(p, _botAbout->rect, stm->msgBg, stm->corners, &stm->msgShadow);
auto top = _botAbout->rect.top() + st::msgPadding.top(); auto top = _botAbout->rect.top() + st::msgPadding.top();
if (!_history->peer->isRepliesChat()) { if (!_history->peer->isRepliesChat()) {
p.setFont(st::msgNameFont); p.setFont(st::msgNameFont);
p.setPen(st::dialogsNameFg); p.setPen(st->dialogsNameFg());
p.drawText(_botAbout->rect.left() + st::msgPadding.left(), top + st::msgNameFont->ascent, tr::lng_bot_description(tr::now)); p.drawText(_botAbout->rect.left() + st::msgPadding.left(), top + st::msgNameFont->ascent, tr::lng_bot_description(tr::now));
top += +st::msgNameFont->height + st::botDescSkip; top += +st::msgNameFont->height + st::botDescSkip;
} }
p.setPen(st::historyTextInFg); p.setPen(stm->historyTextFg);
_botAbout->info->text.draw(p, _botAbout->rect.left() + st::msgPadding.left(), top, _botAbout->width); _botAbout->info->text.draw(p, _botAbout->rect.left() + st::msgPadding.left(), top, _botAbout->width);
p.restoreTextPalette(); p.restoreTextPalette();
} }
} else if (historyDisplayedEmpty) { } else if (historyDisplayedEmpty) {
paintEmpty(p, width(), height()); paintEmpty(p, context.st, width(), height());
} else { } else {
_emptyPainter = nullptr; _emptyPainter = nullptr;
} }
@ -611,8 +628,6 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
} else { } else {
seltoy += _dragSelTo->height(); seltoy += _dragSelTo->height();
} }
const auto visibleAreaTopGlobal = mapToGlobal(
QPoint(0, _visibleAreaTop)).y();
auto mtop = migratedTop(); auto mtop = migratedTop();
auto htop = historyTop(); auto htop = historyTop();
@ -625,12 +640,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
auto item = view->data(); auto item = view->data();
auto top = mtop + block->y() + view->y(); auto top = mtop + block->y() + view->y();
auto context = _controller->preparePaintContext({ context.translate(0, -top);
.theme = _theme.get(),
.visibleAreaTop = _visibleAreaTop,
.visibleAreaTopGlobal = visibleAreaTopGlobal,
.clip = clip,
}).translated(0, -top);
p.translate(0, top); p.translate(0, top);
if (context.clip.y() < view->height()) while (top < drawToY) { if (context.clip.y() < view->height()) while (top < drawToY) {
context.outbg = view->hasOutLayout(); context.outbg = view->hasOutLayout();
@ -666,6 +676,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
item = view->data(); item = view->data();
} }
p.translate(0, -top); p.translate(0, -top);
context.translate(0, top);
} }
if (htop >= 0) { if (htop >= 0) {
auto iBlock = (_curHistory == _history ? _curBlock : 0); auto iBlock = (_curHistory == _history ? _curBlock : 0);
@ -675,15 +686,9 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
auto item = view->data(); auto item = view->data();
auto readTill = (HistoryItem*)nullptr; auto readTill = (HistoryItem*)nullptr;
auto top = htop + block->y() + view->y(); auto top = htop + block->y() + view->y();
auto context = _controller->preparePaintContext({ context.clip = clip.intersected(
.theme = _theme.get(), QRect(0, hdrawtop, width(), clip.top() + clip.height()));
.visibleAreaTop = _visibleAreaTop, context.translate(0, -top);
.visibleAreaTopGlobal = visibleAreaTopGlobal,
.visibleAreaWidth = width(),
.clip = clip.intersected(
QRect(0, hdrawtop, width(), clip.top() + clip.height())
),
}).translated(0, -top);
p.translate(0, top); p.translate(0, top);
while (top < drawToY) { while (top < drawToY) {
const auto height = view->height(); const auto height = view->height();
@ -812,10 +817,11 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
? itemtop ? itemtop
: (dateTop - st::msgServiceMargin.top()); : (dateTop - st::msgServiceMargin.top());
if (const auto date = view->Get<HistoryView::DateBadge>()) { if (const auto date = view->Get<HistoryView::DateBadge>()) {
date->paint(p, dateY, _contentWidth, _isChatWide); date->paint(p, context.st, dateY, _contentWidth, _isChatWide);
} else { } else {
HistoryView::ServiceMessagePainter::paintDate( HistoryView::ServiceMessagePainter::PaintDate(
p, p,
context.st,
view->dateTime(), view->dateTime(),
dateY, dateY,
_contentWidth, _contentWidth,

View file

@ -35,6 +35,7 @@ class SessionController;
namespace Ui { namespace Ui {
class ChatTheme; class ChatTheme;
class ChatStyle;
class PopupMenu; class PopupMenu;
enum class ReportReason; enum class ReportReason;
class PathShiftGradient; class PathShiftGradient;
@ -246,7 +247,11 @@ private:
std::unique_ptr<QMimeData> prepareDrag(); std::unique_ptr<QMimeData> prepareDrag();
void performDrag(); void performDrag();
void paintEmpty(Painter &p, int width, int height); void paintEmpty(
Painter &p,
not_null<const Ui::ChatStyle*> st,
int width,
int height);
QPoint mapPointToItem(QPoint p, const Element *view) const; QPoint mapPointToItem(QPoint p, const Element *view) const;
QPoint mapPointToItem(QPoint p, const HistoryItem *item) const; QPoint mapPointToItem(QPoint p, const HistoryItem *item) const;

View file

@ -107,6 +107,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/chat/pinned_bar.h" #include "ui/chat/pinned_bar.h"
#include "ui/chat/group_call_bar.h" #include "ui/chat/group_call_bar.h"
#include "ui/chat/chat_theme.h" #include "ui/chat/chat_theme.h"
#include "ui/chat/chat_style.h"
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
#include "ui/item_text_options.h" #include "ui/item_text_options.h"
#include "ui/unread_badge.h" #include "ui/unread_badge.h"
@ -7058,9 +7059,10 @@ void HistoryWidget::paintEvent(QPaintEvent *e) {
- st::msgServiceMargin.bottom()) / 2, - st::msgServiceMargin.bottom()) / 2,
w, w,
h); h);
HistoryView::ServiceMessagePainter::paintBubble(p, tr.x(), tr.y(), tr.width(), tr.height()); const auto st = controller()->chatStyle();
HistoryView::ServiceMessagePainter::PaintBubble(p, st, tr);
p.setPen(st::msgServiceFg); p.setPen(st->msgServiceFg());
p.setFont(st::msgServiceFont->f); p.setFont(st::msgServiceFont->f);
p.drawTextLeft(tr.left() + st::msgPadding.left(), tr.top() + st::msgServicePadding.top(), width(), tr::lng_willbe_history(tr::now)); p.drawTextLeft(tr.left() + st::msgPadding.left(), tr.top() + st::msgServicePadding.top(), width(), tr::lng_willbe_history(tr::now));

View file

@ -23,13 +23,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/stickers_emoji_pack.h" #include "chat_helpers/stickers_emoji_pack.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "ui/effects/path_shift_gradient.h" #include "ui/effects/path_shift_gradient.h"
#include "ui/chat/chat_style.h"
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
#include "ui/toasts/common_toasts.h" #include "ui/toasts/common_toasts.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_groups.h" #include "data/data_groups.h"
#include "data/data_media_types.h" #include "data/data_media_types.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "layout/layout_selection.h"
#include "app.h" #include "app.h"
#include "styles/style_chat.h" #include "styles/style_chat.h"
@ -62,10 +62,11 @@ bool IsAttachedToPreviousInSavedMessages(
} // namespace } // namespace
std::unique_ptr<Ui::PathShiftGradient> MakePathShiftGradient( std::unique_ptr<Ui::PathShiftGradient> MakePathShiftGradient(
not_null<const Ui::ChatStyle*> st,
Fn<void()> update) { Fn<void()> update) {
return std::make_unique<Ui::PathShiftGradient>( return std::make_unique<Ui::PathShiftGradient>(
st::msgServiceBg, st->msgServiceBg(),
st::msgServiceBgSelected, st->msgServiceBgSelected(),
std::move(update)); std::move(update));
} }
@ -73,7 +74,10 @@ SimpleElementDelegate::SimpleElementDelegate(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
Fn<void()> update) Fn<void()> update)
: _controller(controller) : _controller(controller)
, _pathGradient(MakePathShiftGradient(std::move(update))) { , _pathGradient(
MakePathShiftGradient(
controller->chatStyle(),
std::move(update))) {
} }
SimpleElementDelegate::~SimpleElementDelegate() = default; SimpleElementDelegate::~SimpleElementDelegate() = default;
@ -259,7 +263,13 @@ int UnreadBar::marginTop() {
return st::lineWidth + st::historyUnreadBarMargin; return st::lineWidth + st::historyUnreadBarMargin;
} }
void UnreadBar::paint(Painter &p, int y, int w, bool chatWide) const { void UnreadBar::paint(
Painter &p,
const PaintContext &context,
int y,
int w,
bool chatWide) const {
const auto st = context.st;
const auto bottom = y + height(); const auto bottom = y + height();
y += marginTop(); y += marginTop();
p.fillRect( p.fillRect(
@ -267,15 +277,15 @@ void UnreadBar::paint(Painter &p, int y, int w, bool chatWide) const {
y, y,
w, w,
height() - marginTop() - st::lineWidth, height() - marginTop() - st::lineWidth,
st::historyUnreadBarBg); st->historyUnreadBarBg());
p.fillRect( p.fillRect(
0, 0,
bottom - st::lineWidth, bottom - st::lineWidth,
w, w,
st::lineWidth, st::lineWidth,
st::historyUnreadBarBorder); st->historyUnreadBarBorder());
p.setFont(st::historyUnreadBarFont); p.setFont(st::historyUnreadBarFont);
p.setPen(st::historyUnreadBarFg); p.setPen(st->historyUnreadBarFg());
int maxwidth = w; int maxwidth = w;
if (chatWide) { if (chatWide) {
@ -310,8 +320,13 @@ int DateBadge::height() const {
+ st::msgServiceMargin.bottom(); + st::msgServiceMargin.bottom();
} }
void DateBadge::paint(Painter &p, int y, int w, bool chatWide) const { void DateBadge::paint(
ServiceMessagePainter::paintDate(p, text, width, y, w, chatWide); Painter &p,
not_null<const Ui::ChatStyle*> st,
int y,
int w,
bool chatWide) const {
ServiceMessagePainter::PaintDate(p, st, text, width, y, w, chatWide);
} }
Element::Element( Element::Element(
@ -367,6 +382,7 @@ void Element::refreshDataIdHook() {
void Element::paintHighlight( void Element::paintHighlight(
Painter &p, Painter &p,
const PaintContext &context,
int geometryHeight) const { int geometryHeight) const {
const auto top = marginTop(); const auto top = marginTop();
const auto bottom = marginBottom(); const auto bottom = marginBottom();
@ -374,7 +390,7 @@ void Element::paintHighlight(
const auto skiptop = top - fill; const auto skiptop = top - fill;
const auto fillheight = fill + geometryHeight + fill; const auto fillheight = fill + geometryHeight + fill;
paintCustomHighlight(p, skiptop, fillheight, data()); paintCustomHighlight(p, context, skiptop, fillheight, data());
} }
float64 Element::highlightOpacity(not_null<const HistoryItem*> item) const { float64 Element::highlightOpacity(not_null<const HistoryItem*> item) const {
@ -392,6 +408,7 @@ float64 Element::highlightOpacity(not_null<const HistoryItem*> item) const {
void Element::paintCustomHighlight( void Element::paintCustomHighlight(
Painter &p, Painter &p,
const PaintContext &context,
int y, int y,
int height, int height,
not_null<const HistoryItem*> item) const { not_null<const HistoryItem*> item) const {
@ -406,7 +423,7 @@ void Element::paintCustomHighlight(
y, y,
width(), width(),
height, height,
st::defaultTextPalette.selectOverlay); context.st->msgSelectOverlay());
p.setOpacity(o); p.setOpacity(o);
} }

View file

@ -26,6 +26,7 @@ namespace Ui {
class PathShiftGradient; class PathShiftGradient;
struct BubblePattern; struct BubblePattern;
struct ChatPaintContext; struct ChatPaintContext;
class ChatStyle;
} // namespace Ui } // namespace Ui
namespace HistoryView { namespace HistoryView {
@ -36,6 +37,8 @@ struct StateRequest;
struct TextState; struct TextState;
class Media; class Media;
using PaintContext = Ui::ChatPaintContext;
enum class Context : char { enum class Context : char {
History, History,
Replies, Replies,
@ -94,6 +97,7 @@ public:
}; };
[[nodiscard]] std::unique_ptr<Ui::PathShiftGradient> MakePathShiftGradient( [[nodiscard]] std::unique_ptr<Ui::PathShiftGradient> MakePathShiftGradient(
not_null<const Ui::ChatStyle*> st,
Fn<void()> update); Fn<void()> update);
class SimpleElementDelegate : public ElementDelegate { class SimpleElementDelegate : public ElementDelegate {
@ -177,7 +181,12 @@ struct UnreadBar : public RuntimeComponent<UnreadBar, Element> {
static int height(); static int height();
static int marginTop(); static int marginTop();
void paint(Painter &p, int y, int w, bool chatWide) const; void paint(
Painter &p,
const PaintContext &context,
int y,
int w,
bool chatWide) const;
QString text; QString text;
int width = 0; int width = 0;
@ -191,15 +200,18 @@ struct DateBadge : public RuntimeComponent<DateBadge, Element> {
void init(const QString &date); void init(const QString &date);
int height() const; int height() const;
void paint(Painter &p, int y, int w, bool chatWide) const; void paint(
Painter &p,
not_null<const Ui::ChatStyle*> st,
int y,
int w,
bool chatWide) const;
QString text; QString text;
int width = 0; int width = 0;
}; };
using PaintContext = Ui::ChatPaintContext;
class Element class Element
: public Object : public Object
, public RuntimeComposer<Element> , public RuntimeComposer<Element>
@ -347,6 +359,7 @@ public:
void paintCustomHighlight( void paintCustomHighlight(
Painter &p, Painter &p,
const PaintContext &context,
int y, int y,
int height, int height,
not_null<const HistoryItem*> item) const; not_null<const HistoryItem*> item) const;
@ -376,6 +389,7 @@ public:
protected: protected:
void paintHighlight( void paintHighlight(
Painter &p, Painter &p,
const PaintContext &context,
int geometryHeight) const; int geometryHeight) const;
[[nodiscard]] ClickHandlerPtr fromLink() const; [[nodiscard]] ClickHandlerPtr fromLink() const;

View file

@ -7,17 +7,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "history/view/history_view_empty_list_bubble.h" #include "history/view/history_view_empty_list_bubble.h"
#include "history/view/history_view_list_widget.h" #include "ui/chat/chat_style.h"
#include "history/view/history_view_service_message.h" #include "history/view/history_view_service_message.h"
namespace HistoryView { namespace HistoryView {
EmptyListBubbleWidget::EmptyListBubbleWidget( EmptyListBubbleWidget::EmptyListBubbleWidget(
not_null<ListWidget*> parent, not_null<Ui::RpWidget*> parent,
not_null<const Ui::ChatStyle*> st,
const style::margins &padding) const style::margins &padding)
: RpWidget(parent) : RpWidget(parent)
, _padding(padding) { , _padding(padding)
, _st(st) {
parent->sizeValue( parent->sizeValue(
) | rpl::start_with_next([=](const QSize &s) { ) | rpl::start_with_next([=](const QSize &s) {
updateGeometry(s); updateGeometry(s);
@ -42,14 +43,9 @@ void EmptyListBubbleWidget::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
const auto r = rect(); const auto r = rect();
HistoryView::ServiceMessagePainter::paintBubble( HistoryView::ServiceMessagePainter::PaintBubble(p, _st, r);
p,
r.x(),
r.y(),
r.width(),
r.height());
p.setPen(st::msgServiceFg); p.setPen(_st->msgServiceFg());
_text.draw( _text.draw(
p, p,
r.x() + _padding.left(), r.x() + _padding.left(),

View file

@ -9,14 +9,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
namespace HistoryView { namespace Ui {
class ChatStyle;
} // namespace Ui
class ListWidget; namespace HistoryView {
class EmptyListBubbleWidget : public Ui::RpWidget { class EmptyListBubbleWidget : public Ui::RpWidget {
public: public:
EmptyListBubbleWidget( EmptyListBubbleWidget(
not_null<ListWidget*> parent, not_null<Ui::RpWidget*> parent,
not_null<const Ui::ChatStyle*> st,
const style::margins &padding); const style::margins &padding);
void setText(const TextWithEntities &textWithEntities); void setText(const TextWithEntities &textWithEntities);
@ -29,6 +32,7 @@ private:
void updateGeometry(const QSize &size); void updateGeometry(const QSize &size);
const style::margins &_padding; const style::margins &_padding;
const not_null<const Ui::ChatStyle*> _st;
Ui::Text::String _text; Ui::Text::String _text;
int _innerWidth = 0; int _innerWidth = 0;
int _forceWidth = 0; int _forceWidth = 0;

View file

@ -256,7 +256,10 @@ ListWidget::ListWidget(
, _controller(controller) , _controller(controller)
, _context(_delegate->listContext()) , _context(_delegate->listContext())
, _itemAverageHeight(itemMinimalHeight()) , _itemAverageHeight(itemMinimalHeight())
, _pathGradient(MakePathShiftGradient([=] { update(); })) , _pathGradient(
MakePathShiftGradient(
controller->chatStyle(),
[=] { update(); }))
, _scrollDateCheck([this] { scrollDateCheck(); }) , _scrollDateCheck([this] { scrollDateCheck(); })
, _applyUpdatedScrollState([this] { applyUpdatedScrollState(); }) , _applyUpdatedScrollState([this] { applyUpdatedScrollState(); })
, _selectEnabled(_delegate->listAllowsMultiSelect()) , _selectEnabled(_delegate->listAllowsMultiSelect())
@ -1700,11 +1703,14 @@ void ListWidget::paintEvent(QPaintEvent *e) {
int dateY = /*noFloatingDate ? itemtop :*/ (dateTop - st::msgServiceMargin.top()); int dateY = /*noFloatingDate ? itemtop :*/ (dateTop - st::msgServiceMargin.top());
int width = view->width(); int width = view->width();
if (const auto date = view->Get<HistoryView::DateBadge>()) { if (const auto date = view->Get<HistoryView::DateBadge>()) {
date->paint(p, dateY, width, _isChatWide); date->paint(p, context.st, dateY, width, _isChatWide);
} else { } else {
ServiceMessagePainter::paintDate( ServiceMessagePainter::PaintDate(
p, p,
ItemDateText(view->data(), IsItemScheduledUntilOnline(view->data())), context.st,
ItemDateText(
view->data(),
IsItemScheduledUntilOnline(view->data())),
dateY, dateY,
width, width,
_isChatWide); _isChatWide);

View file

@ -498,7 +498,12 @@ void Message::draw(Painter &p, const PaintContext &context) const {
auto unreadbarh = bar->height(); auto unreadbarh = bar->height();
if (context.clip.intersects(QRect(0, dateh, width(), unreadbarh))) { if (context.clip.intersects(QRect(0, dateh, width(), unreadbarh))) {
p.translate(0, dateh); p.translate(0, dateh);
bar->paint(p, 0, width(), delegate()->elementIsChatWide()); bar->paint(
p,
context,
0,
width(),
delegate()->elementIsChatWide());
p.translate(0, -dateh); p.translate(0, -dateh);
} }
} }
@ -537,9 +542,9 @@ void Message::draw(Painter &p, const PaintContext &context) const {
} }
if (customHighlight) { if (customHighlight) {
media->drawHighlight(p, localMediaTop); media->drawHighlight(p, context, localMediaTop);
} else { } else {
paintHighlight(p, g.height()); paintHighlight(p, context, g.height());
} }
const auto roll = media ? media->bubbleRoll() : Media::BubbleRoll(); const auto roll = media ? media->bubbleRoll() : Media::BubbleRoll();

View file

@ -163,6 +163,7 @@ ScheduledWidget::ScheduledWidget(
{ {
auto emptyInfo = base::make_unique_q<EmptyListBubbleWidget>( auto emptyInfo = base::make_unique_q<EmptyListBubbleWidget>(
_inner, _inner,
controller->chatStyle(),
st::msgServicePadding); st::msgServicePadding);
const auto emptyText = Ui::Text::Semibold( const auto emptyText = Ui::Text::Semibold(
tr::lng_scheduled_messages_empty(tr::now)); tr::lng_scheduled_messages_empty(tr::now));

View file

@ -41,98 +41,6 @@ enum CornerHorizontalSide {
CornerRight = 0x01, CornerRight = 0x01,
}; };
class ServiceMessageStyleData : public Data::AbstractStructure {
public:
ServiceMessageStyleData() {
style::PaletteChanged(
) | rpl::start_with_next([=] {
for (auto &corner : corners) {
corner = QPixmap();
}
}, _lifetime);
}
// circle[CircleMask value]
QImage circle[2];
// corners[(CircleMask value) * MaskMultiplier | (CornerVerticalSide value) | (CornerHorizontalSide value)]
QPixmap corners[8];
base::flat_map<std::pair<int, uint32>, QPixmap> overridenCorners;
private:
rpl::lifetime _lifetime;
};
Data::GlobalStructurePointer<ServiceMessageStyleData> serviceMessageStyle;
int historyServiceMsgRadius() {
static int HistoryServiceMsgRadius = ([]() {
auto minMsgHeight = (st::msgServiceFont->height + st::msgServicePadding.top() + st::msgServicePadding.bottom());
return minMsgHeight / 2;
})();
return HistoryServiceMsgRadius;
}
int historyServiceMsgInvertedRadius() {
static int HistoryServiceMsgInvertedRadius = ([]() {
auto minRowHeight = st::msgServiceFont->height;
return minRowHeight - historyServiceMsgRadius();
})();
return HistoryServiceMsgInvertedRadius;
}
int historyServiceMsgInvertedShrink() {
static int HistoryServiceMsgInvertedShrink = ([]() {
return (historyServiceMsgInvertedRadius() * 2) / 3;
})();
return HistoryServiceMsgInvertedShrink;
}
void createCircleMasks() {
serviceMessageStyle.createIfNull();
if (!serviceMessageStyle->circle[NormalMask].isNull()) return;
int size = historyServiceMsgRadius() * 2;
serviceMessageStyle->circle[NormalMask] = style::createCircleMask(size);
int sizeInverted = historyServiceMsgInvertedRadius() * 2;
serviceMessageStyle->circle[InvertedMask] = style::createInvertedCircleMask(sizeInverted);
}
uint32 ColorToUint(const style::color &bg) {
const auto &c = bg->c;
return c.red() << 24 | c.green() << 16 | c.blue() << 8 | c.alpha();
}
QPixmap circleCorner(int corner, const style::color &bg) {
auto &currentCorner = (bg == st::msgServiceBg)
? serviceMessageStyle->corners[corner]
: serviceMessageStyle->overridenCorners[{ corner, ColorToUint(bg) }];
if (currentCorner.isNull()) {
int maskType = corner / MaskMultiplier;
int radius = (maskType == NormalMask
? historyServiceMsgRadius()
: historyServiceMsgInvertedRadius());
int size = radius * cIntRetinaFactor();
int xoffset = 0, yoffset = 0;
if (corner & CornerRight) {
xoffset = size;
}
if (corner & CornerBottom) {
yoffset = size;
}
auto part = QRect(xoffset, yoffset, size, size);
auto result = style::colorizeImage(
serviceMessageStyle->circle[maskType],
bg,
part);
result.setDevicePixelRatio(cRetinaFactor());
currentCorner = Ui::PixmapFromImage(std::move(result));
}
return currentCorner;
}
enum class SideStyle { enum class SideStyle {
Rounded, Rounded,
Plain, Plain,
@ -140,96 +48,97 @@ enum class SideStyle {
}; };
// Returns amount of pixels already painted vertically (so you can skip them in the complex rect shape). // Returns amount of pixels already painted vertically (so you can skip them in the complex rect shape).
int paintBubbleSide( int PaintBubbleSide(
Painter &p, Painter &p,
not_null<const Ui::ChatStyle*> st,
int x, int x,
int y, int y,
int width, int width,
SideStyle style, SideStyle style,
CornerVerticalSide side, CornerVerticalSide side) {
const style::color &bg) {
if (style == SideStyle::Rounded) { if (style == SideStyle::Rounded) {
const auto corner = (int(NormalMask) * MaskMultiplier) | side; const auto &corners = st->serviceBgCornersNormal();
auto left = circleCorner(corner | CornerLeft, bg); const auto left = corners.p[(side == CornerTop) ? 0 : 2];
int leftWidth = left.width() / cIntRetinaFactor(); const auto leftWidth = left.width() / cIntRetinaFactor();
p.drawPixmap(x, y, left); p.drawPixmap(x, y, left);
auto right = circleCorner(corner | CornerRight, bg); const auto right = corners.p[(side == CornerTop) ? 1 : 3];
int rightWidth = right.width() / cIntRetinaFactor(); const auto rightWidth = right.width() / cIntRetinaFactor();
p.drawPixmap(x + width - rightWidth, y, right); p.drawPixmap(x + width - rightWidth, y, right);
int cornerHeight = left.height() / cIntRetinaFactor(); const auto cornerHeight = left.height() / cIntRetinaFactor();
p.fillRect( p.fillRect(
x + leftWidth, x + leftWidth,
y, y,
width - leftWidth - rightWidth, width - leftWidth - rightWidth,
cornerHeight, cornerHeight,
bg); st->msgServiceBg());
return cornerHeight; return cornerHeight;
} else if (style == SideStyle::Inverted) { } else if (style == SideStyle::Inverted) {
// CornerLeft and CornerRight are inverted for SideStyle::Inverted sprites. // CornerLeft and CornerRight are inverted in the top part.
const auto corner = (int(InvertedMask) * MaskMultiplier) | side; const auto &corners = st->serviceBgCornersInverted();
auto left = circleCorner(corner | CornerRight, bg); const auto left = corners.p[(side == CornerTop) ? 1 : 2];
int leftWidth = left.width() / cIntRetinaFactor(); const auto leftWidth = left.width() / cIntRetinaFactor();
p.drawPixmap(x - leftWidth, y, left); p.drawPixmap(x - leftWidth, y, left);
auto right = circleCorner(corner | CornerLeft, bg); const auto right = corners.p[(side == CornerTop) ? 0 : 3];
p.drawPixmap(x + width, y, right); p.drawPixmap(x + width, y, right);
} }
return 0; return 0;
} }
void paintBubblePart( void PaintBubblePart(
Painter &p, Painter &p,
not_null<const Ui::ChatStyle*> st,
int x, int x,
int y, int y,
int width, int width,
int height, int height,
SideStyle topStyle, SideStyle topStyle,
SideStyle bottomStyle, SideStyle bottomStyle,
const style::color &bg,
bool forceShrink = false) { bool forceShrink = false) {
if ((topStyle == SideStyle::Inverted) if ((topStyle == SideStyle::Inverted)
|| (bottomStyle == SideStyle::Inverted) || (bottomStyle == SideStyle::Inverted)
|| forceShrink) { || forceShrink) {
width -= historyServiceMsgInvertedShrink() * 2; width -= Ui::HistoryServiceMsgInvertedShrink() * 2;
x += historyServiceMsgInvertedShrink(); x += Ui::HistoryServiceMsgInvertedShrink();
} }
if (int skip = paintBubbleSide(p, x, y, width, topStyle, CornerTop, bg)) { if (int skip = PaintBubbleSide(p, st, x, y, width, topStyle, CornerTop)) {
y += skip; y += skip;
height -= skip; height -= skip;
} }
int bottomSize = 0; int bottomSize = 0;
if (bottomStyle == SideStyle::Rounded) { if (bottomStyle == SideStyle::Rounded) {
bottomSize = historyServiceMsgRadius(); bottomSize = Ui::HistoryServiceMsgRadius();
} else if (bottomStyle == SideStyle::Inverted) { } else if (bottomStyle == SideStyle::Inverted) {
bottomSize = historyServiceMsgInvertedRadius(); bottomSize = Ui::HistoryServiceMsgInvertedRadius();
} }
const auto skip = paintBubbleSide( const auto skip = PaintBubbleSide(
p, p,
st,
x, x,
y + height - bottomSize, y + height - bottomSize,
width, width,
bottomStyle, bottomStyle,
CornerBottom, CornerBottom);
bg);
if (skip) { if (skip) {
height -= skip; height -= skip;
} }
p.fillRect(x, y, width, height, bg); p.fillRect(x, y, width, height, st->msgServiceBg());
} }
void paintPreparedDate( void PaintPreparedDate(
Painter &p, Painter &p,
const style::color &bg,
const Ui::CornersPixmaps &corners,
const style::color &fg,
const QString &dateText, const QString &dateText,
int dateTextWidth, int dateTextWidth,
int y, int y,
int w, int w,
bool chatWide, bool chatWide) {
const style::color &bg,
const style::color &fg) {
int left = st::msgServiceMargin.left(); int left = st::msgServiceMargin.left();
const auto maxwidth = chatWide const auto maxwidth = chatWide
? std::min(w, WideChatWidth()) ? std::min(w, WideChatWidth())
@ -238,19 +147,27 @@ void paintPreparedDate(
left += (w - dateTextWidth - st::msgServicePadding.left() - st::msgServicePadding.right()) / 2; left += (w - dateTextWidth - st::msgServicePadding.left() - st::msgServicePadding.right()) / 2;
int height = st::msgServicePadding.top() + st::msgServiceFont->height + st::msgServicePadding.bottom(); int height = st::msgServicePadding.top() + st::msgServiceFont->height + st::msgServicePadding.bottom();
ServiceMessagePainter::paintBubble( ServiceMessagePainter::PaintBubble(
p, p,
left, bg,
y + st::msgServiceMargin.top(), corners,
dateTextWidth QRect(
+ st::msgServicePadding.left() left,
+ st::msgServicePadding.left(), y + st::msgServiceMargin.top(),
height, dateTextWidth
bg); + st::msgServicePadding.left()
+ st::msgServicePadding.left(),
height));
p.setFont(st::msgServiceFont); p.setFont(st::msgServiceFont);
p.setPen(fg); p.setPen(fg);
p.drawText(left + st::msgServicePadding.left(), y + st::msgServiceMargin.top() + st::msgServicePadding.top() + st::msgServiceFont->ascent, dateText); p.drawText(
left + st::msgServicePadding.left(),
(y
+ st::msgServiceMargin.top()
+ st::msgServicePadding.top()
+ st::msgServiceFont->ascent),
dateText);
} }
bool NeedAboutGroup(not_null<History*> history) { bool NeedAboutGroup(not_null<History*> history) {
@ -268,88 +185,112 @@ int WideChatWidth() {
return st::msgMaxWidth + 2 * st::msgPhotoSkip + 2 * st::msgMargin.left(); return st::msgMaxWidth + 2 * st::msgPhotoSkip + 2 * st::msgMargin.left();
} }
void ServiceMessagePainter::paintDate( void ServiceMessagePainter::PaintDate(
Painter &p, Painter &p,
not_null<const Ui::ChatStyle*> st,
const QDateTime &date, const QDateTime &date,
int y, int y,
int w, int w,
bool chatWide, bool chatWide) {
const style::color &bg, PaintDate(
const style::color &fg) { p,
const auto dateText = langDayOfMonthFull(date.date()); st,
const auto dateTextWidth = st::msgServiceFont->width(dateText); langDayOfMonthFull(date.date()),
paintPreparedDate(p, dateText, dateTextWidth, y, w, chatWide, bg, fg); y,
w,
chatWide);
} }
void ServiceMessagePainter::paintDate( void ServiceMessagePainter::PaintDate(
Painter &p, Painter &p,
not_null<const Ui::ChatStyle*> st,
const QString &dateText, const QString &dateText,
int y, int y,
int w, int w,
bool chatWide, bool chatWide) {
const style::color &bg, PaintDate(
const style::color &fg) {
paintPreparedDate(
p, p,
st,
dateText, dateText,
st::msgServiceFont->width(dateText), st::msgServiceFont->width(dateText),
y, y,
w, w,
chatWide, chatWide);
bg,
fg);
} }
void ServiceMessagePainter::paintDate( void ServiceMessagePainter::PaintDate(
Painter &p, Painter &p,
not_null<const Ui::ChatStyle*> st,
const QString &dateText, const QString &dateText,
int dateTextWidth, int dateTextWidth,
int y, int y,
int w, int w,
bool chatWide, bool chatWide) {
const style::color &bg, PaintPreparedDate(
const style::color &fg) {
paintPreparedDate(p, dateText, dateTextWidth, y, w, chatWide, bg, fg);
}
void ServiceMessagePainter::paintBubble(
Painter &p,
int x,
int y,
int w,
int h,
const style::color &bg) {
createCircleMasks();
paintBubblePart(
p, p,
x, st->msgServiceBg(),
st->serviceBgCornersNormal(),
st->msgServiceFg(),
dateText,
dateTextWidth,
y, y,
w, w,
h, chatWide);
SideStyle::Rounded,
SideStyle::Rounded,
bg);
} }
void ServiceMessagePainter::paintComplexBubble( void ServiceMessagePainter::PaintDate(
Painter &p, Painter &p,
const style::color &bg,
const Ui::CornersPixmaps &corners,
const style::color &fg,
const QString &dateText,
int dateTextWidth,
int y,
int w,
bool chatWide) {
PaintPreparedDate(
p,
bg,
corners,
fg,
dateText,
dateTextWidth,
y,
w,
chatWide);
}
void ServiceMessagePainter::PaintBubble(
Painter &p,
not_null<const Ui::ChatStyle*> st,
QRect rect) {
PaintBubble(p, st->msgServiceBg(), st->serviceBgCornersNormal(), rect);
}
void ServiceMessagePainter::PaintBubble(
Painter &p,
const style::color &bg,
const Ui::CornersPixmaps &corners,
QRect rect) {
Ui::FillRoundRect(p, rect, bg, corners);
}
void ServiceMessagePainter::PaintComplexBubble(
Painter &p,
not_null<const Ui::ChatStyle*> st,
int left, int left,
int width, int width,
const Ui::Text::String &text, const Ui::Text::String &text,
const QRect &textRect, const QRect &textRect) {
const style::color &bg) { const auto lineWidths = CountLineWidths(text, textRect);
createCircleMasks();
auto lineWidths = countLineWidths(text, textRect);
int y = st::msgServiceMargin.top(), previousRichWidth = 0; int y = st::msgServiceMargin.top(), previousRichWidth = 0;
bool previousShrink = false, forceShrink = false; bool previousShrink = false, forceShrink = false;
SideStyle topStyle = SideStyle::Rounded, bottomStyle; SideStyle topStyle = SideStyle::Rounded, bottomStyle;
for (int i = 0, count = lineWidths.size(); i < count; ++i) { for (int i = 0, count = lineWidths.size(); i < count; ++i) {
auto lineWidth = lineWidths.at(i); const auto lineWidth = lineWidths[i];
if (i + 1 < count) { if (i + 1 < count) {
auto nextLineWidth = lineWidths.at(i + 1); const auto nextLineWidth = lineWidths[i + 1];
if (nextLineWidth > lineWidth) { if (nextLineWidth > lineWidth) {
bottomStyle = SideStyle::Inverted; bottomStyle = SideStyle::Inverted;
} else if (nextLineWidth < lineWidth) { } else if (nextLineWidth < lineWidth) {
@ -374,15 +315,15 @@ void ServiceMessagePainter::paintComplexBubble(
richHeight -= st::msgServicePadding.top(); richHeight -= st::msgServicePadding.top();
} }
forceShrink = previousShrink && (richWidth == previousRichWidth); forceShrink = previousShrink && (richWidth == previousRichWidth);
paintBubblePart( PaintBubblePart(
p, p,
st,
left + ((width - richWidth) / 2), left + ((width - richWidth) / 2),
y, y,
richWidth, richWidth,
richHeight, richHeight,
topStyle, topStyle,
bottomStyle, bottomStyle,
bg,
forceShrink); forceShrink);
y += richHeight; y += richHeight;
@ -399,38 +340,46 @@ void ServiceMessagePainter::paintComplexBubble(
} }
} }
QVector<int> ServiceMessagePainter::countLineWidths(const Ui::Text::String &text, const QRect &textRect) { QVector<int> ServiceMessagePainter::CountLineWidths(
int linesCount = qMax(textRect.height() / st::msgServiceFont->height, 1); const Ui::Text::String &text,
QVector<int> lineWidths; const QRect &textRect) {
lineWidths.reserve(linesCount); const auto linesCount = qMax(
text.countLineWidths(textRect.width(), &lineWidths); textRect.height() / st::msgServiceFont->height,
1);
auto result = QVector<int>();
result.reserve(linesCount);
text.countLineWidths(textRect.width(), &result);
int minDelta = 2 * (historyServiceMsgRadius() + historyServiceMsgInvertedRadius() - historyServiceMsgInvertedShrink()); const auto minDelta = 2 * (Ui::HistoryServiceMsgRadius()
for (int i = 0, count = lineWidths.size(); i < count; ++i) { + Ui::HistoryServiceMsgInvertedRadius()
int width = qMax(lineWidths.at(i), 0); - Ui::HistoryServiceMsgInvertedShrink());
for (int i = 0, count = result.size(); i != count; ++i) {
auto width = qMax(result[i], 0);
if (i > 0) { if (i > 0) {
int widthBefore = lineWidths.at(i - 1); const auto widthBefore = result[i - 1];
if (width < widthBefore && width + minDelta > widthBefore) { if (width < widthBefore && width + minDelta > widthBefore) {
width = widthBefore; width = widthBefore;
} }
} }
if (i + 1 < count) { if (i + 1 < count) {
int widthAfter = lineWidths.at(i + 1); const auto widthAfter = result[i + 1];
if (width < widthAfter && width + minDelta > widthAfter) { if (width < widthAfter && width + minDelta > widthAfter) {
width = widthAfter; width = widthAfter;
} }
} }
if (width > lineWidths.at(i)) { if (width > result[i]) {
lineWidths[i] = width; result[i] = width;
if (i > 0) { if (i > 0) {
int widthBefore = lineWidths.at(i - 1); int widthBefore = result[i - 1];
if (widthBefore != width && widthBefore < width + minDelta && widthBefore + minDelta > width) { if (widthBefore != width
&& widthBefore < width + minDelta
&& widthBefore + minDelta > width) {
i -= 2; i -= 2;
} }
} }
} }
} }
return lineWidths; return result;
} }
Service::Service( Service::Service(
@ -527,7 +476,10 @@ void Service::draw(Painter &p, const PaintContext &context) const {
return; return;
} }
auto height = this->height() - st::msgServiceMargin.top() - st::msgServiceMargin.bottom(); const auto st = context.st;
auto height = this->height()
- st::msgServiceMargin.top()
- st::msgServiceMargin.bottom();
auto dateh = 0; auto dateh = 0;
auto unreadbarh = 0; auto unreadbarh = 0;
auto clip = context.clip; auto clip = context.clip;
@ -540,7 +492,12 @@ void Service::draw(Painter &p, const PaintContext &context) const {
if (const auto bar = Get<UnreadBar>()) { if (const auto bar = Get<UnreadBar>()) {
unreadbarh = bar->height(); unreadbarh = bar->height();
if (clip.intersects(QRect(0, 0, width(), unreadbarh))) { if (clip.intersects(QRect(0, 0, width(), unreadbarh))) {
bar->paint(p, 0, width(), delegate()->elementIsChatWide()); bar->paint(
p,
context,
0,
width(),
delegate()->elementIsChatWide());
} }
p.translate(0, unreadbarh); p.translate(0, unreadbarh);
clip.translate(0, -unreadbarh); clip.translate(0, -unreadbarh);
@ -554,9 +511,9 @@ void Service::draw(Painter &p, const PaintContext &context) const {
return; return;
} }
paintHighlight(p, height); paintHighlight(p, context, height);
p.setTextPalette(st::serviceTextPalette); p.setTextPalette(st->serviceTextPalette());
if (auto media = this->media()) { if (auto media = this->media()) {
height -= st::msgServiceMargin.top() + media->height(); height -= st::msgServiceMargin.top() + media->height();
@ -568,10 +525,16 @@ void Service::draw(Painter &p, const PaintContext &context) const {
auto trect = QRect(g.left(), st::msgServiceMargin.top(), g.width(), height).marginsAdded(-st::msgServicePadding); auto trect = QRect(g.left(), st::msgServiceMargin.top(), g.width(), height).marginsAdded(-st::msgServicePadding);
ServiceMessagePainter::paintComplexBubble(p, g.left(), g.width(), item->_text, trect); ServiceMessagePainter::PaintComplexBubble(
p,
context.st,
g.left(),
g.width(),
item->_text,
trect);
p.setBrush(Qt::NoBrush); p.setBrush(Qt::NoBrush);
p.setPen(st::msgServiceFg); p.setPen(st->msgServiceFg());
p.setFont(st::msgServiceFont); p.setFont(st::msgServiceFont);
item->_text.draw(p, trect.x(), trect.y(), trect.width(), Qt::AlignCenter, 0, -1, context.selection, false); item->_text.draw(p, trect.x(), trect.y(), trect.width(), Qt::AlignCenter, 0, -1, context.selection, false);
@ -694,7 +657,11 @@ void EmptyPainter::fillAboutGroup() {
} }
} }
void EmptyPainter::paint(Painter &p, int width, int height) { void EmptyPainter::paint(
Painter &p,
not_null<const Ui::ChatStyle*> st,
int width,
int height) {
if (_phrases.empty()) { if (_phrases.empty()) {
return; return;
} }
@ -731,15 +698,14 @@ void EmptyPainter::paint(Painter &p, int width, int height) {
const auto bubbleLeft = (width - bubbleWidth) / 2; const auto bubbleLeft = (width - bubbleWidth) / 2;
const auto bubbleTop = (height - bubbleHeight) / 2; const auto bubbleTop = (height - bubbleHeight) / 2;
ServiceMessagePainter::paintBubble( ServiceMessagePainter::PaintBubble(
p, p,
bubbleLeft, st->msgServiceBg(),
bubbleTop, st->serviceBgCornersNormal(),
bubbleWidth, QRect(bubbleLeft, bubbleTop, bubbleWidth, bubbleHeight));
bubbleHeight);
p.setPen(st::msgServiceFg); p.setPen(st->msgServiceFg());
p.setBrush(st::msgServiceFg); p.setBrush(st->msgServiceFg());
const auto left = bubbleLeft + padding.left(); const auto left = bubbleLeft + padding.left();
auto top = bubbleTop + padding.top(); auto top = bubbleTop + padding.top();
@ -762,7 +728,7 @@ void EmptyPainter::paint(Painter &p, int width, int height) {
top += textHeight(_text) + st::historyGroupAboutTextSkip; top += textHeight(_text) + st::historyGroupAboutTextSkip;
for (const auto &text : _phrases) { for (const auto &text : _phrases) {
p.setPen(st::msgServiceFg); p.setPen(st->msgServiceFg());
text.drawElided( text.drawElided(
p, p,
left + st::historyGroupAboutBulletSkip, left + st::historyGroupAboutBulletSkip,

View file

@ -11,6 +11,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class HistoryService; class HistoryService;
namespace Ui {
class ChatStyle;
struct CornersPixmaps;
} // namespace Ui
namespace HistoryView { namespace HistoryView {
class Service : public Element { class Service : public Element {
@ -48,50 +53,61 @@ int WideChatWidth();
class ServiceMessagePainter { class ServiceMessagePainter {
public: public:
static void paintDate( static void PaintDate(
Painter &p, Painter &p,
not_null<const Ui::ChatStyle*> st,
const QDateTime &date, const QDateTime &date,
int y, int y,
int w, int w,
bool chatWide, bool chatWide);
const style::color &bg = st::msgServiceBg, static void PaintDate(
const style::color &fg = st::msgServiceFg);
static void paintDate(
Painter &p, Painter &p,
not_null<const Ui::ChatStyle*> st,
const QString &dateText, const QString &dateText,
int y, int y,
int w, int w,
bool chatWide, bool chatWide);
const style::color &bg = st::msgServiceBg, static void PaintDate(
const style::color &fg = st::msgServiceFg);
static void paintDate(
Painter &p, Painter &p,
not_null<const Ui::ChatStyle*> st,
const QString &dateText, const QString &dateText,
int dateTextWidth, int dateTextWidth,
int y, int y,
int w, int w,
bool chatWide, bool chatWide);
const style::color &bg = st::msgServiceBg, static void PaintDate(
const style::color &fg = st::msgServiceFg);
static void paintBubble(
Painter &p, Painter &p,
int x, const style::color &bg,
const Ui::CornersPixmaps &corners,
const style::color &fg,
const QString &dateText,
int dateTextWidth,
int y, int y,
int w, int w,
int h, bool chatWide);
const style::color &bg = st::msgServiceBg);
static void paintComplexBubble( static void PaintBubble(
Painter &p, Painter &p,
not_null<const Ui::ChatStyle*> st,
QRect rect);
static void PaintBubble(
Painter &p,
const style::color &bg,
const Ui::CornersPixmaps &corners,
QRect rect);
static void PaintComplexBubble(
Painter &p,
not_null<const Ui::ChatStyle*> st,
int left, int left,
int width, int width,
const Ui::Text::String &text, const Ui::Text::String &text,
const QRect &textRect, const QRect &textRect);
const style::color &bg = st::msgServiceBg);
private: private:
static QVector<int> countLineWidths(const Ui::Text::String &text, const QRect &textRect); static QVector<int> CountLineWidths(
const Ui::Text::String &text,
const QRect &textRect);
}; };
@ -99,7 +115,11 @@ class EmptyPainter {
public: public:
explicit EmptyPainter(not_null<History*> history); explicit EmptyPainter(not_null<History*> history);
void paint(Painter &p, int width, int height); void paint(
Painter &p,
not_null<const Ui::ChatStyle*> st,
int width,
int height);
private: private:
void fillAboutGroup(); void fillAboutGroup();

View file

@ -86,7 +86,10 @@ public:
} }
virtual void refreshParentId(not_null<HistoryItem*> realParent) { virtual void refreshParentId(not_null<HistoryItem*> realParent) {
} }
virtual void drawHighlight(Painter &p, int top) const { virtual void drawHighlight(
Painter &p,
const PaintContext &context,
int top) const {
} }
virtual void draw(Painter &p, const PaintContext &context) const = 0; virtual void draw(Painter &p, const PaintContext &context) const = 0;
[[nodiscard]] virtual PointState pointState(QPoint point) const; [[nodiscard]] virtual PointState pointState(QPoint point) const;

View file

@ -270,7 +270,10 @@ QMargins GroupedMedia::groupedPadding() const {
(normal.bottom() - grouped.bottom()) + addToBottom); (normal.bottom() - grouped.bottom()) + addToBottom);
} }
void GroupedMedia::drawHighlight(Painter &p, int top) const { void GroupedMedia::drawHighlight(
Painter &p,
const PaintContext &context,
int top) const {
if (_mode != Mode::Column) { if (_mode != Mode::Column) {
return; return;
} }
@ -278,7 +281,12 @@ void GroupedMedia::drawHighlight(Painter &p, int top) const {
for (auto i = 0, count = int(_parts.size()); i != count; ++i) { for (auto i = 0, count = int(_parts.size()); i != count; ++i) {
const auto &part = _parts[i]; const auto &part = _parts[i];
const auto rect = part.geometry.translated(0, skip); const auto rect = part.geometry.translated(0, skip);
_parent->paintCustomHighlight(p, rect.y(), rect.height(), part.item); _parent->paintCustomHighlight(
p,
context,
rect.y(),
rect.height(),
part.item);
} }
} }

View file

@ -31,7 +31,10 @@ public:
void refreshParentId(not_null<HistoryItem*> realParent) override; void refreshParentId(not_null<HistoryItem*> realParent) override;
void drawHighlight(Painter &p, int top) const override; void drawHighlight(
Painter &p,
const PaintContext &context,
int top) const override;
void draw(Painter &p, const PaintContext &context) const override; void draw(Painter &p, const PaintContext &context) const override;
PointState pointState(QPoint point) const override; PointState pointState(QPoint point) const override;
TextState textState( TextState textState(

View file

@ -25,6 +25,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_peer_menu.h" #include "window/window_peer_menu.h"
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
#include "ui/controls/delete_message_context_action.h" #include "ui/controls/delete_message_context_action.h"
#include "ui/chat/chat_style.h"
#include "ui/cached_round_corners.h"
#include "ui/ui_utility.h" #include "ui/ui_utility.h"
#include "ui/inactive_press.h" #include "ui/inactive_press.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
@ -94,6 +96,20 @@ struct ListWidget::Context {
DragSelectAction dragSelectAction; DragSelectAction dragSelectAction;
}; };
struct ListWidget::DateBadge {
DateBadge(Type type, Fn<void()> checkCallback, Fn<void()> hideCallback);
SingleQueuedInvokation check;
base::Timer hideTimer;
Ui::Animations::Simple opacity;
Ui::CornersPixmaps corners;
bool goodType = false;
bool shown = false;
QString text;
int textWidth = 0;
QRect rect;
};
class ListWidget::Section { class ListWidget::Section {
public: public:
Section(Type type) Section(Type type)
@ -228,6 +244,17 @@ ListWidget::CachedItem &ListWidget::CachedItem::operator=(
ListWidget::CachedItem::~CachedItem() = default; ListWidget::CachedItem::~CachedItem() = default;
ListWidget::DateBadge::DateBadge(
Type type,
Fn<void()> checkCallback,
Fn<void()> hideCallback)
: check(std::move(checkCallback))
, hideTimer(std::move(hideCallback))
, goodType(type == Type::Photo
|| type == Type::Video
|| type == Type::GIF) {
}
bool ListWidget::Section::addItem(not_null<BaseLayout*> item) { bool ListWidget::Section::addItem(not_null<BaseLayout*> item) {
if (_items.empty() || belongsHere(item)) { if (_items.empty() || belongsHere(item)) {
if (_items.empty()) setHeader(item); if (_items.empty()) setHeader(item);
@ -664,13 +691,10 @@ ListWidget::ListWidget(
, _migrated(_controller->migrated()) , _migrated(_controller->migrated())
, _type(_controller->section().mediaType()) , _type(_controller->section().mediaType())
, _slice(sliceKey(_universalAroundId)) , _slice(sliceKey(_universalAroundId))
, _dateBadge(DateBadge{ , _dateBadge(std::make_unique<DateBadge>(
.check = SingleQueuedInvokation([=] { scrollDateCheck(); }), _type,
.hideTimer = base::Timer([=] { scrollDateHide(); }), [=] { scrollDateCheck(); },
.goodType = (_type == Type::Photo [=] { scrollDateHide(); })) {
|| _type == Type::Video
|| _type == Type::GIF),
}) {
setMouseTracking(true); setMouseTracking(true);
start(); start();
} }
@ -1204,16 +1228,16 @@ void ListWidget::visibleTopBottomUpdated(
checkMoveToOtherViewer(); checkMoveToOtherViewer();
clearHeavyItems(); clearHeavyItems();
if (_dateBadge.goodType) { if (_dateBadge->goodType) {
updateDateBadgeFor(_visibleTop); updateDateBadgeFor(_visibleTop);
if (!_visibleTop) { if (!_visibleTop) {
if (_dateBadge.shown) { if (_dateBadge->shown) {
scrollDateHide(); scrollDateHide();
} else { } else {
update(_dateBadge.rect); update(_dateBadge->rect);
} }
} else { } else {
_dateBadge.check.call(); _dateBadge->check.call();
} }
} }
} }
@ -1228,29 +1252,30 @@ void ListWidget::updateDateBadgeFor(int top) {
+ st::msgServiceFont->height + st::msgServiceFont->height
+ st::msgServicePadding.bottom(); + st::msgServicePadding.bottom();
_dateBadge.text = ItemDateText(layout->getItem(), false); _dateBadge->text = ItemDateText(layout->getItem(), false);
_dateBadge.rect = QRect(0, top, width(), rectHeight); _dateBadge->textWidth = st::msgServiceFont->width(_dateBadge->text);
_dateBadge->rect = QRect(0, top, width(), rectHeight);
} }
void ListWidget::scrollDateCheck() { void ListWidget::scrollDateCheck() {
if (!_dateBadge.shown) { if (!_dateBadge->shown) {
toggleScrollDateShown(); toggleScrollDateShown();
} }
_dateBadge.hideTimer.callOnce(st::infoScrollDateHideTimeout); _dateBadge->hideTimer.callOnce(st::infoScrollDateHideTimeout);
} }
void ListWidget::scrollDateHide() { void ListWidget::scrollDateHide() {
if (_dateBadge.shown) { if (_dateBadge->shown) {
toggleScrollDateShown(); toggleScrollDateShown();
} }
} }
void ListWidget::toggleScrollDateShown() { void ListWidget::toggleScrollDateShown() {
_dateBadge.shown = !_dateBadge.shown; _dateBadge->shown = !_dateBadge->shown;
_dateBadge.opacity.start( _dateBadge->opacity.start(
[=] { update(_dateBadge.rect); }, [=] { update(_dateBadge->rect); },
_dateBadge.shown ? 0. : 1., _dateBadge->shown ? 0. : 1.,
_dateBadge.shown ? 1. : 0., _dateBadge->shown ? 1. : 0.,
st::infoDateFadeDuration); st::infoDateFadeDuration);
} }
@ -1403,19 +1428,27 @@ void ListWidget::paintEvent(QPaintEvent *e) {
fromSectionIt->paintFloatingHeader(p, _visibleTop, outerWidth); fromSectionIt->paintFloatingHeader(p, _visibleTop, outerWidth);
} }
if (_dateBadge.goodType && clip.intersects(_dateBadge.rect)) { if (_dateBadge->goodType && clip.intersects(_dateBadge->rect)) {
const auto scrollDateOpacity = const auto scrollDateOpacity =
_dateBadge.opacity.value(_dateBadge.shown ? 1. : 0.); _dateBadge->opacity.value(_dateBadge->shown ? 1. : 0.);
if (scrollDateOpacity > 0.) { if (scrollDateOpacity > 0.) {
p.setOpacity(scrollDateOpacity); p.setOpacity(scrollDateOpacity);
HistoryView::ServiceMessagePainter::paintDate( if (_dateBadge->corners.p[0].isNull()) {
_dateBadge->corners = Ui::PrepareCornerPixmaps(
Ui::HistoryServiceMsgRadius(),
st::roundedBg,
nullptr);
}
HistoryView::ServiceMessagePainter::PaintDate(
p, p,
_dateBadge.text, st::roundedBg,
_dateBadge->corners,
st::roundedFg,
_dateBadge->text,
_dateBadge->textWidth,
_visibleTop, _visibleTop,
outerWidth, outerWidth,
false, false);
st::roundedBg,
st::roundedFg);
} }
} }
} }

View file

@ -90,6 +90,7 @@ public:
private: private:
struct Context; struct Context;
struct DateBadge;
class Section; class Section;
using CursorState = HistoryView::CursorState; using CursorState = HistoryView::CursorState;
using TextState = HistoryView::TextState; using TextState = HistoryView::TextState;
@ -331,15 +332,7 @@ private:
DragSelectAction _dragSelectAction = DragSelectAction::None; DragSelectAction _dragSelectAction = DragSelectAction::None;
bool _wasSelectedText = false; // was some text selected in current drag action bool _wasSelectedText = false; // was some text selected in current drag action
struct DateBadge { const std::unique_ptr<DateBadge> _dateBadge;
SingleQueuedInvokation check;
base::Timer hideTimer;
Ui::Animations::Simple opacity;
bool goodType = false;
bool shown = false;
QString text;
QRect rect;
} _dateBadge;
base::unique_qptr<Ui::PopupMenu> _contextMenu; base::unique_qptr<Ui::PopupMenu> _contextMenu;
rpl::event_stream<> _checkForHide; rpl::event_stream<> _checkForHide;

View file

@ -95,9 +95,6 @@ void CreatePaletteCorners() {
PrepareCorners(Doc4Corners, st::roundRadiusSmall, st::msgFile4Bg); PrepareCorners(Doc4Corners, st::roundRadiusSmall, st::msgFile4Bg);
PrepareCorners(MessageInCorners, st::historyMessageRadius, st::msgInBg, &st::msgInShadow); PrepareCorners(MessageInCorners, st::historyMessageRadius, st::msgInBg, &st::msgInShadow);
PrepareCorners(MessageInSelectedCorners, st::historyMessageRadius, st::msgInBgSelected, &st::msgInShadowSelected);
PrepareCorners(MessageOutCorners, st::historyMessageRadius, st::msgOutBg, &st::msgOutShadow);
PrepareCorners(MessageOutSelectedCorners, st::historyMessageRadius, st::msgOutBgSelected, &st::msgOutShadowSelected);
} }
} // namespace } // namespace

View file

@ -43,9 +43,6 @@ enum CachedRoundCorners : int {
InSelectedShadowCorners, InSelectedShadowCorners,
MessageInCorners, // with shadow MessageInCorners, // with shadow
MessageInSelectedCorners,
MessageOutCorners,
MessageOutSelectedCorners,
RoundCornersCount RoundCornersCount
}; };

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/chat/chat_style.h" #include "ui/chat/chat_style.h"
#include "ui/chat/chat_theme.h" #include "ui/chat/chat_theme.h"
#include "ui/ui_utility.h"
#include "styles/style_chat.h" #include "styles/style_chat.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
@ -30,10 +31,36 @@ not_null<const MessageStyle*> ChatPaintContext::messageStyle() const {
return &st->messageStyle(outbg, selected()); return &st->messageStyle(outbg, selected());
} }
int HistoryServiceMsgRadius() {
static const auto result = [] {
const auto minMessageHeight = st::msgServicePadding.top()
+ st::msgServiceFont->height
+ st::msgServicePadding.bottom();
return minMessageHeight / 2;
}();
return result;
}
int HistoryServiceMsgInvertedRadius() {
static const auto result = [] {
const auto minRowHeight = st::msgServiceFont->height;
return minRowHeight - HistoryServiceMsgRadius();
}();
return result;
}
int HistoryServiceMsgInvertedShrink() {
static const auto result = [] {
return (HistoryServiceMsgInvertedRadius() * 2) / 3;
}();
return result;
}
ChatStyle::ChatStyle() { ChatStyle::ChatStyle() {
finalize(); finalize();
make(_historyPsaForwardPalette, st::historyPsaForwardPalette); make(_historyPsaForwardPalette, st::historyPsaForwardPalette);
make(_imgReplyTextPalette, st::imgReplyTextPalette); make(_imgReplyTextPalette, st::imgReplyTextPalette);
make(_serviceTextPalette, st::serviceTextPalette);
make(_historyRepliesInvertedIcon, st::historyRepliesInvertedIcon); make(_historyRepliesInvertedIcon, st::historyRepliesInvertedIcon);
make(_historyViewsInvertedIcon, st::historyViewsInvertedIcon); make(_historyViewsInvertedIcon, st::historyViewsInvertedIcon);
make(_historyViewsSendingIcon, st::historyViewsSendingIcon); make(_historyViewsSendingIcon, st::historyViewsSendingIcon);
@ -212,9 +239,41 @@ void ChatStyle::assignPalette(not_null<const style::palette*> palette) {
for (auto &style : _messageStyles) { for (auto &style : _messageStyles) {
style.corners = {}; style.corners = {};
} }
_serviceBgCornersNormal = {};
_serviceBgCornersInverted = {};
_msgServiceBgCorners = {}; _msgServiceBgCorners = {};
_msgServiceBgSelectedCorners = {}; _msgServiceBgSelectedCorners = {};
_msgBotKbOverBgAddCorners = {}; _msgBotKbOverBgAddCorners = {};
_msgDateImgBgCorners = {};
_msgDateImgBgSelectedCorners = {};
}
const CornersPixmaps &ChatStyle::serviceBgCornersNormal() const {
EnsureCorners(
_serviceBgCornersNormal,
HistoryServiceMsgRadius(),
msgServiceBg());
return _serviceBgCornersNormal;
}
const CornersPixmaps &ChatStyle::serviceBgCornersInverted() const {
if (_serviceBgCornersInverted.p[0].isNull()) {
const auto radius = HistoryServiceMsgInvertedRadius();
const auto size = radius * style::DevicePixelRatio();
auto circle = style::colorizeImage(
style::createInvertedCircleMask(radius * 2),
msgServiceBg());
circle.setDevicePixelRatio(style::DevicePixelRatio());
const auto fill = [&](int index, int xoffset, int yoffset) {
_serviceBgCornersInverted.p[index] = PixmapFromImage(
circle.copy(QRect(xoffset, yoffset, size, size)));
};
fill(0, 0, 0);
fill(1, size, 0);
fill(2, size, size);
fill(3, 0, size);
}
return _serviceBgCornersInverted;
} }
const MessageStyle &ChatStyle::messageStyle(bool outbg, bool selected) const { const MessageStyle &ChatStyle::messageStyle(bool outbg, bool selected) const {

View file

@ -83,12 +83,19 @@ struct ChatPaintContext {
}; };
[[nodiscard]] int HistoryServiceMsgRadius();
[[nodiscard]] int HistoryServiceMsgInvertedRadius();
[[nodiscard]] int HistoryServiceMsgInvertedShrink();
class ChatStyle final : public style::palette { class ChatStyle final : public style::palette {
public: public:
ChatStyle(); ChatStyle();
void apply(not_null<ChatTheme*> theme); void apply(not_null<ChatTheme*> theme);
[[nodiscard]] const CornersPixmaps &serviceBgCornersNormal() const;
[[nodiscard]] const CornersPixmaps &serviceBgCornersInverted() const;
[[nodiscard]] const MessageStyle &messageStyle( [[nodiscard]] const MessageStyle &messageStyle(
bool outbg, bool outbg,
bool selected) const; bool selected) const;
@ -105,6 +112,9 @@ public:
[[nodiscard]] const style::TextPalette &imgReplyTextPalette() const { [[nodiscard]] const style::TextPalette &imgReplyTextPalette() const {
return _imgReplyTextPalette; return _imgReplyTextPalette;
} }
[[nodiscard]] const style::TextPalette &serviceTextPalette() const {
return _serviceTextPalette;
}
[[nodiscard]] const style::icon &historyRepliesInvertedIcon() const { [[nodiscard]] const style::icon &historyRepliesInvertedIcon() const {
return _historyRepliesInvertedIcon; return _historyRepliesInvertedIcon;
} }
@ -174,6 +184,9 @@ private:
const Type &originalOut, const Type &originalOut,
const Type &originalOutSelected); const Type &originalOutSelected);
mutable CornersPixmaps _serviceBgCornersNormal;
mutable CornersPixmaps _serviceBgCornersInverted;
mutable std::array<MessageStyle, 4> _messageStyles; mutable std::array<MessageStyle, 4> _messageStyles;
mutable CornersPixmaps _msgServiceBgCorners; mutable CornersPixmaps _msgServiceBgCorners;
@ -184,6 +197,7 @@ private:
style::TextPalette _historyPsaForwardPalette; style::TextPalette _historyPsaForwardPalette;
style::TextPalette _imgReplyTextPalette; style::TextPalette _imgReplyTextPalette;
style::TextPalette _serviceTextPalette;
style::icon _historyRepliesInvertedIcon = { Qt::Uninitialized }; style::icon _historyRepliesInvertedIcon = { Qt::Uninitialized };
style::icon _historyViewsInvertedIcon = { Qt::Uninitialized }; style::icon _historyViewsInvertedIcon = { Qt::Uninitialized };
style::icon _historyViewsSendingIcon = { Qt::Uninitialized }; style::icon _historyViewsSendingIcon = { Qt::Uninitialized };

View file

@ -416,6 +416,9 @@ public:
}; };
[[nodiscard]] Ui::ChatPaintContext preparePaintContext( [[nodiscard]] Ui::ChatPaintContext preparePaintContext(
PaintContextArgs &&args); PaintContextArgs &&args);
[[nodiscard]] not_null<const Ui::ChatStyle*> chatStyle() const {
return _chatStyle.get();
}
rpl::lifetime &lifetime() { rpl::lifetime &lifetime() {
return _lifetime; return _lifetime;
@ -486,7 +489,7 @@ private:
std::shared_ptr<Ui::ChatTheme> _defaultChatTheme; std::shared_ptr<Ui::ChatTheme> _defaultChatTheme;
base::flat_map<uint64, CachedTheme> _customChatThemes; base::flat_map<uint64, CachedTheme> _customChatThemes;
rpl::event_stream<std::shared_ptr<Ui::ChatTheme>> _cachedThemesStream; rpl::event_stream<std::shared_ptr<Ui::ChatTheme>> _cachedThemesStream;
std::unique_ptr<Ui::ChatStyle> _chatStyle; const std::unique_ptr<Ui::ChatStyle> _chatStyle;
std::weak_ptr<Ui::ChatTheme> _chatStyleTheme; std::weak_ptr<Ui::ChatTheme> _chatStyleTheme;
rpl::lifetime _lifetime; rpl::lifetime _lifetime;