mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 14:17:12 +02:00
Use outbox bubble colors, adjust custom colors.
This commit is contained in:
parent
e4e5c4a1d2
commit
c318f57fc0
18 changed files with 208 additions and 98 deletions
|
@ -914,6 +914,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) {
|
|||
.theme = _theme.get(),
|
||||
.visibleAreaTop = _visibleTop,
|
||||
.visibleAreaTopGlobal = mapToGlobal(QPoint(0, _visibleTop)).y(),
|
||||
.visibleAreaWidth = width(),
|
||||
.clip = clip,
|
||||
});
|
||||
if (_items.empty() && _upLoaded && _downLoaded) {
|
||||
|
|
|
@ -579,6 +579,7 @@ void HistoryInner::paintEvent(QPaintEvent *e) {
|
|||
.theme = _theme.get(),
|
||||
.visibleAreaTop = _visibleAreaTop,
|
||||
.visibleAreaTopGlobal = visibleAreaTopGlobal,
|
||||
.visibleAreaWidth = width(),
|
||||
.clip = clip,
|
||||
});
|
||||
_pathGradient->startFrame(
|
||||
|
|
|
@ -1625,6 +1625,7 @@ void ListWidget::paintEvent(QPaintEvent *e) {
|
|||
.theme = _delegate->listChatTheme(),
|
||||
.visibleAreaTop = _visibleTop,
|
||||
.visibleAreaTopGlobal = mapToGlobal(QPoint(0, _visibleTop)).y(),
|
||||
.visibleAreaWidth = width(),
|
||||
.clip = clip,
|
||||
}).translated(0, -top);
|
||||
p.translate(0, top);
|
||||
|
|
|
@ -232,7 +232,7 @@ void Game::draw(Painter &p, const PaintContext &context) const {
|
|||
tshift += _titleLines * lineHeight;
|
||||
}
|
||||
if (_descriptionLines) {
|
||||
p.setPen(stm->webPageDescriptionFg);
|
||||
p.setPen(stm->historyTextFg);
|
||||
auto endskip = 0;
|
||||
if (_description.hasSkipBlock()) {
|
||||
endskip = _parent->skipBlockWidth();
|
||||
|
|
|
@ -233,7 +233,7 @@ void Invoice::draw(Painter &p, const PaintContext &context) const {
|
|||
p.setTextPalette(stm->textPalette);
|
||||
}
|
||||
if (_descriptionHeight) {
|
||||
p.setPen(stm->webPageDescriptionFg);
|
||||
p.setPen(stm->historyTextFg);
|
||||
_description.drawLeft(p, padding.left(), tshift, paintw, width(), style::al_left, 0, -1, toDescriptionSelection(context.selection));
|
||||
tshift += _descriptionHeight;
|
||||
}
|
||||
|
@ -268,7 +268,7 @@ void Invoice::draw(Painter &p, const PaintContext &context) const {
|
|||
|
||||
p.translate(-attachLeft, -attachTop);
|
||||
} else {
|
||||
p.setPen(stm->webPageDescriptionFg);
|
||||
p.setPen(stm->historyTextFg);
|
||||
_status.drawLeft(p, padding.left(), tshift + st::mediaInBubbleSkip, paintw, width());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -165,13 +165,12 @@ void Location::draw(Painter &p, const PaintContext &context) const {
|
|||
|
||||
auto textw = width() - st::msgPadding.left() - st::msgPadding.right();
|
||||
|
||||
p.setPen(stm->historyTextFg);
|
||||
if (!_title.isEmpty()) {
|
||||
p.setPen(stm->webPageTitleFg);
|
||||
_title.drawLeftElided(p, paintx + st::msgPadding.left(), painty, textw, width(), 2, style::al_left, 0, -1, 0, false, context.selection);
|
||||
painty += qMin(_title.countHeight(textw), 2 * st::webPageTitleFont->height);
|
||||
}
|
||||
if (!_description.isEmpty()) {
|
||||
p.setPen(stm->webPageDescriptionFg);
|
||||
_description.drawLeftElided(p, paintx + st::msgPadding.left(), painty, textw, width(), 3, style::al_left, 0, -1, 0, false, toDescriptionSelection(context.selection));
|
||||
painty += qMin(_description.countHeight(textw), 3 * st::webPageDescriptionFont->height);
|
||||
}
|
||||
|
|
|
@ -731,7 +731,7 @@ void Poll::draw(Painter &p, const PaintContext &context) const {
|
|||
}
|
||||
paintw -= padding.left() + padding.right();
|
||||
|
||||
p.setPen(stm->webPageTitleFg);
|
||||
p.setPen(stm->historyTextFg);
|
||||
_question.drawLeft(p, padding.left(), tshift, paintw, width(), style::al_left, 0, -1, context.selection);
|
||||
tshift += _question.countHeight(paintw) + st::historyPollSubtitleSkip;
|
||||
|
||||
|
@ -1099,7 +1099,7 @@ int Poll::paintAnswer(
|
|||
}
|
||||
|
||||
top += st::historyPollAnswerPadding.top();
|
||||
p.setPen(stm->webPageDescriptionFg);
|
||||
p.setPen(stm->historyTextFg);
|
||||
answer.text.drawLeft(p, aleft, top, awidth, outerWidth);
|
||||
|
||||
return height;
|
||||
|
@ -1182,7 +1182,7 @@ void Poll::paintPercent(
|
|||
top += st::historyPollAnswerPadding.top();
|
||||
|
||||
p.setFont(st::historyPollPercentFont);
|
||||
p.setPen(stm->webPageDescriptionFg);
|
||||
p.setPen(stm->historyTextFg);
|
||||
const auto pleft = aleft - percentWidth - st::historyPollPercentSkip;
|
||||
p.drawTextLeft(pleft, top + st::historyPollPercentTop, outerWidth, percent, percentWidth);
|
||||
}
|
||||
|
|
|
@ -521,8 +521,8 @@ void WebPage::draw(Painter &p, const PaintContext &context) const {
|
|||
_siteName.drawLeftElided(p, padding.left(), tshift, paintw, width(), _siteNameLines, style::al_left, 0, -1, endskip, false, context.selection);
|
||||
tshift += lineHeight;
|
||||
}
|
||||
p.setPen(stm->historyTextFg);
|
||||
if (_titleLines) {
|
||||
p.setPen(stm->webPageTitleFg);
|
||||
auto endskip = 0;
|
||||
if (_title.hasSkipBlock()) {
|
||||
endskip = _parent->skipBlockWidth();
|
||||
|
@ -531,7 +531,6 @@ void WebPage::draw(Painter &p, const PaintContext &context) const {
|
|||
tshift += _titleLines * lineHeight;
|
||||
}
|
||||
if (_descriptionLines) {
|
||||
p.setPen(stm->webPageDescriptionFg);
|
||||
auto endskip = 0;
|
||||
if (_description.hasSkipBlock()) {
|
||||
endskip = _parent->skipBlockWidth();
|
||||
|
|
|
@ -690,10 +690,6 @@ webPageLeft: 10px;
|
|||
webPageBar: 2px;
|
||||
webPageTitleFont: semiboldFont;
|
||||
webPageTitleStyle: semiboldTextStyle;
|
||||
webPageTitleOutFg: historyTextOutFg;
|
||||
webPageTitleInFg: historyTextInFg;
|
||||
webPageDescriptionOutFg: historyTextOutFg;
|
||||
webPageDescriptionInFg: historyTextInFg;
|
||||
webPageDescriptionFont: normalFont;
|
||||
webPageDescriptionStyle: defaultTextStyle;
|
||||
webPagePhotoSize: 100px;
|
||||
|
|
|
@ -211,18 +211,6 @@ ChatStyle::ChatStyle() {
|
|||
st::mediaInFgSelected,
|
||||
st::mediaOutFg,
|
||||
st::mediaOutFgSelected);
|
||||
make(
|
||||
&MessageStyle::webPageTitleFg,
|
||||
st::webPageTitleInFg,
|
||||
st::webPageTitleInFg,
|
||||
st::webPageTitleOutFg,
|
||||
st::webPageTitleOutFg);
|
||||
make(
|
||||
&MessageStyle::webPageDescriptionFg,
|
||||
st::webPageDescriptionInFg,
|
||||
st::webPageDescriptionInFg,
|
||||
st::webPageDescriptionOutFg,
|
||||
st::webPageDescriptionOutFg);
|
||||
make(
|
||||
&MessageStyle::textPalette,
|
||||
st::inTextPalette,
|
||||
|
|
|
@ -38,8 +38,6 @@ struct MessageStyle {
|
|||
style::color historyFileNameFg;
|
||||
style::color historyFileRadialFg;
|
||||
style::color mediaFg;
|
||||
style::color webPageTitleFg;
|
||||
style::color webPageDescriptionFg;
|
||||
style::TextPalette textPalette;
|
||||
style::TextPalette semiboldPalette;
|
||||
style::TextPalette fwdTextPalette;
|
||||
|
|
|
@ -124,6 +124,15 @@ constexpr auto kMaxSize = 2960;
|
|||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] QImage PrepareBubblesBackground(
|
||||
const ChatThemeBubblesData &data) {
|
||||
if (data.colors.size() < 2) {
|
||||
return QImage();
|
||||
}
|
||||
constexpr auto kSize = 512;
|
||||
return Images::GenerateLinearGradient(QSize(kSize, kSize), data.colors);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool operator==(const ChatThemeBackground &a, const ChatThemeBackground &b) {
|
||||
|
@ -167,11 +176,72 @@ ChatTheme::ChatTheme(ChatThemeDescriptor &&descriptor)
|
|||
: _id(descriptor.id)
|
||||
, _palette(std::make_unique<style::palette>()) {
|
||||
descriptor.preparePalette(*_palette);
|
||||
setBackground(descriptor.prepareBackground());
|
||||
setBackground(PrepareBackgroundImage(descriptor.backgroundData));
|
||||
setBubblesBackground(PrepareBubblesBackground(descriptor.bubblesData));
|
||||
adjustPalette(descriptor);
|
||||
}
|
||||
|
||||
ChatTheme::~ChatTheme() = default;
|
||||
|
||||
void ChatTheme::adjustPalette(const ChatThemeDescriptor &descriptor) {
|
||||
auto &p = *_palette;
|
||||
const auto overrideOutBg = (descriptor.bubblesData.colors.size() == 1);
|
||||
if (overrideOutBg) {
|
||||
set(p.msgOutBg(), descriptor.bubblesData.colors.front());
|
||||
}
|
||||
const auto &background = descriptor.backgroundData.colors;
|
||||
if (!background.empty()) {
|
||||
const auto average = CountAverageColor(background);
|
||||
adjust(p.msgServiceBg(), average);
|
||||
adjust(p.msgServiceBgSelected(), average);
|
||||
adjust(p.historyScrollBg(), average);
|
||||
adjust(p.historyScrollBgOver(), average);
|
||||
adjust(p.historyScrollBarBg(), average);
|
||||
adjust(p.historyScrollBarBgOver(), average);
|
||||
}
|
||||
const auto bubblesAccent = descriptor.bubblesData.accent
|
||||
? descriptor.bubblesData.accent
|
||||
: !descriptor.bubblesData.colors.empty()
|
||||
? ThemeAdjustedColor(
|
||||
p.msgOutReplyBarColor()->c,
|
||||
CountAverageColor(descriptor.bubblesData.colors))
|
||||
: std::optional<QColor>();
|
||||
if (bubblesAccent) {
|
||||
const auto by = *bubblesAccent;
|
||||
if (!overrideOutBg) {
|
||||
adjust(p.msgOutBg(), by);
|
||||
}
|
||||
adjust(p.msgOutShadow(), by);
|
||||
adjust(p.msgOutServiceFg(), by);
|
||||
adjust(p.msgOutDateFg(), by);
|
||||
adjust(p.msgFileThumbLinkOutFg(), by);
|
||||
adjust(p.msgFileOutBg(), by);
|
||||
adjust(p.msgOutReplyBarColor(), by);
|
||||
adjust(p.msgWaveformOutActive(), by);
|
||||
adjust(p.msgWaveformOutInactive(), by);
|
||||
adjust(p.historyTextOutFg(), by);
|
||||
adjust(p.historyFileNameOutFg(), by);
|
||||
adjust(p.historyFileOutRadialFg(), by);
|
||||
adjust(p.mediaOutFg(), by);
|
||||
|
||||
adjust(p.historyLinkOutFg(), by);
|
||||
adjust(p.msgOutMonoFg(), by);
|
||||
adjust(p.historyOutIconFg(), by);
|
||||
adjust(p.historyCallArrowOutFg(), by);
|
||||
adjust(p.historyFileOutIconFg(), by);
|
||||
}
|
||||
}
|
||||
|
||||
void ChatTheme::set(const style::color &my, const QColor &color) {
|
||||
auto r = 0, g = 0, b = 0, a = 0;
|
||||
color.getRgb(&r, &g, &b, &a);
|
||||
my.set(uchar(r), uchar(g), uchar(b), uchar(a));
|
||||
}
|
||||
|
||||
void ChatTheme::adjust(const style::color &my, const QColor &by) {
|
||||
set(my, ThemeAdjustedColor(my->c, by));
|
||||
}
|
||||
|
||||
void ChatTheme::setBackground(ChatThemeBackground &&background) {
|
||||
_mutableBackground = std::move(background);
|
||||
_backgroundState = {};
|
||||
|
@ -200,15 +270,23 @@ uint64 ChatTheme::key() const {
|
|||
}
|
||||
|
||||
void ChatTheme::setBubblesBackground(QImage image) {
|
||||
_bubblesBackgroundPrepared = std::move(image);
|
||||
if (!_bubblesBackground.area.isEmpty()) {
|
||||
_bubblesBackground = CacheBackground({
|
||||
.background = {
|
||||
.prepared = _bubblesBackgroundPrepared,
|
||||
},
|
||||
.area = _bubblesBackground.area,
|
||||
});
|
||||
if (image.isNull() && _bubblesBackgroundPrepared.isNull()) {
|
||||
return;
|
||||
}
|
||||
_bubblesBackgroundPrepared = std::move(image);
|
||||
if (_bubblesBackgroundPrepared.isNull()) {
|
||||
_bubblesBackgroundPattern = nullptr;
|
||||
_repaintBackgroundRequests.fire({});
|
||||
return;
|
||||
}
|
||||
_bubblesBackground = CacheBackground({
|
||||
.background = {
|
||||
.prepared = _bubblesBackgroundPrepared,
|
||||
},
|
||||
.area = (_bubblesBackground.area.isEmpty()
|
||||
? _bubblesBackgroundPrepared.size()
|
||||
: _bubblesBackground.area),
|
||||
});
|
||||
if (!_bubblesBackgroundPattern) {
|
||||
_bubblesBackgroundPattern = PrepareBubblePattern(palette());
|
||||
}
|
||||
|
@ -471,8 +549,29 @@ QColor CountAverageColor(const QImage &image) {
|
|||
}
|
||||
}
|
||||
if (size) {
|
||||
for (auto i = 0; i != 3; ++i) {
|
||||
components[i] /= size;
|
||||
for (auto &component : components) {
|
||||
component /= size;
|
||||
}
|
||||
}
|
||||
return QColor(components[0], components[1], components[2]);
|
||||
}
|
||||
|
||||
QColor CountAverageColor(const std::vector<QColor> &colors) {
|
||||
Expects(colors.size() < (std::numeric_limits<int>::max() / 256));
|
||||
|
||||
int components[3] = { 0 };
|
||||
auto r = 0;
|
||||
auto g = 0;
|
||||
auto b = 0;
|
||||
for (const auto &color : colors) {
|
||||
color.getRgb(&r, &g, &b);
|
||||
components[0] += r;
|
||||
components[1] += g;
|
||||
components[2] += b;
|
||||
}
|
||||
if (const auto size = colors.size()) {
|
||||
for (auto &component : components) {
|
||||
component /= size;
|
||||
}
|
||||
}
|
||||
return QColor(components[0], components[1], components[2]);
|
||||
|
@ -652,46 +751,46 @@ QImage GenerateDitheredGradient(
|
|||
}
|
||||
|
||||
ChatThemeBackground PrepareBackgroundImage(
|
||||
const QString &path,
|
||||
const QByteArray &bytes,
|
||||
bool gzipSvg,
|
||||
const std::vector<QColor> &colors,
|
||||
bool isPattern,
|
||||
float64 patternOpacity,
|
||||
bool isBlurred) {
|
||||
auto prepared = (isPattern || colors.empty())
|
||||
? PreprocessBackgroundImage(ReadBackgroundImage(path, bytes, gzipSvg))
|
||||
const ChatThemeBackgroundData &data) {
|
||||
auto prepared = (data.isPattern || data.colors.empty())
|
||||
? PreprocessBackgroundImage(
|
||||
ReadBackgroundImage(data.path, data.bytes, data.gzipSvg))
|
||||
: QImage();
|
||||
if (isPattern && !prepared.isNull()) {
|
||||
if (colors.size() < 2) {
|
||||
if (data.isPattern && !prepared.isNull()) {
|
||||
if (data.colors.size() < 2) {
|
||||
const auto gradientRotation = 0; // No gradient here.
|
||||
prepared = PreparePatternImage(
|
||||
std::move(prepared),
|
||||
colors,
|
||||
gradientRotation,
|
||||
patternOpacity);
|
||||
data.colors,
|
||||
data.gradientRotation,
|
||||
data.patternOpacity);
|
||||
}
|
||||
prepared.setDevicePixelRatio(style::DevicePixelRatio());
|
||||
} else if (colors.empty()) {
|
||||
} else if (data.colors.empty()) {
|
||||
prepared.setDevicePixelRatio(style::DevicePixelRatio());
|
||||
}
|
||||
const auto imageMonoColor = (colors.size() < 2)
|
||||
const auto imageMonoColor = (data.colors.size() < 2)
|
||||
? CalculateImageMonoColor(prepared)
|
||||
: std::nullopt;
|
||||
if (!prepared.isNull() && !isPattern && isBlurred) {
|
||||
if (!prepared.isNull() && !data.isPattern && data.isBlurred) {
|
||||
prepared = PrepareBlurredBackground(std::move(prepared));
|
||||
}
|
||||
auto gradientForFill = (data.generateGradient && data.colors.size() > 1)
|
||||
? Ui::GenerateDitheredGradient(data.colors, data.gradientRotation)
|
||||
: QImage();
|
||||
return ChatThemeBackground{
|
||||
.prepared = prepared,
|
||||
.preparedForTiled = PrepareImageForTiled(prepared),
|
||||
.gradientForFill = std::move(gradientForFill),
|
||||
.colorForFill = (!prepared.isNull()
|
||||
? imageMonoColor
|
||||
: (colors.size() > 1 || colors.empty())
|
||||
: (data.colors.size() > 1 || data.colors.empty())
|
||||
? std::nullopt
|
||||
: std::make_optional(colors.front())),
|
||||
.colors = colors,
|
||||
.patternOpacity = patternOpacity,
|
||||
.isPattern = isPattern,
|
||||
: std::make_optional(data.colors.front())),
|
||||
.colors = data.colors,
|
||||
.patternOpacity = data.patternOpacity,
|
||||
.gradientRotation = data.generateGradient ? data.gradientRotation : 0,
|
||||
.isPattern = data.isPattern,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,23 @@ struct ChatThemeBackground {
|
|||
bool operator==(const ChatThemeBackground &a, const ChatThemeBackground &b);
|
||||
bool operator!=(const ChatThemeBackground &a, const ChatThemeBackground &b);
|
||||
|
||||
struct ChatThemeBackgroundData {
|
||||
QString path;
|
||||
QByteArray bytes;
|
||||
bool gzipSvg = false;
|
||||
std::vector<QColor> colors;
|
||||
bool isPattern = false;
|
||||
float64 patternOpacity = 0.;
|
||||
bool isBlurred = false;
|
||||
bool generateGradient = false;
|
||||
int gradientRotation = 0;
|
||||
};
|
||||
|
||||
struct ChatThemeBubblesData {
|
||||
std::vector<QColor> colors;
|
||||
std::optional<QColor> accent;
|
||||
};
|
||||
|
||||
struct CacheBackgroundRequest {
|
||||
ChatThemeBackground background;
|
||||
QSize area;
|
||||
|
@ -82,7 +99,8 @@ struct BackgroundState {
|
|||
struct ChatThemeDescriptor {
|
||||
uint64 id = 0;
|
||||
Fn<void(style::palette&)> preparePalette;
|
||||
Fn<ChatThemeBackground()> prepareBackground;
|
||||
ChatThemeBackgroundData backgroundData;
|
||||
ChatThemeBubblesData bubblesData;
|
||||
};
|
||||
|
||||
class ChatTheme final : public base::has_weak_ptr {
|
||||
|
@ -131,6 +149,10 @@ private:
|
|||
[[nodiscard]] bool readyForBackgroundRotation() const;
|
||||
void generateNextBackgroundRotation();
|
||||
|
||||
void adjustPalette(const ChatThemeDescriptor &descriptor);
|
||||
void set(const style::color &my, const QColor &color);
|
||||
void adjust(const style::color &my, const QColor &by);
|
||||
|
||||
uint64 _id = 0;
|
||||
std::unique_ptr<style::palette> _palette;
|
||||
ChatThemeBackground _mutableBackground;
|
||||
|
@ -160,6 +182,7 @@ struct ChatBackgroundRects {
|
|||
QSize imageSize);
|
||||
|
||||
[[nodiscard]] QColor CountAverageColor(const QImage &image);
|
||||
[[nodiscard]] QColor CountAverageColor(const std::vector<QColor> &colors);
|
||||
[[nodiscard]] QColor ThemeAdjustedColor(QColor original, QColor background);
|
||||
[[nodiscard]] QImage PreprocessBackgroundImage(QImage image);
|
||||
[[nodiscard]] std::optional<QColor> CalculateImageMonoColor(
|
||||
|
@ -185,14 +208,7 @@ struct ChatBackgroundRects {
|
|||
[[nodiscard]] QImage GenerateDitheredGradient(
|
||||
const std::vector<QColor> &colors,
|
||||
int rotation);
|
||||
|
||||
[[nodiscard]] ChatThemeBackground PrepareBackgroundImage(
|
||||
const QString &path,
|
||||
const QByteArray &bytes,
|
||||
bool gzipSvg,
|
||||
const std::vector<QColor> &colors,
|
||||
bool isPattern,
|
||||
float64 patternOpacity,
|
||||
bool isBlurred);
|
||||
const ChatThemeBackgroundData &data);
|
||||
|
||||
} // namespace Ui
|
||||
|
|
|
@ -752,12 +752,11 @@ void ChatBackground::setPrepared(
|
|||
prepared = Ui::PrepareBlurredBackground(std::move(prepared));
|
||||
}
|
||||
if (adjustPaletteRequired()) {
|
||||
if (!gradient.isNull()) {
|
||||
adjustPaletteUsingBackground(gradient);
|
||||
if ((prepared.isNull() || _paper.isPattern())
|
||||
&& !_paper.backgroundColors().empty()) {
|
||||
adjustPaletteUsingColors(_paper.backgroundColors());
|
||||
} else if (!prepared.isNull()) {
|
||||
adjustPaletteUsingBackground(prepared);
|
||||
} else if (!_paper.backgroundColors().empty()) {
|
||||
adjustPaletteUsingColor(_paper.backgroundColors().front());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -819,6 +818,11 @@ void ChatBackground::adjustPaletteUsingBackground(const QImage &image) {
|
|||
adjustPaletteUsingColor(Ui::CountAverageColor(image));
|
||||
}
|
||||
|
||||
void ChatBackground::adjustPaletteUsingColors(
|
||||
const std::vector<QColor> &colors) {
|
||||
adjustPaletteUsingColor(Ui::CountAverageColor(colors));
|
||||
}
|
||||
|
||||
void ChatBackground::adjustPaletteUsingColor(QColor color) {
|
||||
const auto prepared = color.toHsl();
|
||||
for (const auto &adjustable : _adjustableColors) {
|
||||
|
|
|
@ -219,6 +219,7 @@ private:
|
|||
|
||||
[[nodiscard]] bool adjustPaletteRequired();
|
||||
void adjustPaletteUsingBackground(const QImage &image);
|
||||
void adjustPaletteUsingColors(const std::vector<QColor> &colors);
|
||||
void adjustPaletteUsingColor(QColor color);
|
||||
void restoreAdjustableColors();
|
||||
|
||||
|
|
|
@ -109,6 +109,14 @@ constexpr auto kMaxChatEntryHistorySize = 50;
|
|||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] Ui::ChatThemeBubblesData PrepareBubblesData(
|
||||
const Data::CloudTheme &theme) {
|
||||
return {
|
||||
.colors = theme.outgoingMessagesColors,
|
||||
.accent = theme.outgoingAccentColor,
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void ActivateWindow(not_null<SessionController*> controller) {
|
||||
|
@ -1442,7 +1450,8 @@ void SessionController::cacheChatTheme(const Data::CloudTheme &data) {
|
|||
.preparePalette = PreparePaletteCallback(
|
||||
data.basedOnDark,
|
||||
data.accentColor),
|
||||
.prepareBackground = backgroundGenerator(theme),
|
||||
.backgroundData = backgroundData(theme),
|
||||
.bubblesData = PrepareBubblesData(data),
|
||||
};
|
||||
crl::async([
|
||||
this,
|
||||
|
@ -1500,8 +1509,11 @@ void SessionController::updateCustomThemeBackground(CachedTheme &theme) {
|
|||
}
|
||||
const auto key = theme.theme->key();
|
||||
const auto weak = base::make_weak(this);
|
||||
crl::async([=, generator = backgroundGenerator(theme, false)] {
|
||||
crl::on_main(weak, [=, result = generator()]() mutable {
|
||||
crl::async([=, data = backgroundData(theme, false)] {
|
||||
crl::on_main(weak, [
|
||||
=,
|
||||
result = Ui::PrepareBackgroundImage(data)
|
||||
]() mutable {
|
||||
const auto i = _customChatThemes.find(key);
|
||||
if (i != end(_customChatThemes)) {
|
||||
i->second.theme->updateBackgroundImageFrom(std::move(result));
|
||||
|
@ -1510,9 +1522,9 @@ void SessionController::updateCustomThemeBackground(CachedTheme &theme) {
|
|||
});
|
||||
}
|
||||
|
||||
Fn<Ui::ChatThemeBackground()> SessionController::backgroundGenerator(
|
||||
Ui::ChatThemeBackgroundData SessionController::backgroundData(
|
||||
CachedTheme &theme,
|
||||
bool generateGradient) {
|
||||
bool generateGradient) const {
|
||||
const auto &paper = theme.paper;
|
||||
const auto &media = theme.media;
|
||||
const auto paperPath = media ? media->owner()->filepath() : QString();
|
||||
|
@ -1523,22 +1535,16 @@ Fn<Ui::ChatThemeBackground()> SessionController::backgroundGenerator(
|
|||
const auto patternOpacity = paper.patternOpacity();
|
||||
const auto isBlurred = paper.isBlurred();
|
||||
const auto gradientRotation = paper.gradientRotation();
|
||||
return [=] {
|
||||
auto result = Ui::PrepareBackgroundImage(
|
||||
paperPath,
|
||||
paperBytes,
|
||||
gzipSvg,
|
||||
colors,
|
||||
isPattern,
|
||||
patternOpacity,
|
||||
isBlurred);
|
||||
if (generateGradient) {
|
||||
result.gradientForFill = (colors.size() > 1)
|
||||
? Ui::GenerateDitheredGradient(colors, gradientRotation)
|
||||
: QImage();
|
||||
result.gradientRotation = gradientRotation;
|
||||
}
|
||||
return result;
|
||||
return {
|
||||
.path = paperPath,
|
||||
.bytes = paperBytes,
|
||||
.gzipSvg = gzipSvg,
|
||||
.colors = colors,
|
||||
.isPattern = isPattern,
|
||||
.patternOpacity = patternOpacity,
|
||||
.isBlurred = isBlurred,
|
||||
.generateGradient = generateGradient,
|
||||
.gradientRotation = gradientRotation,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ class ChatStyle;
|
|||
class ChatTheme;
|
||||
struct ChatPaintContext;
|
||||
struct ChatThemeBackground;
|
||||
struct ChatThemeBackgroundData;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Data {
|
||||
|
@ -455,9 +456,9 @@ private:
|
|||
void cacheChatTheme(const Data::CloudTheme &data);
|
||||
void cacheChatThemeDone(std::shared_ptr<Ui::ChatTheme> result);
|
||||
void updateCustomThemeBackground(CachedTheme &theme);
|
||||
[[nodiscard]] Fn<Ui::ChatThemeBackground()> backgroundGenerator(
|
||||
[[nodiscard]] Ui::ChatThemeBackgroundData backgroundData(
|
||||
CachedTheme &theme,
|
||||
bool generateGradient = true);
|
||||
bool generateGradient = true) const;
|
||||
|
||||
const not_null<Controller*> _window;
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit af1429cb87d765be7e70308a318ee20d2478ae74
|
||||
Subproject commit db1b4b65c7c70001412ce1ca357d82f3590008f3
|
Loading…
Add table
Reference in a new issue