Load chat cloud themes list.

This commit is contained in:
John Preston 2021-08-25 19:16:50 +03:00
parent 70808dfa7d
commit f3dd8c68b3
10 changed files with 192 additions and 32 deletions

View file

@ -887,6 +887,7 @@ void ApplyChannelUpdate(
session->changes().peerUpdated(channel, UpdateFlag::StickersSet);
}
}
channel->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty()));
channel->fullUpdated();
if (canViewAdmins != channel->canViewAdmins()

View file

@ -428,6 +428,7 @@ void ApplyChatUpdate(not_null<ChatData*> chat, const MTPDchatFull &update) {
SetTopPinnedMessageId(chat, pinned->v);
}
chat->checkFolder(update.vfolder_id().value_or_empty());
chat->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty()));
chat->fullUpdated();
chat->setAbout(qs(update.vabout()));

View file

@ -31,21 +31,69 @@ constexpr auto kReloadTimeout = 3600 * crl::time(1000);
CloudTheme CloudTheme::Parse(
not_null<Main::Session*> session,
const MTPDtheme &data) {
const MTPDtheme &data,
bool parseSettings) {
constexpr auto size = sizeof(CloudTheme);
const auto document = data.vdocument();
const auto paper = [&]() -> std::optional<WallPaper> {
if (const auto settings = data.vsettings()) {
settings->match([&](const MTPDthemeSettings &data) {
return data.vwallpaper()
? std::make_optional(
WallPaper::Create(session, *data.vwallpaper()))
: std::nullopt;
});
}
return {};
};
const auto outgoingMessagesColors = [&] {
auto result = std::vector<QColor>();
if (const auto settings = data.vsettings()) {
settings->match([&](const MTPDthemeSettings &data) {
if (const auto colors = data.vmessage_colors()) {
for (const auto color : colors->v) {
result.push_back(ColorFromSerialized(color));
}
}
});
}
return result;
};
const auto accentColor = [&]() -> std::optional<QColor> {
if (const auto settings = data.vsettings()) {
settings->match([&](const MTPDthemeSettings &data) {
return ColorFromSerialized(data.vaccent_color().v);
});
}
return {};
};
return {
data.vid().v,
data.vaccess_hash().v,
qs(data.vslug()),
qs(data.vtitle()),
(document
.id = data.vid().v,
.accessHash = data.vaccess_hash().v,
.slug = qs(data.vslug()),
.title = qs(data.vtitle()),
.documentId = (document
? session->data().processDocument(*document)->id
: DocumentId(0)),
data.is_creator() ? session->userId() : UserId(0),
data.vinstalls_count().value_or_empty()
.createdBy = data.is_creator() ? session->userId() : UserId(0),
.usersCount = data.vinstalls_count().value_or_empty(),
.paper = parseSettings ? paper() : std::nullopt,
.accentColor = parseSettings ? accentColor() : std::nullopt,
.outgoingMessagesColors = (parseSettings
? outgoingMessagesColors()
: std::vector<QColor>()),
};
}
CloudTheme CloudTheme::Parse(
not_null<Main::Session*> session,
const MTPTheme &data,
bool parseSettings) {
return data.match([&](const MTPDtheme &data) {
return CloudTheme::Parse(session, data, parseSettings);
});
}
QString CloudThemes::Format() {
static const auto kResult = QString::fromLatin1("tdesktop");
return kResult;
@ -256,14 +304,14 @@ void CloudThemes::scheduleReload() {
}
void CloudThemes::refresh() {
if (_refreshRquestId) {
if (_refreshRequestId) {
return;
}
_refreshRquestId = _session->api().request(MTPaccount_GetThemes(
_refreshRequestId = _session->api().request(MTPaccount_GetThemes(
MTP_string(Format()),
MTP_int(_hash)
)).done([=](const MTPaccount_Themes &result) {
_refreshRquestId = 0;
_refreshRequestId = 0;
result.match([&](const MTPDaccount_themes &data) {
_hash = data.vhash().v;
parseThemes(data.vthemes().v);
@ -271,7 +319,7 @@ void CloudThemes::refresh() {
}, [](const MTPDaccount_themesNotModified &) {
});
}).fail([=](const MTP::Error &error) {
_refreshRquestId = 0;
_refreshRequestId = 0;
}).send();
}
@ -279,13 +327,61 @@ void CloudThemes::parseThemes(const QVector<MTPTheme> &list) {
_list.clear();
_list.reserve(list.size());
for (const auto &theme : list) {
theme.match([&](const MTPDtheme &data) {
_list.push_back(CloudTheme::Parse(_session, data));
});
_list.push_back(CloudTheme::Parse(_session, theme));
}
checkCurrentTheme();
}
void CloudThemes::refreshChatThemes() {
if (_chatThemesRequestId) {
return;
}
_chatThemesRequestId = _session->api().request(MTPaccount_GetChatThemes(
MTP_int(_chatThemesHash)
)).done([=](const MTPaccount_ChatThemes &result) {
_chatThemesRequestId = 0;
result.match([&](const MTPDaccount_chatThemes &data) {
_hash = data.vhash().v;
parseChatThemes(data.vthemes().v);
_chatThemesUpdates.fire({});
}, [](const MTPDaccount_chatThemesNotModified &) {
});
}).fail([=](const MTP::Error &error) {
_chatThemesRequestId = 0;
}).send();
}
const std::vector<ChatTheme> &CloudThemes::chatThemes() const {
return _chatThemes;
}
rpl::producer<> CloudThemes::chatThemesUpdated() const {
return _chatThemesUpdates.events();
}
std::optional<ChatTheme> CloudThemes::themeForEmoji(
const QString &emoji) const {
if (emoji.isEmpty()) {
return {};
}
const auto i = ranges::find(_chatThemes, emoji, &ChatTheme::emoji);
return (i != end(_chatThemes)) ? std::make_optional(*i) : std::nullopt;
}
void CloudThemes::parseChatThemes(const QVector<MTPChatTheme> &list) {
_chatThemes.clear();
_chatThemes.reserve(list.size());
for (const auto &theme : list) {
theme.match([&](const MTPDchatTheme &data) {
_chatThemes.push_back({
.emoji = qs(data.vemoticon()),
.light = CloudTheme::Parse(_session, data.vtheme(), true),
.dark = CloudTheme::Parse(_session, data.vdark_theme(), true),
});
});
}
}
void CloudThemes::checkCurrentTheme() {
const auto &object = Window::Theme::Background()->themeObject();
if (!object.cloud.id || !object.cloud.documentId) {

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "base/timer.h"
#include "data/data_wall_paper.h"
class DocumentData;
@ -31,10 +32,24 @@ struct CloudTheme {
DocumentId documentId = 0;
UserId createdBy = 0;
int usersCount = 0;
std::optional<WallPaper> paper;
std::optional<QColor> accentColor;
std::vector<QColor> outgoingMessagesColors;
static CloudTheme Parse(
not_null<Main::Session*> session,
const MTPDtheme &data);
const MTPDtheme &data,
bool parseSettings = false);
static CloudTheme Parse(
not_null<Main::Session*> session,
const MTPTheme &data,
bool parseSettings = false);
};
struct ChatTheme {
QString emoji;
CloudTheme light;
CloudTheme dark;
};
class CloudThemes final {
@ -49,6 +64,12 @@ public:
void savedFromEditor(const CloudTheme &data);
void remove(uint64 cloudThemeId);
void refreshChatThemes();
[[nodiscard]] const std::vector<ChatTheme> &chatThemes() const;
[[nodiscard]] rpl::producer<> chatThemesUpdated() const;
[[nodiscard]] std::optional<ChatTheme> themeForEmoji(
const QString &emoji) const;
void applyUpdate(const MTPTheme &theme);
void resolve(
@ -90,13 +111,20 @@ private:
Fn<void(std::shared_ptr<Data::DocumentMedia>)> callback);
void invokeForLoaded(LoadingDocument &value);
void parseChatThemes(const QVector<MTPChatTheme> &list);
const not_null<Main::Session*> _session;
int32 _hash = 0;
mtpRequestId _refreshRquestId = 0;
mtpRequestId _refreshRequestId = 0;
mtpRequestId _resolveRequestId = 0;
std::vector<CloudTheme> _list;
rpl::event_stream<> _updates;
int32 _chatThemesHash = 0;
mtpRequestId _chatThemesRequestId = 0;
std::vector<ChatTheme> _chatThemes;
rpl::event_stream<> _chatThemesUpdates;
base::Timer _reloadCurrentTimer;
LoadingDocument _updatingFrom;
LoadingDocument _previewFrom;

View file

@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h"
#include "data/data_file_origin.h"
#include "data/data_histories.h"
#include "data/data_cloud_themes.h"
#include "base/unixtime.h"
#include "base/crc32hash.h"
#include "lang/lang_keys.h"
@ -1012,6 +1013,17 @@ PeerId PeerData::groupCallDefaultJoinAs() const {
return 0;
}
void PeerData::setThemeEmoji(const QString &emoji) {
_themeEmoji = emoji;
if (!emoji.isEmpty() && !owner().cloudThemes().themeForEmoji(emoji)) {
owner().cloudThemes().refreshChatThemes();
}
}
const QString &PeerData::themeEmoji() const {
return _themeEmoji;
}
void PeerData::setIsBlocked(bool is) {
const auto status = is
? BlockStatus::Blocked

View file

@ -470,6 +470,9 @@ public:
[[nodiscard]] Data::GroupCall *groupCall() const;
[[nodiscard]] PeerId groupCallDefaultJoinAs() const;
void setThemeEmoji(const QString &emoji);
[[nodiscard]] const QString &themeEmoji() const;
const PeerId id;
QString name;
MTPinputPeer input = MTP_inputPeerEmpty();
@ -515,6 +518,7 @@ private:
LoadedStatus _loadedStatus = LoadedStatus::Not;
QString _about;
QString _themeEmoji;
};

View file

@ -225,6 +225,7 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
user->setAbout(qs(update.vabout().value_or_empty()));
user->setCommonChatsCount(update.vcommon_chats_count().v);
user->checkFolder(update.vfolder_id().value_or_empty());
user->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty()));
user->fullUpdated();
}

View file

@ -45,25 +45,10 @@ constexpr auto kVersion = 1;
return color ? SerializeColor(*color) : quint32(-1);
}
[[nodiscard]] std::optional<QColor> MaybeColorFromSerialized(
quint32 serialized) {
return (serialized == quint32(-1))
? std::nullopt
: std::make_optional(QColor(
int((serialized >> 16) & 0xFFU),
int((serialized >> 8) & 0xFFU),
int(serialized & 0xFFU)));
}
[[nodiscard]] QColor DefaultBackgroundColor() {
return QColor(213, 223, 233);
}
[[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>();
@ -791,6 +776,29 @@ QImage GenerateDitheredGradient(const Data::WallPaper &paper) {
paper.gradientRotation());
}
QColor ColorFromSerialized(quint32 serialized) {
return QColor(
int((serialized >> 16) & 0xFFU),
int((serialized >> 8) & 0xFFU),
int(serialized & 0xFFU));
}
QColor ColorFromSerialized(MTPint serialized) {
return ColorFromSerialized(serialized.v);
}
std::optional<QColor> MaybeColorFromSerialized(
quint32 serialized) {
return (serialized == quint32(-1))
? std::nullopt
: std::make_optional(ColorFromSerialized(serialized));
}
std::optional<QColor> MaybeColorFromSerialized(
const tl::conditional<MTPint> &mtp) {
return mtp ? std::make_optional(ColorFromSerialized(*mtp)) : std::nullopt;
}
namespace details {
WallPaper UninitializedWallPaper() {

View file

@ -139,6 +139,13 @@ private:
int rotation);
[[nodiscard]] QImage GenerateDitheredGradient(const WallPaper &paper);
[[nodiscard]] QColor ColorFromSerialized(quint32 serialized);
[[nodiscard]] QColor ColorFromSerialized(MTPint serialized);
[[nodiscard]] std::optional<QColor> MaybeColorFromSerialized(
quint32 serialized);
[[nodiscard]] std::optional<QColor> MaybeColorFromSerialized(
const tl::conditional<MTPint> &mtp);
namespace details {
[[nodiscard]] WallPaper UninitializedWallPaper();

View file

@ -1061,6 +1061,8 @@ void History::applyServiceChanges(
}
}
}
}, [&](const MTPDmessageActionSetChatTheme &data) {
peer->setThemeEmoji(qs(data.vemoticon()));
}, [](const auto &) {
});
}