Don't use MTP* for WallPaper flags.

This commit is contained in:
John Preston 2021-08-12 12:32:30 +03:00
parent 474a6a71d9
commit 85cc3b30a0
8 changed files with 321 additions and 136 deletions

View file

@ -255,7 +255,7 @@ void BackgroundBox::Inner::updatePapers() {
_papers = _session->data().wallpapers( _papers = _session->data().wallpapers(
) | ranges::views::filter([](const Data::WallPaper &paper) { ) | ranges::views::filter([](const Data::WallPaper &paper) {
return !paper.isPattern() || paper.backgroundColor().has_value(); return !paper.isPattern() || !paper.backgroundColors().empty();
}) | ranges::views::transform([](const Data::WallPaper &paper) { }) | ranges::views::transform([](const Data::WallPaper &paper) {
return Paper{ paper }; return Paper{ paper };
}) | ranges::to_vector; }) | ranges::to_vector;
@ -336,6 +336,7 @@ void BackgroundBox::Inner::validatePaperThumbnail(
: paper.dataMedia->thumbnail(); : paper.dataMedia->thumbnail();
auto original = thumbnail->original(); auto original = thumbnail->original();
if (paper.data.isPattern()) { if (paper.data.isPattern()) {
// #TODO themes gradients
const auto color = *paper.data.backgroundColor(); const auto color = *paper.data.backgroundColor();
original = Data::PreparePatternImage( original = Data::PreparePatternImage(
std::move(original), std::move(original),

View file

@ -768,7 +768,7 @@ bool BackgroundPreviewBox::Start(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
const QString &slug, const QString &slug,
const QMap<QString, QString> &params) { const QMap<QString, QString> &params) {
if (const auto paper = Data::WallPaper::FromColorSlug(slug)) { if (const auto paper = Data::WallPaper::FromColorsSlug(slug)) {
controller->show(Box<BackgroundPreviewBox>( controller->show(Box<BackgroundPreviewBox>(
controller, controller,
paper->withUrlParams(params))); paper->withUrlParams(params)));

View file

@ -231,7 +231,10 @@ bool ShowWallPaper(
const auto params = url_parse_params( const auto params = url_parse_params(
match->captured(1), match->captured(1),
qthelp::UrlParamNameTransform::ToLower); qthelp::UrlParamNameTransform::ToLower);
if (!params.value("gradient").isEmpty()) { const auto bg = params.value("bg_color");
if (!params.value("gradient").isEmpty()
|| bg.contains('~')
|| bg.contains('-')) {
Ui::show(Box<InformBox>( Ui::show(Box<InformBox>(
tr::lng_background_gradient_unsupported(tr::now))); tr::lng_background_gradient_unsupported(tr::now)));
return false; return false;

View file

@ -32,15 +32,21 @@ constexpr auto kLegacy2DefaultBackground = 5947530738516623361;
constexpr auto kDefaultBackground = 5778236420632084488; constexpr auto kDefaultBackground = 5778236420632084488;
constexpr auto kIncorrectDefaultBackground = FromLegacyBackgroundId(105); constexpr auto kIncorrectDefaultBackground = FromLegacyBackgroundId(105);
quint32 SerializeMaybeColor(std::optional<QColor> color) { constexpr auto kVersionTag = qint32(0x7FFFFFFF);
return color constexpr auto kVersion = 1;
? ((quint32(std::clamp(color->red(), 0, 255)) << 16)
| (quint32(std::clamp(color->green(), 0, 255)) << 8) [[nodiscard]] quint32 SerializeColor(const QColor &color) {
| quint32(std::clamp(color->blue(), 0, 255))) return (quint32(std::clamp(color.red(), 0, 255)) << 16)
: quint32(-1); | (quint32(std::clamp(color.green(), 0, 255)) << 8)
| quint32(std::clamp(color.blue(), 0, 255));
} }
std::optional<QColor> MaybeColorFromSerialized(quint32 serialized) { [[nodiscard]] quint32 SerializeMaybeColor(std::optional<QColor> color) {
return color ? SerializeColor(*color) : quint32(-1);
}
[[nodiscard]] std::optional<QColor> MaybeColorFromSerialized(
quint32 serialized) {
return (serialized == quint32(-1)) return (serialized == quint32(-1))
? std::nullopt ? std::nullopt
: std::make_optional(QColor( : std::make_optional(QColor(
@ -49,7 +55,39 @@ std::optional<QColor> MaybeColorFromSerialized(quint32 serialized) {
int(serialized & 0xFFU))); int(serialized & 0xFFU)));
} }
std::optional<QColor> ColorFromString(const QString &string) { [[nodiscard]] std::optional<QColor> MaybeColorFromSerialized(
const tl::conditional<MTPint> &mtp) {
return mtp ? MaybeColorFromSerialized(mtp->v) : std::nullopt;
}
[[nodiscard]] std::vector<QColor> ColorsFromMTP(
const MTPDwallPaperSettings &data) {
auto result = std::vector<QColor>();
const auto c1 = MaybeColorFromSerialized(data.vbackground_color());
if (!c1) {
return result;
}
result.reserve(4);
result.push_back(*c1);
const auto c2 = MaybeColorFromSerialized(data.vsecond_background_color());
if (!c2) {
return result;
}
result.push_back(*c2);
const auto c3 = MaybeColorFromSerialized(data.vthird_background_color());
if (!c3) {
return result;
}
result.push_back(*c3);
const auto c4 = MaybeColorFromSerialized(data.vfourth_background_color());
if (!c4) {
return result;
}
result.push_back(*c4);
return result;
}
[[nodiscard]] std::optional<QColor> ColorFromString(QStringView string) {
if (string.size() != 6) { if (string.size() != 6) {
return {}; return {};
} else if (ranges::any_of(string, [](QChar ch) { } else if (ranges::any_of(string, [](QChar ch) {
@ -59,7 +97,7 @@ std::optional<QColor> ColorFromString(const QString &string) {
})) { })) {
return {}; return {};
} }
const auto component = [](const QString &text, int index) { const auto component = [](QStringView text, int index) {
const auto decimal = [](QChar hex) { const auto decimal = [](QChar hex) {
const auto code = hex.unicode(); const auto code = hex.unicode();
return (code >= '0' && code <= '9') return (code >= '0' && code <= '9')
@ -78,7 +116,29 @@ std::optional<QColor> ColorFromString(const QString &string) {
255); 255);
} }
QString StringFromColor(QColor color) { [[nodiscard]] std::vector<QColor> ColorsFromString(const QString &string) {
constexpr auto kMaxColors = 1; // #TODO themes gradients replace to 4
const auto view = QStringView(string);
const auto count = int(view.size() / 6);
if (!count || count > kMaxColors || view.size() != count * 7 - 1) {
return {};
}
const auto separator = QChar(count > 2 ? '~' : '-');
auto result = std::vector<QColor>();
result.reserve(count);
for (auto i = 0; i != count; ++i) {
if (i + 1 < count && view[i * 7 + 6] != separator) {
return {};
} else if (const auto parsed = ColorFromString(view.mid(i * 7, 6))) {
result.push_back(*parsed);
} else {
return {};
}
}
return result;
}
[[nodiscard]] QString StringFromColor(QColor color) {
const auto component = [](int value) { const auto component = [](int value) {
const auto hex = [](int value) { const auto hex = [](int value) {
value = std::clamp(value, 0, 15); value = std::clamp(value, 0, 15);
@ -93,6 +153,26 @@ QString StringFromColor(QColor color) {
+ component(color.blue()); + component(color.blue());
} }
[[nodiscard]] QString StringFromColors(const std::vector<QColor> &colors) {
Expects(!colors.empty());
auto strings = QStringList();
strings.reserve(colors.size());
for (const auto &color : colors) {
strings.push_back(StringFromColor(color));
}
const auto separator = (colors.size() > 2) ? '~' : '-';
return strings.join(separator);
}
[[nodiscard]] qint32 RawFromLegacyFlags(qint32 legacyFlags) {
using Flag = WallPaperFlag;
return ((legacyFlags & (1 << 0)) ? qint32(Flag::Creator) : 0)
| ((legacyFlags & (1 << 1)) ? qint32(Flag::Default) : 0)
| ((legacyFlags & (1 << 3)) ? qint32(Flag::Pattern) : 0)
| ((legacyFlags & (1 << 4)) ? qint32(Flag::Dark) : 0);
}
} // namespace } // namespace
WallPaper::WallPaper(WallPaperId id) : _id(id) { WallPaper::WallPaper(WallPaperId id) : _id(id) {
@ -112,7 +192,13 @@ WallPaperId WallPaper::id() const {
} }
std::optional<QColor> WallPaper::backgroundColor() const { std::optional<QColor> WallPaper::backgroundColor() const {
return _backgroundColor; return _backgroundColors.empty()
? std::nullopt
: std::make_optional(_backgroundColors.front());
}
const std::vector<QColor> WallPaper::backgroundColors() const {
return _backgroundColors;
} }
DocumentData *WallPaper::document() const { DocumentData *WallPaper::document() const {
@ -124,19 +210,19 @@ Image *WallPaper::localThumbnail() const {
} }
bool WallPaper::isPattern() const { bool WallPaper::isPattern() const {
return _flags & MTPDwallPaper::Flag::f_pattern; return _flags & WallPaperFlag::Pattern;
} }
bool WallPaper::isDefault() const { bool WallPaper::isDefault() const {
return _flags & MTPDwallPaper::Flag::f_default; return _flags & WallPaperFlag::Default;
} }
bool WallPaper::isCreator() const { bool WallPaper::isCreator() const {
return _flags & MTPDwallPaper::Flag::f_creator; return _flags & WallPaperFlag::Creator;
} }
bool WallPaper::isDark() const { bool WallPaper::isDark() const {
return _flags & MTPDwallPaper::Flag::f_dark; return _flags & WallPaperFlag::Dark;
} }
bool WallPaper::isLocal() const { bool WallPaper::isLocal() const {
@ -144,7 +230,7 @@ bool WallPaper::isLocal() const {
} }
bool WallPaper::isBlurred() const { bool WallPaper::isBlurred() const {
return _settings & MTPDwallPaperSettings::Flag::f_blur; return _blurred;
} }
int WallPaper::patternIntensity() const { int WallPaper::patternIntensity() const {
@ -162,20 +248,18 @@ QString WallPaper::shareUrl(not_null<Main::Session*> session) const {
const auto base = session->createInternalLinkFull("bg/" + _slug); const auto base = session->createInternalLinkFull("bg/" + _slug);
auto params = QStringList(); auto params = QStringList();
if (isPattern()) { if (isPattern()) {
if (_backgroundColor) { if (!backgroundColors().empty()) {
params.push_back("bg_color=" + StringFromColor(*_backgroundColor)); params.push_back(
"bg_color=" + StringFromColors(backgroundColors()));
} }
if (_intensity) { if (_intensity) {
params.push_back("intensity=" + QString::number(_intensity)); params.push_back("intensity=" + QString::number(_intensity));
} }
} }
auto mode = QStringList(); auto mode = QStringList();
if (_settings & MTPDwallPaperSettings::Flag::f_blur) { if (_blurred) {
mode.push_back("blur"); mode.push_back("blur");
} }
if (_settings & MTPDwallPaperSettings::Flag::f_motion) {
mode.push_back("motion");
}
if (!mode.isEmpty()) { if (!mode.isEmpty()) {
params.push_back("mode=" + mode.join('+')); params.push_back("mode=" + mode.join('+'));
} }
@ -211,47 +295,58 @@ MTPInputWallPaper WallPaper::mtpInput(not_null<Main::Session*> session) const {
} }
MTPWallPaperSettings WallPaper::mtpSettings() const { MTPWallPaperSettings WallPaper::mtpSettings() const {
const auto serializeForIndex = [&](int index) {
return (_backgroundColors.size() > index)
? MTP_int(SerializeColor(_backgroundColors[index]))
: MTP_int(0);
};
using Flag = MTPDwallPaperSettings::Flag;
const auto flagForIndex = [&](int index) {
return (_backgroundColors.size() <= index)
? Flag(0)
: (index == 0)
? Flag::f_background_color
: (index == 1)
? Flag::f_second_background_color
: (index == 2)
? Flag::f_third_background_color
: Flag::f_fourth_background_color;
};
return MTP_wallPaperSettings( return MTP_wallPaperSettings(
MTP_flags(_settings), MTP_flags((_blurred ? Flag::f_blur : Flag(0))
(_backgroundColor | flagForIndex(0)
? MTP_int(SerializeMaybeColor(_backgroundColor)) | flagForIndex(1)
: MTP_int(0)), | flagForIndex(2)
MTP_int(0), // second_background_color | flagForIndex(3)),
MTP_int(0), // third_background_color serializeForIndex(0),
MTP_int(0), // fourth_background_color serializeForIndex(1),
serializeForIndex(2),
serializeForIndex(3),
MTP_int(_intensity), MTP_int(_intensity),
MTP_int(0) // rotation MTP_int(_rotation));
);
} }
WallPaper WallPaper::withUrlParams( WallPaper WallPaper::withUrlParams(
const QMap<QString, QString> &params) const { const QMap<QString, QString> &params) const {
using Flag = MTPDwallPaperSettings::Flag;
auto result = *this; auto result = *this;
result._settings = Flag(0); result._blurred = false;
result._backgroundColor = ColorFromString(_slug); result._backgroundColors = ColorsFromString(_slug);
result._intensity = kDefaultIntensity; result._intensity = kDefaultIntensity;
if (auto mode = params.value("mode"); !mode.isEmpty()) { if (auto mode = params.value("mode"); !mode.isEmpty()) {
const auto list = mode.replace('+', ' ').split(' '); const auto list = mode.replace('+', ' ').split(' ');
for (const auto &change : list) { for (const auto &change : list) {
if (change == qstr("blur")) { if (change == qstr("blur")) {
result._settings |= Flag::f_blur; result._blurred = true;
} else if (change == qstr("motion")) {
result._settings |= Flag::f_motion;
} }
} }
} }
if (const auto color = ColorFromString(params.value("bg_color"))) { if (result._backgroundColors.empty()) {
result._settings |= Flag::f_background_color; result._backgroundColors = ColorsFromString(params.value("bg_color"));
result._backgroundColor = color;
} }
if (const auto string = params.value("intensity"); !string.isEmpty()) { if (const auto string = params.value("intensity"); !string.isEmpty()) {
auto ok = false; auto ok = false;
const auto intensity = string.toInt(&ok); const auto intensity = string.toInt(&ok);
if (ok && base::in_range(intensity, 0, 101)) { if (ok && base::in_range(intensity, 0, 101)) {
result._settings |= Flag::f_intensity;
result._intensity = intensity; result._intensity = intensity;
} }
} }
@ -260,45 +355,39 @@ WallPaper WallPaper::withUrlParams(
} }
WallPaper WallPaper::withBlurred(bool blurred) const { WallPaper WallPaper::withBlurred(bool blurred) const {
using Flag = MTPDwallPaperSettings::Flag;
auto result = *this; auto result = *this;
if (blurred) { result._blurred = blurred;
result._settings |= Flag::f_blur;
} else {
result._settings &= ~Flag::f_blur;
}
return result; return result;
} }
WallPaper WallPaper::withPatternIntensity(int intensity) const { WallPaper WallPaper::withPatternIntensity(int intensity) const {
using Flag = MTPDwallPaperSettings::Flag;
auto result = *this; auto result = *this;
result._settings |= Flag::f_intensity;
result._intensity = intensity; result._intensity = intensity;
return result; return result;
} }
WallPaper WallPaper::withBackgroundColor(QColor color) const { WallPaper WallPaper::withGradientRotation(int rotation) const {
using Flag = MTPDwallPaperSettings::Flag;
auto result = *this; auto result = *this;
result._settings |= Flag::f_background_color; result._rotation = rotation;
result._backgroundColor = color; return result;
if (ColorFromString(_slug)) { }
result._slug = StringFromColor(color);
WallPaper WallPaper::withBackgroundColors(std::vector<QColor> colors) const {
auto result = *this;
result._backgroundColors = std::move(colors);
if (!ColorsFromString(_slug).empty()) {
result._slug = StringFromColors(result._backgroundColors);
} }
return result; return result;
} }
WallPaper WallPaper::withParamsFrom(const WallPaper &other) const { WallPaper WallPaper::withParamsFrom(const WallPaper &other) const {
auto result = *this; auto result = *this;
result._settings = other._settings; result._blurred = other._blurred;
if (other._backgroundColor || !ColorFromString(_slug)) { if (!other._backgroundColors.empty() || ColorsFromString(_slug).empty()) {
result._backgroundColor = other._backgroundColor; result._backgroundColors = other._backgroundColors;
if (ColorFromString(_slug)) { if (!ColorsFromString(_slug).empty()) {
result._slug = StringFromColor(*result._backgroundColor); result._slug = StringFromColors(result._backgroundColors);
} }
} }
result._intensity = other._intensity; result._intensity = other._intensity;
@ -317,15 +406,13 @@ std::optional<WallPaper> WallPaper::Create(
return data.match([&](const MTPDwallPaper &data) { return data.match([&](const MTPDwallPaper &data) {
return Create(session, data); return Create(session, data);
}, [](const MTPDwallPaperNoFile &data) { }, [](const MTPDwallPaperNoFile &data) {
return std::optional<WallPaper>(); // #TODO themes return Create(data);
}); });
} }
std::optional<WallPaper> WallPaper::Create( std::optional<WallPaper> WallPaper::Create(
not_null<Main::Session*> session, not_null<Main::Session*> session,
const MTPDwallPaper &data) { const MTPDwallPaper &data) {
using Flag = MTPDwallPaper::Flag;
const auto document = session->data().processDocument( const auto document = session->data().processDocument(
data.vdocument()); data.vdocument());
if (!document->checkWallPaperProperties()) { if (!document->checkWallPaperProperties()) {
@ -343,27 +430,50 @@ std::optional<WallPaper> WallPaper::Create(
auto result = WallPaper(data.vid().v); auto result = WallPaper(data.vid().v);
result._accessHash = data.vaccess_hash().v; result._accessHash = data.vaccess_hash().v;
result._ownerId = session->userId(); result._ownerId = session->userId();
result._flags = data.vflags().v; result._flags = (data.is_dark() ? WallPaperFlag::Dark : WallPaperFlag(0))
| (data.is_pattern() ? WallPaperFlag::Pattern : WallPaperFlag(0))
| (data.is_default() ? WallPaperFlag::Default : WallPaperFlag(0))
| (data.is_creator() ? WallPaperFlag::Creator : WallPaperFlag(0));
result._slug = qs(data.vslug()); result._slug = qs(data.vslug());
result._document = document; result._document = document;
if (const auto settings = data.vsettings()) { if (const auto settings = data.vsettings()) {
const auto isPattern = ((result._flags & Flag::f_pattern) != 0);
settings->match([&](const MTPDwallPaperSettings &data) { settings->match([&](const MTPDwallPaperSettings &data) {
using Flag = MTPDwallPaperSettings::Flag; result._blurred = data.is_blur();
if (result.isPattern()) {
result._settings = data.vflags().v; result._backgroundColors = ColorsFromMTP(data);
const auto backgroundColor = data.vbackground_color(); if (const auto intensity = data.vintensity()) {
if (isPattern && backgroundColor) { result._intensity = intensity->v;
result._backgroundColor = MaybeColorFromSerialized( }
backgroundColor->v); if (const auto rotation = data.vrotation()) {
} else { result._rotation = rotation->v;
result._settings &= ~Flag::f_background_color; }
} }
const auto intensity = data.vintensity(); });
if (isPattern && intensity) { }
result._intensity = intensity->v; return result;
} else { }
result._settings &= ~Flag::f_intensity;
std::optional<WallPaper> WallPaper::Create(const MTPDwallPaperNoFile &data) {
const auto unsupported = data.vsettings()
&& data.vsettings()->match([&](const MTPDwallPaperSettings &data) {
return data.vsecond_background_color()
|| data.vthird_background_color()
|| data.vfourth_background_color(); // #TODO themes gradients
});
if (unsupported) {
return std::nullopt;
}
auto result = WallPaper(data.vid().v);
result._flags = (data.is_dark() ? WallPaperFlag::Dark : WallPaperFlag(0))
| (data.is_default() ? WallPaperFlag::Default : WallPaperFlag(0));
result._blurred = false;
result._backgroundColors.clear();
if (const auto settings = data.vsettings()) {
settings->match([&](const MTPDwallPaperSettings &data) {
result._blurred = data.is_blur();
result._backgroundColors = ColorsFromMTP(data);
if (const auto rotation = data.vrotation()) {
result._rotation = rotation->v;
} }
}); });
} }
@ -373,30 +483,38 @@ std::optional<WallPaper> WallPaper::Create(
QByteArray WallPaper::serialize() const { QByteArray WallPaper::serialize() const {
auto size = sizeof(quint64) // _id auto size = sizeof(quint64) // _id
+ sizeof(quint64) // _accessHash + sizeof(quint64) // _accessHash
+ sizeof(qint32) // version tag
+ sizeof(qint32) // version
+ sizeof(qint32) // _flags + sizeof(qint32) // _flags
+ Serialize::stringSize(_slug) + Serialize::stringSize(_slug)
+ sizeof(qint32) // _settings + sizeof(qint32) // _settings
+ sizeof(quint32) // _backgroundColor + sizeof(qint32) // _backgroundColors.size()
+ (_backgroundColors.size() * sizeof(quint32)) // _backgroundColors
+ sizeof(qint32) // _intensity + sizeof(qint32) // _intensity
+ (2 * sizeof(qint32)); // ownerId + sizeof(qint32) // _rotation
+ sizeof(quint64); // ownerId
auto result = QByteArray(); auto result = QByteArray();
result.reserve(size); result.reserve(size);
{ {
const auto field1 = qint32(uint32(_ownerId.bare & 0xFFFFFFFF));
const auto field2 = qint32(uint32(_ownerId.bare >> 32));
auto stream = QDataStream(&result, QIODevice::WriteOnly); auto stream = QDataStream(&result, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_5_1); stream.setVersion(QDataStream::Qt_5_1);
stream stream
<< quint64(_id) << quint64(_id)
<< quint64(_accessHash) << quint64(_accessHash)
<< qint32(kVersionTag)
<< qint32(kVersion)
<< qint32(_flags) << qint32(_flags)
<< _slug << _slug
<< qint32(_settings) << qint32(_blurred ? 1 : 0)
<< SerializeMaybeColor(_backgroundColor) << qint32(_backgroundColors.size());
for (const auto &color : _backgroundColors) {
stream << SerializeMaybeColor(color);
}
stream
<< qint32(_intensity) << qint32(_intensity)
<< field1 << qint32(_rotation)
<< field2; << quint64(_ownerId.bare);
} }
return result; return result;
} }
@ -409,32 +527,74 @@ std::optional<WallPaper> WallPaper::FromSerialized(
auto id = quint64(); auto id = quint64();
auto accessHash = quint64(); auto accessHash = quint64();
auto ownerId = UserId(); auto versionTag = qint32();
auto flags = qint32(); auto version = qint32(0);
auto slug = QString();
auto settings = qint32();
auto backgroundColor = quint32();
auto intensity = qint32();
auto stream = QDataStream(serialized); auto stream = QDataStream(serialized);
stream.setVersion(QDataStream::Qt_5_1); stream.setVersion(QDataStream::Qt_5_1);
stream stream
>> id >> id
>> accessHash >> accessHash
>> flags >> versionTag;
>> slug
>> settings auto flags = qint32();
>> backgroundColor auto ownerId = UserId();
>> intensity; auto slug = QString();
if (!stream.atEnd()) { auto blurred = qint32();
auto field1 = qint32(); auto backgroundColors = std::vector<QColor>();
auto field2 = qint32(); auto intensity = qint32();
stream >> field1; auto rotation = qint32();
if (!stream.atEnd()) { if (versionTag == kVersionTag) {
stream >> field2; auto bareOwnerId = quint64();
auto backgroundColorsCount = qint32();
stream
>> version
>> flags
>> slug
>> blurred
>> backgroundColorsCount;
// #TODO themes gradients replace with 4
if (backgroundColorsCount < 0 || backgroundColorsCount > 1) {
return std::nullopt;
}
backgroundColors.reserve(backgroundColorsCount);
for (auto i = 0; i != backgroundColorsCount; ++i) {
auto serialized = quint32();
stream >> serialized;
const auto color = MaybeColorFromSerialized(serialized);
if (!color) {
return std::nullopt;
}
backgroundColors.push_back(*color);
}
stream
>> intensity
>> rotation
>> bareOwnerId;
ownerId = UserId(BareId(bareOwnerId));
} else {
auto settings = qint32();
auto backgroundColor = quint32();
stream
>> slug
>> settings
>> backgroundColor
>> intensity;
if (!stream.atEnd()) {
auto field1 = qint32();
auto field2 = qint32();
stream >> field1;
if (!stream.atEnd()) {
stream >> field2;
}
ownerId = UserId(
BareId(uint32(field1)) | (BareId(uint32(field2)) << 32));
}
flags = RawFromLegacyFlags(versionTag);
blurred = (settings & qint32(1U << 1)) ? 1 : 0;
if (const auto color = MaybeColorFromSerialized(backgroundColor)) {
backgroundColors.push_back(*color);
} }
ownerId = UserId(
BareId(uint32(field1)) | (BareId(uint32(field2)) << 32));
} }
if (stream.status() != QDataStream::Ok) { if (stream.status() != QDataStream::Ok) {
return std::nullopt; return std::nullopt;
@ -444,11 +604,12 @@ std::optional<WallPaper> WallPaper::FromSerialized(
auto result = WallPaper(id); auto result = WallPaper(id);
result._accessHash = accessHash; result._accessHash = accessHash;
result._ownerId = ownerId; result._ownerId = ownerId;
result._flags = MTPDwallPaper::Flags::from_raw(flags); result._flags = WallPaperFlags::from_raw(flags);
result._slug = slug; result._slug = slug;
result._settings = MTPDwallPaperSettings::Flags::from_raw(settings); result._blurred = (blurred == 1);
result._backgroundColor = MaybeColorFromSerialized(backgroundColor); result._backgroundColors = std::move(backgroundColors);
result._intensity = intensity; result._intensity = intensity;
result._rotation = rotation;
return result; return result;
} }
@ -459,28 +620,31 @@ std::optional<WallPaper> WallPaper::FromLegacySerialized(
QString slug) { QString slug) {
auto result = WallPaper(id); auto result = WallPaper(id);
result._accessHash = accessHash; result._accessHash = accessHash;
result._flags = MTPDwallPaper::Flags::from_raw(flags); result._flags = WallPaperFlags::from_raw(RawFromLegacyFlags(flags));
result._slug = slug; result._slug = slug;
result._backgroundColor = ColorFromString(slug); if (const auto color = ColorFromString(slug)) {
result._backgroundColors.push_back(*color);
}
return result; return result;
} }
std::optional<WallPaper> WallPaper::FromLegacyId(qint32 legacyId) { std::optional<WallPaper> WallPaper::FromLegacyId(qint32 legacyId) {
auto result = WallPaper(FromLegacyBackgroundId(legacyId)); auto result = WallPaper(FromLegacyBackgroundId(legacyId));
if (!IsCustomWallPaper(result)) { if (!IsCustomWallPaper(result)) {
result._flags = MTPDwallPaper::Flag::f_default; result._flags = WallPaperFlag::Default;
} }
return result; return result;
} }
std::optional<WallPaper> WallPaper::FromColorSlug(const QString &slug) { std::optional<WallPaper> WallPaper::FromColorsSlug(const QString &slug) {
if (const auto color = ColorFromString(slug)) { auto colors = ColorsFromString(slug);
auto result = CustomWallPaper(); if (colors.empty()) {
result._slug = slug; return std::nullopt;
result._backgroundColor = color;
return result;
} }
return std::nullopt; auto result = CustomWallPaper();
result._slug = slug;
result._backgroundColors = std::move(colors);
return result;
} }
WallPaper ThemeWallPaper() { WallPaper ThemeWallPaper() {

View file

@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "base/flags.h"
class Image; class Image;
namespace Main { namespace Main {
@ -17,6 +19,15 @@ namespace Data {
struct FileOrigin; struct FileOrigin;
enum class WallPaperFlag {
Pattern = (1 << 0),
Default = (1 << 1),
Creator = (1 << 2),
Dark = (1 << 3),
};
inline constexpr bool is_flag_type(WallPaperFlag) { return true; };
using WallPaperFlags = base::flags<WallPaperFlag>;
class WallPaper { class WallPaper {
public: public:
explicit WallPaper(WallPaperId id); explicit WallPaper(WallPaperId id);
@ -25,6 +36,7 @@ public:
[[nodiscard]] WallPaperId id() const; [[nodiscard]] WallPaperId id() const;
[[nodiscard]] std::optional<QColor> backgroundColor() const; [[nodiscard]] std::optional<QColor> backgroundColor() const;
[[nodiscard]] const std::vector<QColor> backgroundColors() const;
[[nodiscard]] DocumentData *document() const; [[nodiscard]] DocumentData *document() const;
[[nodiscard]] Image *localThumbnail() const; [[nodiscard]] Image *localThumbnail() const;
[[nodiscard]] bool isPattern() const; [[nodiscard]] bool isPattern() const;
@ -50,7 +62,9 @@ public:
const QMap<QString, QString> &params) const; const QMap<QString, QString> &params) const;
[[nodiscard]] WallPaper withBlurred(bool blurred) const; [[nodiscard]] WallPaper withBlurred(bool blurred) const;
[[nodiscard]] WallPaper withPatternIntensity(int intensity) const; [[nodiscard]] WallPaper withPatternIntensity(int intensity) const;
[[nodiscard]] WallPaper withBackgroundColor(QColor color) const; [[nodiscard]] WallPaper withGradientRotation(int rotation) const;
[[nodiscard]] WallPaper withBackgroundColors(
std::vector<QColor> colors) const;
[[nodiscard]] WallPaper withParamsFrom(const WallPaper &other) const; [[nodiscard]] WallPaper withParamsFrom(const WallPaper &other) const;
[[nodiscard]] WallPaper withoutImageData() const; [[nodiscard]] WallPaper withoutImageData() const;
@ -60,6 +74,8 @@ public:
[[nodiscard]] static std::optional<WallPaper> Create( [[nodiscard]] static std::optional<WallPaper> Create(
not_null<Main::Session*> session, not_null<Main::Session*> session,
const MTPDwallPaper &data); const MTPDwallPaper &data);
[[nodiscard]] static std::optional<WallPaper> Create(
const MTPDwallPaperNoFile &data);
[[nodiscard]] QByteArray serialize() const; [[nodiscard]] QByteArray serialize() const;
[[nodiscard]] static std::optional<WallPaper> FromSerialized( [[nodiscard]] static std::optional<WallPaper> FromSerialized(
@ -71,21 +87,22 @@ public:
QString slug); QString slug);
[[nodiscard]] static std::optional<WallPaper> FromLegacyId( [[nodiscard]] static std::optional<WallPaper> FromLegacyId(
qint32 legacyId); qint32 legacyId);
[[nodiscard]] static std::optional<WallPaper> FromColorSlug( [[nodiscard]] static std::optional<WallPaper> FromColorsSlug(
const QString &slug); const QString &slug);
private: private:
static constexpr auto kDefaultIntensity = 40; static constexpr auto kDefaultIntensity = 50;
WallPaperId _id = WallPaperId(); WallPaperId _id = WallPaperId();
uint64 _accessHash = 0; uint64 _accessHash = 0;
UserId _ownerId = 0; UserId _ownerId = 0;
MTPDwallPaper::Flags _flags; WallPaperFlags _flags;
QString _slug; QString _slug;
MTPDwallPaperSettings::Flags _settings; std::vector<QColor> _backgroundColors;
std::optional<QColor> _backgroundColor; int _rotation = 0;
int _intensity = kDefaultIntensity; int _intensity = kDefaultIntensity;
bool _blurred = false;
DocumentData *_document = nullptr; DocumentData *_document = nullptr;
std::shared_ptr<Image> _thumbnail; std::shared_ptr<Image> _thumbnail;

View file

@ -1213,7 +1213,7 @@ void MainWidget::setReadyChatBackground(
const auto resetToDefault = image.isNull() const auto resetToDefault = image.isNull()
&& !background.document() && !background.document()
&& !background.backgroundColor() && background.backgroundColors().empty()
&& !Data::IsLegacy1DefaultWallPaper(background); && !Data::IsLegacy1DefaultWallPaper(background);
const auto ready = resetToDefault const auto ready = resetToDefault
? Data::DefaultWallPaper() ? Data::DefaultWallPaper()

View file

@ -740,7 +740,7 @@ bool readBackground() {
image = QImage(); image = QImage();
} }
} }
if (!image.isNull() || paper->backgroundColor()) { if (!image.isNull() || !paper->backgroundColors().empty()) {
_backgroundCanWrite = false; _backgroundCanWrite = false;
Window::Theme::Background()->set(*paper, std::move(image)); Window::Theme::Background()->set(*paper, std::move(image));
_backgroundCanWrite = true; _backgroundCanWrite = true;

View file

@ -752,7 +752,7 @@ void ChatBackground::set(const Data::WallPaper &paper, QImage image) {
Qt::SmoothTransformation); Qt::SmoothTransformation);
} }
} else if (Data::IsDefaultWallPaper(_paper) } else if (Data::IsDefaultWallPaper(_paper)
|| (!_paper.backgroundColor() && image.isNull())) { || (_paper.backgroundColors().empty() && image.isNull())) {
setPaper(Data::DefaultWallPaper().withParamsFrom(_paper)); setPaper(Data::DefaultWallPaper().withParamsFrom(_paper));
image.load(qsl(":/gui/art/background.jpg")); image.load(qsl(":/gui/art/background.jpg"));
} }