mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Load chat cloud themes list.
This commit is contained in:
parent
70808dfa7d
commit
f3dd8c68b3
10 changed files with 192 additions and 32 deletions
|
@ -887,6 +887,7 @@ void ApplyChannelUpdate(
|
||||||
session->changes().peerUpdated(channel, UpdateFlag::StickersSet);
|
session->changes().peerUpdated(channel, UpdateFlag::StickersSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
channel->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty()));
|
||||||
channel->fullUpdated();
|
channel->fullUpdated();
|
||||||
|
|
||||||
if (canViewAdmins != channel->canViewAdmins()
|
if (canViewAdmins != channel->canViewAdmins()
|
||||||
|
|
|
@ -428,6 +428,7 @@ void ApplyChatUpdate(not_null<ChatData*> chat, const MTPDchatFull &update) {
|
||||||
SetTopPinnedMessageId(chat, pinned->v);
|
SetTopPinnedMessageId(chat, pinned->v);
|
||||||
}
|
}
|
||||||
chat->checkFolder(update.vfolder_id().value_or_empty());
|
chat->checkFolder(update.vfolder_id().value_or_empty());
|
||||||
|
chat->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty()));
|
||||||
chat->fullUpdated();
|
chat->fullUpdated();
|
||||||
chat->setAbout(qs(update.vabout()));
|
chat->setAbout(qs(update.vabout()));
|
||||||
|
|
||||||
|
|
|
@ -31,21 +31,69 @@ constexpr auto kReloadTimeout = 3600 * crl::time(1000);
|
||||||
|
|
||||||
CloudTheme CloudTheme::Parse(
|
CloudTheme CloudTheme::Parse(
|
||||||
not_null<Main::Session*> session,
|
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 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 {
|
return {
|
||||||
data.vid().v,
|
.id = data.vid().v,
|
||||||
data.vaccess_hash().v,
|
.accessHash = data.vaccess_hash().v,
|
||||||
qs(data.vslug()),
|
.slug = qs(data.vslug()),
|
||||||
qs(data.vtitle()),
|
.title = qs(data.vtitle()),
|
||||||
(document
|
.documentId = (document
|
||||||
? session->data().processDocument(*document)->id
|
? session->data().processDocument(*document)->id
|
||||||
: DocumentId(0)),
|
: DocumentId(0)),
|
||||||
data.is_creator() ? session->userId() : UserId(0),
|
.createdBy = data.is_creator() ? session->userId() : UserId(0),
|
||||||
data.vinstalls_count().value_or_empty()
|
.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() {
|
QString CloudThemes::Format() {
|
||||||
static const auto kResult = QString::fromLatin1("tdesktop");
|
static const auto kResult = QString::fromLatin1("tdesktop");
|
||||||
return kResult;
|
return kResult;
|
||||||
|
@ -256,14 +304,14 @@ void CloudThemes::scheduleReload() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CloudThemes::refresh() {
|
void CloudThemes::refresh() {
|
||||||
if (_refreshRquestId) {
|
if (_refreshRequestId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_refreshRquestId = _session->api().request(MTPaccount_GetThemes(
|
_refreshRequestId = _session->api().request(MTPaccount_GetThemes(
|
||||||
MTP_string(Format()),
|
MTP_string(Format()),
|
||||||
MTP_int(_hash)
|
MTP_int(_hash)
|
||||||
)).done([=](const MTPaccount_Themes &result) {
|
)).done([=](const MTPaccount_Themes &result) {
|
||||||
_refreshRquestId = 0;
|
_refreshRequestId = 0;
|
||||||
result.match([&](const MTPDaccount_themes &data) {
|
result.match([&](const MTPDaccount_themes &data) {
|
||||||
_hash = data.vhash().v;
|
_hash = data.vhash().v;
|
||||||
parseThemes(data.vthemes().v);
|
parseThemes(data.vthemes().v);
|
||||||
|
@ -271,7 +319,7 @@ void CloudThemes::refresh() {
|
||||||
}, [](const MTPDaccount_themesNotModified &) {
|
}, [](const MTPDaccount_themesNotModified &) {
|
||||||
});
|
});
|
||||||
}).fail([=](const MTP::Error &error) {
|
}).fail([=](const MTP::Error &error) {
|
||||||
_refreshRquestId = 0;
|
_refreshRequestId = 0;
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,13 +327,61 @@ void CloudThemes::parseThemes(const QVector<MTPTheme> &list) {
|
||||||
_list.clear();
|
_list.clear();
|
||||||
_list.reserve(list.size());
|
_list.reserve(list.size());
|
||||||
for (const auto &theme : list) {
|
for (const auto &theme : list) {
|
||||||
theme.match([&](const MTPDtheme &data) {
|
_list.push_back(CloudTheme::Parse(_session, theme));
|
||||||
_list.push_back(CloudTheme::Parse(_session, data));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
checkCurrentTheme();
|
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() {
|
void CloudThemes::checkCurrentTheme() {
|
||||||
const auto &object = Window::Theme::Background()->themeObject();
|
const auto &object = Window::Theme::Background()->themeObject();
|
||||||
if (!object.cloud.id || !object.cloud.documentId) {
|
if (!object.cloud.id || !object.cloud.documentId) {
|
||||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "base/timer.h"
|
#include "base/timer.h"
|
||||||
|
#include "data/data_wall_paper.h"
|
||||||
|
|
||||||
class DocumentData;
|
class DocumentData;
|
||||||
|
|
||||||
|
@ -31,10 +32,24 @@ struct CloudTheme {
|
||||||
DocumentId documentId = 0;
|
DocumentId documentId = 0;
|
||||||
UserId createdBy = 0;
|
UserId createdBy = 0;
|
||||||
int usersCount = 0;
|
int usersCount = 0;
|
||||||
|
std::optional<WallPaper> paper;
|
||||||
|
std::optional<QColor> accentColor;
|
||||||
|
std::vector<QColor> outgoingMessagesColors;
|
||||||
|
|
||||||
static CloudTheme Parse(
|
static CloudTheme Parse(
|
||||||
not_null<Main::Session*> session,
|
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 {
|
class CloudThemes final {
|
||||||
|
@ -49,6 +64,12 @@ public:
|
||||||
void savedFromEditor(const CloudTheme &data);
|
void savedFromEditor(const CloudTheme &data);
|
||||||
void remove(uint64 cloudThemeId);
|
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 applyUpdate(const MTPTheme &theme);
|
||||||
|
|
||||||
void resolve(
|
void resolve(
|
||||||
|
@ -90,13 +111,20 @@ private:
|
||||||
Fn<void(std::shared_ptr<Data::DocumentMedia>)> callback);
|
Fn<void(std::shared_ptr<Data::DocumentMedia>)> callback);
|
||||||
void invokeForLoaded(LoadingDocument &value);
|
void invokeForLoaded(LoadingDocument &value);
|
||||||
|
|
||||||
|
void parseChatThemes(const QVector<MTPChatTheme> &list);
|
||||||
|
|
||||||
const not_null<Main::Session*> _session;
|
const not_null<Main::Session*> _session;
|
||||||
int32 _hash = 0;
|
int32 _hash = 0;
|
||||||
mtpRequestId _refreshRquestId = 0;
|
mtpRequestId _refreshRequestId = 0;
|
||||||
mtpRequestId _resolveRequestId = 0;
|
mtpRequestId _resolveRequestId = 0;
|
||||||
std::vector<CloudTheme> _list;
|
std::vector<CloudTheme> _list;
|
||||||
rpl::event_stream<> _updates;
|
rpl::event_stream<> _updates;
|
||||||
|
|
||||||
|
int32 _chatThemesHash = 0;
|
||||||
|
mtpRequestId _chatThemesRequestId = 0;
|
||||||
|
std::vector<ChatTheme> _chatThemes;
|
||||||
|
rpl::event_stream<> _chatThemesUpdates;
|
||||||
|
|
||||||
base::Timer _reloadCurrentTimer;
|
base::Timer _reloadCurrentTimer;
|
||||||
LoadingDocument _updatingFrom;
|
LoadingDocument _updatingFrom;
|
||||||
LoadingDocument _previewFrom;
|
LoadingDocument _previewFrom;
|
||||||
|
|
|
@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
#include "data/data_histories.h"
|
#include "data/data_histories.h"
|
||||||
|
#include "data/data_cloud_themes.h"
|
||||||
#include "base/unixtime.h"
|
#include "base/unixtime.h"
|
||||||
#include "base/crc32hash.h"
|
#include "base/crc32hash.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
|
@ -1012,6 +1013,17 @@ PeerId PeerData::groupCallDefaultJoinAs() const {
|
||||||
return 0;
|
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) {
|
void PeerData::setIsBlocked(bool is) {
|
||||||
const auto status = is
|
const auto status = is
|
||||||
? BlockStatus::Blocked
|
? BlockStatus::Blocked
|
||||||
|
|
|
@ -470,6 +470,9 @@ public:
|
||||||
[[nodiscard]] Data::GroupCall *groupCall() const;
|
[[nodiscard]] Data::GroupCall *groupCall() const;
|
||||||
[[nodiscard]] PeerId groupCallDefaultJoinAs() const;
|
[[nodiscard]] PeerId groupCallDefaultJoinAs() const;
|
||||||
|
|
||||||
|
void setThemeEmoji(const QString &emoji);
|
||||||
|
[[nodiscard]] const QString &themeEmoji() const;
|
||||||
|
|
||||||
const PeerId id;
|
const PeerId id;
|
||||||
QString name;
|
QString name;
|
||||||
MTPinputPeer input = MTP_inputPeerEmpty();
|
MTPinputPeer input = MTP_inputPeerEmpty();
|
||||||
|
@ -515,6 +518,7 @@ private:
|
||||||
LoadedStatus _loadedStatus = LoadedStatus::Not;
|
LoadedStatus _loadedStatus = LoadedStatus::Not;
|
||||||
|
|
||||||
QString _about;
|
QString _about;
|
||||||
|
QString _themeEmoji;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -225,6 +225,7 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
|
||||||
user->setAbout(qs(update.vabout().value_or_empty()));
|
user->setAbout(qs(update.vabout().value_or_empty()));
|
||||||
user->setCommonChatsCount(update.vcommon_chats_count().v);
|
user->setCommonChatsCount(update.vcommon_chats_count().v);
|
||||||
user->checkFolder(update.vfolder_id().value_or_empty());
|
user->checkFolder(update.vfolder_id().value_or_empty());
|
||||||
|
user->setThemeEmoji(qs(update.vtheme_emoticon().value_or_empty()));
|
||||||
user->fullUpdated();
|
user->fullUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,25 +45,10 @@ constexpr auto kVersion = 1;
|
||||||
return color ? SerializeColor(*color) : quint32(-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() {
|
[[nodiscard]] QColor DefaultBackgroundColor() {
|
||||||
return QColor(213, 223, 233);
|
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(
|
[[nodiscard]] std::vector<QColor> ColorsFromMTP(
|
||||||
const MTPDwallPaperSettings &data) {
|
const MTPDwallPaperSettings &data) {
|
||||||
auto result = std::vector<QColor>();
|
auto result = std::vector<QColor>();
|
||||||
|
@ -791,6 +776,29 @@ QImage GenerateDitheredGradient(const Data::WallPaper &paper) {
|
||||||
paper.gradientRotation());
|
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 {
|
namespace details {
|
||||||
|
|
||||||
WallPaper UninitializedWallPaper() {
|
WallPaper UninitializedWallPaper() {
|
||||||
|
|
|
@ -139,6 +139,13 @@ private:
|
||||||
int rotation);
|
int rotation);
|
||||||
[[nodiscard]] QImage GenerateDitheredGradient(const WallPaper &paper);
|
[[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 {
|
namespace details {
|
||||||
|
|
||||||
[[nodiscard]] WallPaper UninitializedWallPaper();
|
[[nodiscard]] WallPaper UninitializedWallPaper();
|
||||||
|
|
|
@ -1061,6 +1061,8 @@ void History::applyServiceChanges(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}, [&](const MTPDmessageActionSetChatTheme &data) {
|
||||||
|
peer->setThemeEmoji(qs(data.vemoticon()));
|
||||||
}, [](const auto &) {
|
}, [](const auto &) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue