mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-08-31 06:26:18 +00:00
Adjust outgoing bubble text and icon colors.
This commit is contained in:
@@ -472,6 +472,8 @@ void ChatStyle::assignPalette(not_null<const style::palette*> palette) {
|
||||
_msgBotKbOverBgAddCorners = {};
|
||||
_msgSelectOverlayCornersSmall = {};
|
||||
_msgSelectOverlayCornersLarge = {};
|
||||
|
||||
_paletteChanged.fire({});
|
||||
}
|
||||
|
||||
const CornersPixmaps &ChatStyle::serviceBgCornersNormal() const {
|
||||
@@ -616,6 +618,17 @@ void ChatStyle::make(
|
||||
make(my.ripple.color, original.ripple.color);
|
||||
}
|
||||
|
||||
void ChatStyle::make(
|
||||
style::ScrollArea &my,
|
||||
const style::ScrollArea &original) const {
|
||||
my = original;
|
||||
make(my.bg, original.bg);
|
||||
make(my.bgOver, original.bgOver);
|
||||
make(my.barBg, original.barBg);
|
||||
make(my.barBgOver, original.barBgOver);
|
||||
make(my.shColor, original.shColor);
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
void ChatStyle::make(
|
||||
Type MessageStyle::*my,
|
||||
|
@@ -15,6 +15,7 @@ enum class ImageRoundRadius;
|
||||
|
||||
namespace style {
|
||||
struct TwoIconButton;
|
||||
struct ScrollArea;
|
||||
} // namespace style
|
||||
|
||||
namespace Ui {
|
||||
@@ -138,6 +139,10 @@ public:
|
||||
|
||||
void apply(not_null<ChatTheme*> theme);
|
||||
|
||||
[[nodiscard]] rpl::producer<> paletteChanged() const {
|
||||
return _paletteChanged.events();
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
[[nodiscard]] Type value(const Type &original) const {
|
||||
auto my = Type();
|
||||
@@ -145,6 +150,15 @@ public:
|
||||
return my;
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
[[nodiscard]] const Type &value(
|
||||
rpl::lifetime &parentLifetime,
|
||||
const Type &original) const {
|
||||
const auto my = parentLifetime.make_state<Type>();
|
||||
make(*my, original);
|
||||
return *my;
|
||||
}
|
||||
|
||||
[[nodiscard]] const CornersPixmaps &serviceBgCornersNormal() const;
|
||||
[[nodiscard]] const CornersPixmaps &serviceBgCornersInverted() const;
|
||||
|
||||
@@ -241,6 +255,9 @@ private:
|
||||
void make(
|
||||
style::TwoIconButton &my,
|
||||
const style::TwoIconButton &original) const;
|
||||
void make(
|
||||
style::ScrollArea &my,
|
||||
const style::ScrollArea &original) const;
|
||||
|
||||
[[nodiscard]] MessageStyle &messageStyleRaw(
|
||||
bool outbg,
|
||||
@@ -303,6 +320,8 @@ private:
|
||||
style::icon _historyPollChoiceRight = { Qt::Uninitialized };
|
||||
style::icon _historyPollChoiceWrong = { Qt::Uninitialized };
|
||||
|
||||
rpl::event_stream<> _paletteChanged;
|
||||
|
||||
rpl::lifetime _defaultPaletteChangeLifetime;
|
||||
|
||||
};
|
||||
|
@@ -25,6 +25,8 @@ constexpr auto kCacheBackgroundFastTimeout = crl::time(200);
|
||||
constexpr auto kBackgroundFadeDuration = crl::time(200);
|
||||
constexpr auto kMinimumTiledSize = 512;
|
||||
constexpr auto kMaxSize = 2960;
|
||||
constexpr auto kMaxContrastValue = 21.;
|
||||
constexpr auto kMinAcceptableContrast = 1.14;// 4.5;
|
||||
|
||||
[[nodiscard]] QColor DefaultBackgroundColor() {
|
||||
return QColor(213, 223, 233);
|
||||
@@ -133,6 +135,25 @@ constexpr auto kMaxSize = 2960;
|
||||
return Images::GenerateLinearGradient(QSize(kSize, kSize), data.colors);
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/9733420
|
||||
[[nodiscard]] float64 CountContrast(const QColor &a, const QColor &b) {
|
||||
const auto luminance = [](const QColor &c) {
|
||||
const auto map = [](double value) {
|
||||
return (value <= 0.03928)
|
||||
? (value / 12.92)
|
||||
: std::pow((value + 0.055) / 1.055, 2.4);
|
||||
};
|
||||
return map(c.redF()) * 0.2126
|
||||
+ map(c.greenF()) * 0.7152
|
||||
+ map(c.blueF()) * 0.0722;
|
||||
};
|
||||
const auto luminance1 = luminance(a);
|
||||
const auto luminance2 = luminance(b);
|
||||
const auto brightest = std::max(luminance1, luminance2);
|
||||
const auto darkest = std::min(luminance1, luminance2);
|
||||
return (brightest + 0.05) / (darkest + 0.05);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool operator==(const ChatThemeBackground &a, const ChatThemeBackground &b) {
|
||||
@@ -201,7 +222,7 @@ void ChatTheme::adjustPalette(const ChatThemeDescriptor &descriptor) {
|
||||
}
|
||||
const auto bubblesAccent = descriptor.bubblesData.accent
|
||||
? descriptor.bubblesData.accent
|
||||
: !descriptor.bubblesData.colors.empty()
|
||||
: (!descriptor.bubblesData.colors.empty())
|
||||
? ThemeAdjustedColor(
|
||||
p.msgOutReplyBarColor()->c,
|
||||
CountAverageColor(descriptor.bubblesData.colors))
|
||||
@@ -230,6 +251,55 @@ void ChatTheme::adjustPalette(const ChatThemeDescriptor &descriptor) {
|
||||
adjust(p.historyCallArrowOutFg(), by);
|
||||
adjust(p.historyFileOutIconFg(), by);
|
||||
}
|
||||
auto outBgColors = descriptor.bubblesData.colors;
|
||||
if (outBgColors.empty()) {
|
||||
outBgColors.push_back(p.msgOutBg()->c);
|
||||
}
|
||||
const auto colors = {
|
||||
p.msgOutServiceFg(),
|
||||
p.msgOutDateFg(),
|
||||
p.msgFileThumbLinkOutFg(),
|
||||
p.msgFileOutBg(),
|
||||
p.msgOutReplyBarColor(),
|
||||
p.msgWaveformOutActive(),
|
||||
p.historyTextOutFg(),
|
||||
p.mediaOutFg(),
|
||||
p.historyLinkOutFg(),
|
||||
p.msgOutMonoFg(),
|
||||
p.historyOutIconFg(),
|
||||
p.historyCallArrowOutFg(),
|
||||
};
|
||||
const auto minimal = [&](const QColor &with) {
|
||||
auto result = kMaxContrastValue;
|
||||
for (const auto &color : colors) {
|
||||
result = std::min(result, CountContrast(color->c, with));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const auto withBg = [&](auto &&count) {
|
||||
auto result = kMaxContrastValue;
|
||||
for (const auto &bg : outBgColors) {
|
||||
result = std::min(result, count(bg));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const auto singleWithBg = [&](const QColor &c) {
|
||||
return withBg([&](const QColor &with) {
|
||||
return CountContrast(c, with);
|
||||
});
|
||||
};
|
||||
if (withBg(minimal) < kMinAcceptableContrast) {
|
||||
const auto white = QColor(255, 255, 255);
|
||||
const auto black = QColor(0, 0, 0);
|
||||
// This one always gives black :)
|
||||
//const auto now = (singleWithBg(white) >= singleWithBg(black))
|
||||
// ? white
|
||||
// : black;
|
||||
const auto now = descriptor.basedOnDark ? white : black;
|
||||
for (const auto &color : colors) {
|
||||
set(color, now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChatTheme::set(const style::color &my, const QColor &color) {
|
||||
|
@@ -101,6 +101,7 @@ struct ChatThemeDescriptor {
|
||||
Fn<void(style::palette&)> preparePalette;
|
||||
ChatThemeBackgroundData backgroundData;
|
||||
ChatThemeBubblesData bubblesData;
|
||||
bool basedOnDark = false;
|
||||
};
|
||||
|
||||
class ChatTheme final : public base::has_weak_ptr {
|
||||
|
Reference in New Issue
Block a user