mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-15 21:57:10 +02:00
Update API scheme with new cloud themes.
This commit is contained in:
parent
045689fab1
commit
97ae094c3c
14 changed files with 383 additions and 300 deletions
|
@ -1125,7 +1125,7 @@ restrictionReason#d072acb4 platform:string reason:string text:string = Restricti
|
|||
inputTheme#3c5693e9 id:long access_hash:long = InputTheme;
|
||||
inputThemeSlug#f5890df1 slug:string = InputTheme;
|
||||
|
||||
theme#e802b8dc flags:# creator:flags.0?true default:flags.1?true for_chat:flags.5?true id:long access_hash:long slug:string title:string document:flags.2?Document settings:flags.3?ThemeSettings installs_count:flags.4?int = Theme;
|
||||
theme#a00e67d6 flags:# creator:flags.0?true default:flags.1?true for_chat:flags.5?true id:long access_hash:long slug:string title:string document:flags.2?Document settings:flags.3?Vector<ThemeSettings> emoticon:flags.6?string installs_count:flags.4?int = Theme;
|
||||
|
||||
account.themesNotModified#f41eb622 = account.Themes;
|
||||
account.themes#9a3d8c6d hash:long themes:Vector<Theme> = account.Themes;
|
||||
|
@ -1274,11 +1274,6 @@ account.resetPasswordFailedWait#e3779861 retry_date:int = account.ResetPasswordR
|
|||
account.resetPasswordRequestedWait#e9effc7d until_date:int = account.ResetPasswordResult;
|
||||
account.resetPasswordOk#e926d63e = account.ResetPasswordResult;
|
||||
|
||||
chatTheme#ed0b5c33 emoticon:string theme:Theme dark_theme:Theme = ChatTheme;
|
||||
|
||||
account.chatThemesNotModified#e011e1c4 = account.ChatThemes;
|
||||
account.chatThemes#fe4cbebd hash:int themes:Vector<ChatTheme> = account.ChatThemes;
|
||||
|
||||
sponsoredMessage#d151e19a flags:# random_id:bytes from_id:Peer channel_post:flags.2?int start_param:flags.0?string message:string entities:flags.1?Vector<MessageEntity> = SponsoredMessage;
|
||||
|
||||
messages.sponsoredMessages#65a4c7d5 messages:Vector<SponsoredMessage> chats:Vector<Chat> users:Vector<User> = messages.SponsoredMessages;
|
||||
|
@ -1287,8 +1282,6 @@ searchResultsCalendarPeriod#c9b0539f date:int min_msg_id:int max_msg_id:int coun
|
|||
|
||||
messages.searchResultsCalendar#147ee23c flags:# inexact:flags.0?true count:int min_date:int min_msg_id:int offset_id_offset:flags.1?int periods:Vector<SearchResultsCalendarPeriod> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.SearchResultsCalendar;
|
||||
|
||||
messages.searchResultsRawMessages#7817237c msg_ids:Vector<int> msg_dates:Vector<int> = messages.SearchResultsRawMessages;
|
||||
|
||||
searchResultPosition#7f648b67 msg_id:int date:int offset:int = SearchResultsPosition;
|
||||
|
||||
messages.searchResultsPositions#53b22baf count:int positions:Vector<SearchResultsPosition> = messages.SearchResultsPositions;
|
||||
|
@ -1379,10 +1372,10 @@ account.resetWallPapers#bb3b9804 = Bool;
|
|||
account.getAutoDownloadSettings#56da0b3f = account.AutoDownloadSettings;
|
||||
account.saveAutoDownloadSettings#76f36233 flags:# low:flags.0?true high:flags.1?true settings:AutoDownloadSettings = Bool;
|
||||
account.uploadTheme#1c3db333 flags:# file:InputFile thumb:flags.0?InputFile file_name:string mime_type:string = Document;
|
||||
account.createTheme#8432c21f flags:# slug:string title:string document:flags.2?InputDocument settings:flags.3?InputThemeSettings = Theme;
|
||||
account.updateTheme#5cb367d5 flags:# format:string theme:InputTheme slug:flags.0?string title:flags.1?string document:flags.2?InputDocument settings:flags.3?InputThemeSettings = Theme;
|
||||
account.createTheme#652e4400 flags:# slug:string title:string document:flags.2?InputDocument settings:flags.3?Vector<InputThemeSettings> = Theme;
|
||||
account.updateTheme#2bf40ccc flags:# format:string theme:InputTheme slug:flags.0?string title:flags.1?string document:flags.2?InputDocument settings:flags.3?Vector<InputThemeSettings> = Theme;
|
||||
account.saveTheme#f257106c theme:InputTheme unsave:Bool = Bool;
|
||||
account.installTheme#7ae43737 flags:# dark:flags.0?true format:flags.1?string theme:flags.1?InputTheme = Bool;
|
||||
account.installTheme#c727bb3b flags:# dark:flags.0?true theme:flags.1?InputTheme format:flags.2?string base_theme:flags.3?BaseTheme = Bool;
|
||||
account.getTheme#8d9d742b format:string theme:InputTheme document_id:long = Theme;
|
||||
account.getThemes#7206e458 format:string hash:long = account.Themes;
|
||||
account.setContentSettings#b574b16b flags:# sensitive_enabled:flags.0?true = Bool;
|
||||
|
@ -1393,7 +1386,7 @@ account.setGlobalPrivacySettings#1edaaac2 settings:GlobalPrivacySettings = Globa
|
|||
account.reportProfilePhoto#fa8cc6f5 peer:InputPeer photo_id:InputPhoto reason:ReportReason message:string = Bool;
|
||||
account.resetPassword#9308ce1b = account.ResetPasswordResult;
|
||||
account.declinePasswordReset#4c9409f6 = Bool;
|
||||
account.getChatThemes#d6d71d7b hash:int = account.ChatThemes;
|
||||
account.getChatThemes#d638de89 hash:long = account.Themes;
|
||||
|
||||
users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
|
||||
users.getFullUser#ca30a5b1 id:InputUser = UserFull;
|
||||
|
@ -1425,7 +1418,7 @@ messages.getDialogs#a0f4cb4f flags:# exclude_pinned:flags.0?true folder_id:flags
|
|||
messages.getHistory#4423e6c5 peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
|
||||
messages.search#a0fda762 flags:# peer:InputPeer q:string from_id:flags.0?InputPeer top_msg_id:flags.1?int filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
|
||||
messages.readHistory#e306d3a peer:InputPeer max_id:int = messages.AffectedMessages;
|
||||
messages.deleteHistory#1c015b09 flags:# just_clear:flags.0?true revoke:flags.1?true peer:InputPeer max_id:int = messages.AffectedHistory;
|
||||
messages.deleteHistory#b08f922a flags:# just_clear:flags.0?true revoke:flags.1?true peer:InputPeer max_id:int min_date:flags.2?int max_date:flags.3?int = messages.AffectedHistory;
|
||||
messages.deleteMessages#e58e95d2 flags:# revoke:flags.0?true id:Vector<int> = messages.AffectedMessages;
|
||||
messages.receivedMessages#5a954c0 max_id:int = Vector<ReceivedNotifyMessage>;
|
||||
messages.setTyping#58943ee2 flags:# peer:InputPeer top_msg_id:flags.0?int action:SendMessageAction = Bool;
|
||||
|
@ -1563,8 +1556,7 @@ messages.setHistoryTTL#b80e5fe4 peer:InputPeer period:int = Updates;
|
|||
messages.checkHistoryImportPeer#5dc60f03 peer:InputPeer = messages.CheckedHistoryImportPeer;
|
||||
messages.setChatTheme#e63be13f peer:InputPeer emoticon:string = Updates;
|
||||
messages.getMessageReadParticipants#2c6f97b7 peer:InputPeer msg_id:int = Vector<long>;
|
||||
messages.getSearchResultsCalendar#8948d7e3 flags:# by_months:flags.0?true peer:InputPeer filter:MessagesFilter offset_id:int offset_date:int = messages.SearchResultsCalendar;
|
||||
messages.getSearchResultsRawMessages#4b08919a peer:InputPeer filter:MessagesFilter offset_id:int offset_date:int = messages.SearchResultsRawMessages;
|
||||
messages.getSearchResultsCalendar#49f0bde9 peer:InputPeer filter:MessagesFilter offset_id:int offset_date:int = messages.SearchResultsCalendar;
|
||||
messages.getSearchResultsPositions#6e9583a3 peer:InputPeer filter:MessagesFilter offset_id:int limit:int = messages.SearchResultsPositions;
|
||||
messages.hideChatJoinRequest#7fe7e815 flags:# approved:flags.0?true peer:InputPeer user_id:InputUser = Updates;
|
||||
|
||||
|
|
|
@ -477,78 +477,77 @@ bool ShowInviteLink(
|
|||
void ExportTestChatTheme(
|
||||
not_null<Main::Session*> session,
|
||||
not_null<const Data::CloudTheme*> theme) {
|
||||
if (!theme->paper
|
||||
|| !theme->paper->isPattern()
|
||||
|| theme->paper->backgroundColors().empty()
|
||||
|| !theme->accentColor
|
||||
|| !theme->paper->hasShareUrl()) {
|
||||
Ui::Toast::Show("Something went wrong :(");
|
||||
return;
|
||||
}
|
||||
const auto &bg = theme->paper->backgroundColors();
|
||||
const auto url = theme->paper->shareUrl(session);
|
||||
const auto from = url.indexOf("bg/");
|
||||
const auto till = url.indexOf("?");
|
||||
if (from < 0 || till <= from) {
|
||||
Ui::Toast::Show("Bad WallPaper link: " + url);
|
||||
return;
|
||||
}
|
||||
|
||||
using Flag = MTPaccount_CreateTheme::Flag;
|
||||
using Setting = MTPDinputThemeSettings::Flag;
|
||||
using Paper = MTPDwallPaperSettings::Flag;
|
||||
const auto color = [](const QColor &color) {
|
||||
const auto red = color.red();
|
||||
const auto green = color.green();
|
||||
const auto blue = color.blue();
|
||||
return int(((uint32(red) & 0xFFU) << 16)
|
||||
| ((uint32(green) & 0xFFU) << 8)
|
||||
| (uint32(blue) & 0xFFU));
|
||||
};
|
||||
const auto colors = [&](const std::vector<QColor> &colors) {
|
||||
auto result = QVector<MTPint>();
|
||||
result.reserve(colors.size());
|
||||
for (const auto &single : colors) {
|
||||
result.push_back(MTP_int(color(single)));
|
||||
const auto inputSettings = [&](Data::CloudThemeType type)
|
||||
-> std::optional<MTPInputThemeSettings> {
|
||||
const auto i = theme->settings.find(type);
|
||||
if (i == end(theme->settings)) {
|
||||
Ui::Toast::Show("Something went wrong :(");
|
||||
return std::nullopt;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const auto slug = url.mid(from + 3, till - from - 3);
|
||||
const auto flags = Flag::f_settings;
|
||||
const auto settings = Setting::f_wallpaper
|
||||
| Setting::f_wallpaper_settings
|
||||
| (theme->outgoingAccentColor
|
||||
? Setting::f_outbox_accent_color
|
||||
: Setting(0))
|
||||
| (!theme->outgoingMessagesColors.empty()
|
||||
? Setting::f_message_colors
|
||||
: Setting(0));
|
||||
const auto papers = Paper::f_background_color
|
||||
| Paper::f_intensity
|
||||
| (bg.size() > 1
|
||||
? Paper::f_second_background_color
|
||||
: Paper(0))
|
||||
| (bg.size() > 2
|
||||
? Paper::f_third_background_color
|
||||
: Paper(0))
|
||||
| (bg.size() > 3
|
||||
? Paper::f_fourth_background_color
|
||||
: Paper(0));
|
||||
session->api().request(MTPaccount_CreateTheme(
|
||||
MTP_flags(flags),
|
||||
MTP_string(Window::Theme::GenerateSlug()),
|
||||
MTP_string(theme->title + " Desktop"),
|
||||
MTPInputDocument(),
|
||||
MTP_inputThemeSettings(
|
||||
const auto &fields = i->second;
|
||||
if (!fields.paper
|
||||
|| !fields.paper->isPattern()
|
||||
|| fields.paper->backgroundColors().empty()
|
||||
|| !fields.paper->hasShareUrl()) {
|
||||
Ui::Toast::Show("Something went wrong :(");
|
||||
return std::nullopt;
|
||||
}
|
||||
const auto &bg = fields.paper->backgroundColors();
|
||||
const auto url = fields.paper->shareUrl(session);
|
||||
const auto from = url.indexOf("bg/");
|
||||
const auto till = url.indexOf("?");
|
||||
if (from < 0 || till <= from) {
|
||||
Ui::Toast::Show("Bad WallPaper link: " + url);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
using Setting = MTPDinputThemeSettings::Flag;
|
||||
using Paper = MTPDwallPaperSettings::Flag;
|
||||
const auto color = [](const QColor &color) {
|
||||
const auto red = color.red();
|
||||
const auto green = color.green();
|
||||
const auto blue = color.blue();
|
||||
return int(((uint32(red) & 0xFFU) << 16)
|
||||
| ((uint32(green) & 0xFFU) << 8)
|
||||
| (uint32(blue) & 0xFFU));
|
||||
};
|
||||
const auto colors = [&](const std::vector<QColor> &colors) {
|
||||
auto result = QVector<MTPint>();
|
||||
result.reserve(colors.size());
|
||||
for (const auto &single : colors) {
|
||||
result.push_back(MTP_int(color(single)));
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const auto slug = url.mid(from + 3, till - from - 3);
|
||||
const auto settings = Setting::f_wallpaper
|
||||
| Setting::f_wallpaper_settings
|
||||
| (fields.outgoingAccentColor
|
||||
? Setting::f_outbox_accent_color
|
||||
: Setting(0))
|
||||
| (!fields.outgoingMessagesColors.empty()
|
||||
? Setting::f_message_colors
|
||||
: Setting(0));
|
||||
const auto papers = Paper::f_background_color
|
||||
| Paper::f_intensity
|
||||
| (bg.size() > 1
|
||||
? Paper::f_second_background_color
|
||||
: Paper(0))
|
||||
| (bg.size() > 2
|
||||
? Paper::f_third_background_color
|
||||
: Paper(0))
|
||||
| (bg.size() > 3
|
||||
? Paper::f_fourth_background_color
|
||||
: Paper(0));
|
||||
return MTP_inputThemeSettings(
|
||||
MTP_flags(settings),
|
||||
(theme->basedOnDark
|
||||
((type == Data::CloudThemeType::Dark)
|
||||
? MTP_baseThemeTinted()
|
||||
: MTP_baseThemeClassic()),
|
||||
MTP_int(color(theme->accentColor.value_or(Qt::black))),
|
||||
MTP_int(color(theme->outgoingAccentColor.value_or(
|
||||
MTP_int(color(fields.accentColor)),
|
||||
MTP_int(color(fields.outgoingAccentColor.value_or(
|
||||
Qt::black))),
|
||||
MTP_vector<MTPint>(colors(
|
||||
theme->outgoingMessagesColors)),
|
||||
MTP_vector<MTPint>(colors(fields.outgoingMessagesColors)),
|
||||
MTP_inputWallPaperSlug(MTP_string(slug)),
|
||||
MTP_wallPaperSettings(
|
||||
MTP_flags(papers),
|
||||
|
@ -556,8 +555,26 @@ void ExportTestChatTheme(
|
|||
MTP_int(color(bg.size() > 1 ? bg[1] : Qt::black)),
|
||||
MTP_int(color(bg.size() > 2 ? bg[2] : Qt::black)),
|
||||
MTP_int(color(bg.size() > 3 ? bg[3] : Qt::black)),
|
||||
MTP_int(theme->paper->patternIntensity()),
|
||||
MTP_int(0)))
|
||||
MTP_int(fields.paper->patternIntensity()),
|
||||
MTP_int(0)));
|
||||
};
|
||||
const auto light = inputSettings(Data::CloudThemeType::Light);
|
||||
if (!light) {
|
||||
return;
|
||||
}
|
||||
const auto dark = inputSettings(Data::CloudThemeType::Dark);
|
||||
if (!dark) {
|
||||
return;
|
||||
}
|
||||
session->api().request(MTPaccount_CreateTheme(
|
||||
MTP_flags(MTPaccount_CreateTheme::Flag::f_settings),
|
||||
MTP_string(Window::Theme::GenerateSlug()),
|
||||
MTP_string(theme->title + " Desktop"),
|
||||
MTPInputDocument(),
|
||||
MTP_vector<MTPInputThemeSettings>(QVector<MTPInputThemeSettings>{
|
||||
*light,
|
||||
*dark,
|
||||
})
|
||||
)).done([=](const MTPTheme &result) {
|
||||
const auto slug = Data::CloudTheme::Parse(session, result, true).slug;
|
||||
QGuiApplication::clipboard()->setText(
|
||||
|
@ -587,8 +604,13 @@ bool ResolveTestChatTheme(
|
|||
if (!params["export"].isEmpty()) {
|
||||
ExportTestChatTheme(&controller->session(), &*theme);
|
||||
}
|
||||
[[maybe_unused]] auto value = controller->cachedChatThemeValue(
|
||||
*theme);
|
||||
const auto recache = [&](Data::CloudThemeType type) {
|
||||
[[maybe_unused]] auto value = theme->settings.contains(type)
|
||||
? controller->cachedChatThemeValue(*theme, type)
|
||||
: nullptr;
|
||||
};
|
||||
recache(Data::CloudThemeType::Dark);
|
||||
recache(Data::CloudThemeType::Light);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -36,60 +36,64 @@ CloudTheme CloudTheme::Parse(
|
|||
const MTPDtheme &data,
|
||||
bool parseSettings) {
|
||||
const auto document = data.vdocument();
|
||||
const auto paper = [&]() -> std::optional<WallPaper> {
|
||||
if (const auto settings = data.vsettings()) {
|
||||
return settings->match([&](const MTPDthemeSettings &data) {
|
||||
return data.vwallpaper()
|
||||
? WallPaper::Create(session, *data.vwallpaper())
|
||||
: std::nullopt;
|
||||
});
|
||||
}
|
||||
return {};
|
||||
const auto paper = [&](const MTPThemeSettings &settings) {
|
||||
return settings.match([&](const MTPDthemeSettings &data) {
|
||||
return data.vwallpaper()
|
||||
? WallPaper::Create(session, *data.vwallpaper())
|
||||
: std::nullopt;
|
||||
});
|
||||
};
|
||||
const auto outgoingMessagesColors = [&] {
|
||||
const auto outgoingMessagesColors = [&](
|
||||
const MTPThemeSettings &settings) {
|
||||
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));
|
||||
}
|
||||
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 = [&](const MTPThemeSettings &settings) {
|
||||
return settings.match([&](const MTPDthemeSettings &data) {
|
||||
return ColorFromSerialized(data.vaccent_color().v);
|
||||
});
|
||||
};
|
||||
const auto outgoingAccentColor = [&](const MTPThemeSettings &settings) {
|
||||
return settings.match([&](const MTPDthemeSettings &data) {
|
||||
return MaybeColorFromSerialized(data.voutbox_accent_color());
|
||||
});
|
||||
};
|
||||
const auto basedOnDark = [&](const MTPThemeSettings &settings) {
|
||||
return settings.match([&](const MTPDthemeSettings &data) {
|
||||
return data.vbase_theme().match([](
|
||||
const MTPDbaseThemeNight &) {
|
||||
return true;
|
||||
}, [](const MTPDbaseThemeTinted &) {
|
||||
return true;
|
||||
}, [](const auto &) {
|
||||
return false;
|
||||
});
|
||||
});
|
||||
};
|
||||
const auto settings = [&] {
|
||||
auto result = base::flat_map<Type, Settings>();
|
||||
const auto settings = data.vsettings();
|
||||
if (!settings) {
|
||||
return result;
|
||||
}
|
||||
for (const auto &fields : settings->v) {
|
||||
const auto type = basedOnDark(fields) ? Type::Dark : Type::Light;
|
||||
result.emplace(type, Settings{
|
||||
.paper = paper(fields),
|
||||
.accentColor = accentColor(fields),
|
||||
.outgoingAccentColor = outgoingAccentColor(fields),
|
||||
.outgoingMessagesColors = outgoingMessagesColors(fields),
|
||||
});
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const auto accentColor = [&]() -> std::optional<QColor> {
|
||||
if (const auto settings = data.vsettings()) {
|
||||
return settings->match([&](const MTPDthemeSettings &data) {
|
||||
return ColorFromSerialized(data.vaccent_color().v);
|
||||
});
|
||||
}
|
||||
return {};
|
||||
};
|
||||
const auto outgoingAccentColor = [&]() -> std::optional<QColor> {
|
||||
if (const auto settings = data.vsettings()) {
|
||||
return settings->match([&](const MTPDthemeSettings &data) {
|
||||
return MaybeColorFromSerialized(data.voutbox_accent_color());
|
||||
});
|
||||
}
|
||||
return {};
|
||||
};
|
||||
const auto basedOnDark = [&] {
|
||||
if (const auto settings = data.vsettings()) {
|
||||
return settings->match([&](const MTPDthemeSettings &data) {
|
||||
return data.vbase_theme().match([](
|
||||
const MTPDbaseThemeNight &) {
|
||||
return true;
|
||||
}, [](const MTPDbaseThemeTinted &) {
|
||||
return true;
|
||||
}, [](const auto &) {
|
||||
return false;
|
||||
});
|
||||
});
|
||||
}
|
||||
return false;
|
||||
};
|
||||
return {
|
||||
.id = data.vid().v,
|
||||
.accessHash = data.vaccess_hash().v,
|
||||
|
@ -100,15 +104,10 @@ CloudTheme CloudTheme::Parse(
|
|||
: DocumentId(0)),
|
||||
.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,
|
||||
.outgoingAccentColor = (parseSettings
|
||||
? outgoingAccentColor()
|
||||
: std::nullopt),
|
||||
.outgoingMessagesColors = (parseSettings
|
||||
? outgoingMessagesColors()
|
||||
: std::vector<QColor>()),
|
||||
.basedOnDark = parseSettings && basedOnDark(),
|
||||
.emoticon = qs(data.vemoticon().value_or_empty()),
|
||||
.settings = (parseSettings
|
||||
? settings()
|
||||
: base::flat_map<Type, Settings>()),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -176,8 +175,9 @@ void CloudThemes::install() {
|
|||
| (themeId ? Flag::f_theme : Flag(0));
|
||||
_session->api().request(MTPaccount_InstallTheme(
|
||||
MTP_flags(flags),
|
||||
MTP_inputTheme(MTP_long(cloudId), MTP_long(fields.accessHash)),
|
||||
MTP_string(Format()),
|
||||
MTP_inputTheme(MTP_long(cloudId), MTP_long(fields.accessHash))
|
||||
MTPBaseTheme()
|
||||
)).send();
|
||||
}
|
||||
|
||||
|
@ -364,21 +364,21 @@ void CloudThemes::refreshChatThemes() {
|
|||
return;
|
||||
}
|
||||
_chatThemesRequestId = _session->api().request(MTPaccount_GetChatThemes(
|
||||
MTP_int(_chatThemesHash)
|
||||
)).done([=](const MTPaccount_ChatThemes &result) {
|
||||
MTP_long(_chatThemesHash)
|
||||
)).done([=](const MTPaccount_Themes &result) {
|
||||
_chatThemesRequestId = 0;
|
||||
result.match([&](const MTPDaccount_chatThemes &data) {
|
||||
_hash = data.vhash().v;
|
||||
result.match([&](const MTPDaccount_themes &data) {
|
||||
_chatThemesHash = data.vhash().v;
|
||||
parseChatThemes(data.vthemes().v);
|
||||
_chatThemesUpdates.fire({});
|
||||
}, [](const MTPDaccount_chatThemesNotModified &) {
|
||||
}, [](const MTPDaccount_themesNotModified &) {
|
||||
});
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
_chatThemesRequestId = 0;
|
||||
}).send();
|
||||
}
|
||||
|
||||
const std::vector<ChatTheme> &CloudThemes::chatThemes() const {
|
||||
const std::vector<CloudTheme> &CloudThemes::chatThemes() const {
|
||||
return _chatThemes;
|
||||
}
|
||||
|
||||
|
@ -386,23 +386,23 @@ rpl::producer<> CloudThemes::chatThemesUpdated() const {
|
|||
return _chatThemesUpdates.events();
|
||||
}
|
||||
|
||||
std::optional<ChatTheme> CloudThemes::themeForEmoji(
|
||||
std::optional<CloudTheme> CloudThemes::themeForEmoji(
|
||||
const QString &emoticon) const {
|
||||
const auto emoji = Ui::Emoji::Find(emoticon);
|
||||
if (!emoji) {
|
||||
return {};
|
||||
}
|
||||
const auto i = ranges::find(_chatThemes, emoji, [](const ChatTheme &v) {
|
||||
const auto i = ranges::find(_chatThemes, emoji, [](const CloudTheme &v) {
|
||||
return Ui::Emoji::Find(v.emoticon);
|
||||
});
|
||||
return (i != end(_chatThemes)) ? std::make_optional(*i) : std::nullopt;
|
||||
}
|
||||
|
||||
rpl::producer<std::optional<ChatTheme>> CloudThemes::themeForEmojiValue(
|
||||
rpl::producer<std::optional<CloudTheme>> CloudThemes::themeForEmojiValue(
|
||||
const QString &emoticon) {
|
||||
const auto testing = TestingColors();
|
||||
if (!Ui::Emoji::Find(emoticon)) {
|
||||
return rpl::single<std::optional<ChatTheme>>(std::nullopt);
|
||||
return rpl::single<std::optional<CloudTheme>>(std::nullopt);
|
||||
} else if (auto result = themeForEmoji(emoticon)) {
|
||||
if (testing) {
|
||||
return rpl::single(
|
||||
|
@ -410,7 +410,7 @@ rpl::producer<std::optional<ChatTheme>> CloudThemes::themeForEmojiValue(
|
|||
) | rpl::then(chatThemesUpdated(
|
||||
) | rpl::map([=] {
|
||||
return themeForEmoji(emoticon);
|
||||
}) | rpl::filter([](const std::optional<ChatTheme> &theme) {
|
||||
}) | rpl::filter([](const std::optional<CloudTheme> &theme) {
|
||||
return theme.has_value();
|
||||
}));
|
||||
}
|
||||
|
@ -418,12 +418,12 @@ rpl::producer<std::optional<ChatTheme>> CloudThemes::themeForEmojiValue(
|
|||
}
|
||||
refreshChatThemes();
|
||||
const auto limit = testing ? (1 << 20) : 1;
|
||||
return rpl::single<std::optional<ChatTheme>>(
|
||||
return rpl::single<std::optional<CloudTheme>>(
|
||||
std::nullopt
|
||||
) | rpl::then(chatThemesUpdated(
|
||||
) | rpl::map([=] {
|
||||
return themeForEmoji(emoticon);
|
||||
}) | rpl::filter([](const std::optional<ChatTheme> &theme) {
|
||||
}) | rpl::filter([](const std::optional<CloudTheme> &theme) {
|
||||
return theme.has_value();
|
||||
}) | rpl::take(limit));
|
||||
}
|
||||
|
@ -454,30 +454,33 @@ QString CloudThemes::prepareTestingLink(const CloudTheme &theme) const {
|
|||
return list.join(",");
|
||||
};
|
||||
auto arguments = QStringList();
|
||||
if (theme.basedOnDark) {
|
||||
arguments.push_back("dark=1");
|
||||
}
|
||||
if (theme.accentColor) {
|
||||
arguments.push_back("accent=" + color(*theme.accentColor));
|
||||
}
|
||||
if (theme.paper && !theme.paper->backgroundColors().empty()) {
|
||||
arguments.push_back("bg=" + colors(theme.paper->backgroundColors()));
|
||||
}
|
||||
if (theme.paper/* && theme.paper->hasShareUrl()*/) {
|
||||
arguments.push_back("intensity="
|
||||
+ QString::number(theme.paper->patternIntensity()));
|
||||
//const auto url = theme.paper->shareUrl(_session);
|
||||
//const auto from = url.indexOf("bg/");
|
||||
//const auto till = url.indexOf("?");
|
||||
//if (from > 0 && till > from) {
|
||||
// arguments.push_back("slug=" + url.mid(from + 3, till - from - 3));
|
||||
//}
|
||||
}
|
||||
if (theme.outgoingAccentColor) {
|
||||
arguments.push_back("out_accent" + color(*theme.outgoingAccentColor));
|
||||
}
|
||||
if (!theme.outgoingMessagesColors.empty()) {
|
||||
arguments.push_back("out_bg=" + colors(theme.outgoingMessagesColors));
|
||||
for (const auto &[type, settings] : theme.settings) {
|
||||
const auto add = [&](const QString &value) {
|
||||
const auto prefix = (type == CloudTheme::Type::Dark)
|
||||
? u"dark_"_q
|
||||
: u""_q;
|
||||
arguments.push_back(prefix + value);
|
||||
};
|
||||
add("accent=" + color(settings.accentColor));
|
||||
if (settings.paper && !settings.paper->backgroundColors().empty()) {
|
||||
add("bg=" + colors(settings.paper->backgroundColors()));
|
||||
}
|
||||
if (settings.paper/* && settings.paper->hasShareUrl()*/) {
|
||||
add("intensity="
|
||||
+ QString::number(settings.paper->patternIntensity()));
|
||||
//const auto url = settings.paper->shareUrl(_session);
|
||||
//const auto from = url.indexOf("bg/");
|
||||
//const auto till = url.indexOf("?");
|
||||
//if (from > 0 && till > from) {
|
||||
// add("slug=" + url.mid(from + 3, till - from - 3));
|
||||
//}
|
||||
}
|
||||
if (settings.outgoingAccentColor) {
|
||||
add("out_accent" + color(*settings.outgoingAccentColor));
|
||||
}
|
||||
if (!settings.outgoingMessagesColors.empty()) {
|
||||
add("out_bg=" + colors(settings.outgoingMessagesColors));
|
||||
}
|
||||
}
|
||||
return arguments.isEmpty()
|
||||
? QString()
|
||||
|
@ -491,7 +494,7 @@ std::optional<CloudTheme> CloudThemes::updateThemeFromLink(
|
|||
if (!TestingColors() || !emoji) {
|
||||
return std::nullopt;
|
||||
}
|
||||
const auto i = ranges::find(_chatThemes, emoji, [](const ChatTheme &v) {
|
||||
const auto i = ranges::find(_chatThemes, emoji, [](const CloudTheme &v) {
|
||||
return Ui::Emoji::Find(v.emoticon);
|
||||
});
|
||||
if (i == end(_chatThemes)) {
|
||||
|
@ -536,33 +539,42 @@ std::optional<CloudTheme> CloudThemes::updateThemeFromLink(
|
|||
return (result.size() > 4) ? std::vector<QColor>() : result;
|
||||
};
|
||||
|
||||
auto &applyTo = params["dark"].isEmpty() ? i->light : i->dark;
|
||||
applyTo.accentColor = color(params["accent"]);
|
||||
const auto bg = colors(params["bg"]);
|
||||
applyTo.paper = (applyTo.paper && !bg.empty())
|
||||
? std::make_optional(applyTo.paper->withBackgroundColors(bg))
|
||||
: applyTo.paper;
|
||||
applyTo.paper = (applyTo.paper && params["intensity"].toInt())
|
||||
? std::make_optional(
|
||||
applyTo.paper->withPatternIntensity(params["intensity"].toInt()))
|
||||
: applyTo.paper;
|
||||
applyTo.outgoingAccentColor = color(params["out_accent"]);
|
||||
applyTo.outgoingMessagesColors = colors(params["out_bg"]);
|
||||
const auto parse = [&](CloudThemeType type, const QString &prefix = {}) {
|
||||
const auto accent = color(params["accent"]);
|
||||
if (!accent) {
|
||||
return;
|
||||
}
|
||||
auto &settings = i->settings[type];
|
||||
settings.accentColor = *accent;
|
||||
const auto bg = colors(params["bg"]);
|
||||
settings.paper = (settings.paper && !bg.empty())
|
||||
? std::make_optional(settings.paper->withBackgroundColors(bg))
|
||||
: settings.paper;
|
||||
settings.paper = (settings.paper && params["intensity"].toInt())
|
||||
? std::make_optional(
|
||||
settings.paper->withPatternIntensity(
|
||||
params["intensity"].toInt()))
|
||||
: settings.paper;
|
||||
settings.outgoingAccentColor = color(params["out_accent"]);
|
||||
settings.outgoingMessagesColors = colors(params["out_bg"]);
|
||||
};
|
||||
if (params.contains("dark_accent")) {
|
||||
parse(CloudThemeType::Dark, "dark_");
|
||||
}
|
||||
if (params.contains("accent")) {
|
||||
parse(params["dark"].isEmpty()
|
||||
? CloudThemeType::Light
|
||||
: CloudThemeType::Dark);
|
||||
}
|
||||
_chatThemesUpdates.fire({});
|
||||
return applyTo;
|
||||
return *i;
|
||||
}
|
||||
|
||||
void CloudThemes::parseChatThemes(const QVector<MTPChatTheme> &list) {
|
||||
void CloudThemes::parseChatThemes(const QVector<MTPTheme> &list) {
|
||||
_chatThemes.clear();
|
||||
_chatThemes.reserve(list.size());
|
||||
for (const auto &theme : list) {
|
||||
theme.match([&](const MTPDchatTheme &data) {
|
||||
_chatThemes.push_back({
|
||||
.emoticon = qs(data.vemoticon()),
|
||||
.light = CloudTheme::Parse(_session, data.vtheme(), true),
|
||||
.dark = CloudTheme::Parse(_session, data.vdark_theme(), true),
|
||||
});
|
||||
});
|
||||
_chatThemes.push_back(CloudTheme::Parse(_session, theme, true));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,11 @@ namespace Data {
|
|||
|
||||
class DocumentMedia;
|
||||
|
||||
enum class CloudThemeType {
|
||||
Dark,
|
||||
Light,
|
||||
};
|
||||
|
||||
struct CloudTheme {
|
||||
uint64 id = 0;
|
||||
uint64 accessHash = 0;
|
||||
|
@ -32,12 +37,16 @@ struct CloudTheme {
|
|||
DocumentId documentId = 0;
|
||||
UserId createdBy = 0;
|
||||
int usersCount = 0;
|
||||
QString emoticon;
|
||||
|
||||
std::optional<WallPaper> paper;
|
||||
std::optional<QColor> accentColor;
|
||||
std::optional<QColor> outgoingAccentColor;
|
||||
std::vector<QColor> outgoingMessagesColors;
|
||||
bool basedOnDark = false;
|
||||
using Type = CloudThemeType;
|
||||
struct Settings {
|
||||
std::optional<WallPaper> paper;
|
||||
QColor accentColor;
|
||||
std::optional<QColor> outgoingAccentColor;
|
||||
std::vector<QColor> outgoingMessagesColors;
|
||||
};
|
||||
base::flat_map<Type, Settings> settings;
|
||||
|
||||
static CloudTheme Parse(
|
||||
not_null<Main::Session*> session,
|
||||
|
@ -49,12 +58,6 @@ struct CloudTheme {
|
|||
bool parseSettings = false);
|
||||
};
|
||||
|
||||
struct ChatTheme {
|
||||
QString emoticon;
|
||||
CloudTheme light;
|
||||
CloudTheme dark;
|
||||
};
|
||||
|
||||
class CloudThemes final {
|
||||
public:
|
||||
explicit CloudThemes(not_null<Main::Session*> session);
|
||||
|
@ -68,12 +71,12 @@ public:
|
|||
void remove(uint64 cloudThemeId);
|
||||
|
||||
void refreshChatThemes();
|
||||
[[nodiscard]] const std::vector<ChatTheme> &chatThemes() const;
|
||||
[[nodiscard]] const std::vector<CloudTheme> &chatThemes() const;
|
||||
[[nodiscard]] rpl::producer<> chatThemesUpdated() const;
|
||||
[[nodiscard]] std::optional<ChatTheme> themeForEmoji(
|
||||
[[nodiscard]] std::optional<CloudTheme> themeForEmoji(
|
||||
const QString &emoticon) const;
|
||||
[[nodiscard]] rpl::producer<std::optional<ChatTheme>> themeForEmojiValue(
|
||||
const QString &emoticon);
|
||||
[[nodiscard]] auto themeForEmojiValue(const QString &emoticon)
|
||||
-> rpl::producer<std::optional<CloudTheme>>;
|
||||
|
||||
[[nodiscard]] static bool TestingColors();
|
||||
static void SetTestingColors(bool testing);
|
||||
|
@ -123,7 +126,7 @@ private:
|
|||
Fn<void(std::shared_ptr<Data::DocumentMedia>)> callback);
|
||||
void invokeForLoaded(LoadingDocument &value);
|
||||
|
||||
void parseChatThemes(const QVector<MTPChatTheme> &list);
|
||||
void parseChatThemes(const QVector<MTPTheme> &list);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
uint64 _hash = 0;
|
||||
|
@ -132,9 +135,9 @@ private:
|
|||
std::vector<CloudTheme> _list;
|
||||
rpl::event_stream<> _updates;
|
||||
|
||||
int32 _chatThemesHash = 0;
|
||||
uint64 _chatThemesHash = 0;
|
||||
mtpRequestId _chatThemesRequestId = 0;
|
||||
std::vector<ChatTheme> _chatThemes;
|
||||
std::vector<CloudTheme> _chatThemes;
|
||||
rpl::event_stream<> _chatThemesUpdates;
|
||||
|
||||
base::Timer _reloadCurrentTimer;
|
||||
|
|
|
@ -688,7 +688,9 @@ void Histories::deleteAllMessages(
|
|||
return session().api().request(MTPmessages_DeleteHistory(
|
||||
MTP_flags(flags),
|
||||
peer->input,
|
||||
MTP_int(0)
|
||||
MTP_int(0),
|
||||
MTPint(), // min_date
|
||||
MTPint() // max_date
|
||||
)).done([=](const MTPmessages_AffectedHistory &result) {
|
||||
const auto offset = session().api().applyAffectedHistory(
|
||||
peer,
|
||||
|
|
|
@ -706,20 +706,11 @@ HistoryWidget::HistoryWidget(
|
|||
) | rpl::filter_optional(
|
||||
) | rpl::take(
|
||||
1
|
||||
) | rpl::start_with_next([=](const Data::ChatTheme &theme) {
|
||||
auto text = QStringList();
|
||||
const auto push = [&](QString label, const auto &theme) {
|
||||
using namespace Data;
|
||||
const auto &themes = _peer->owner().cloudThemes();
|
||||
const auto l = themes.prepareTestingLink(theme);
|
||||
if (!l.isEmpty()) {
|
||||
text.push_back(label + ": " + l);
|
||||
}
|
||||
};
|
||||
push("Light", theme.light);
|
||||
push("Dark", theme.dark);
|
||||
) | rpl::start_with_next([=](const Data::CloudTheme &theme) {
|
||||
const auto &themes = _peer->owner().cloudThemes();
|
||||
const auto text = themes.prepareTestingLink(theme);
|
||||
if (!text.isEmpty()) {
|
||||
_field->setText(text.join("\n\n"));
|
||||
_field->setText(text);
|
||||
}
|
||||
}, _list->lifetime());
|
||||
}
|
||||
|
|
|
@ -217,7 +217,7 @@ ChatTheme::ChatTheme() {
|
|||
|
||||
// Runs from background thread.
|
||||
ChatTheme::ChatTheme(ChatThemeDescriptor &&descriptor)
|
||||
: _id(descriptor.id)
|
||||
: _key(descriptor.key)
|
||||
, _palette(std::make_unique<style::palette>()) {
|
||||
descriptor.preparePalette(*_palette);
|
||||
setBackground(PrepareBackgroundImage(descriptor.backgroundData));
|
||||
|
@ -431,8 +431,8 @@ void ChatTheme::updateBackgroundImageFrom(ChatThemeBackground &&background) {
|
|||
}
|
||||
}
|
||||
|
||||
uint64 ChatTheme::key() const {
|
||||
return _id;
|
||||
ChatThemeKey ChatTheme::key() const {
|
||||
return _key;
|
||||
}
|
||||
|
||||
void ChatTheme::setBubblesBackground(QImage image) {
|
||||
|
|
|
@ -103,8 +103,36 @@ struct BackgroundState {
|
|||
float64 shown = 1.;
|
||||
};
|
||||
|
||||
struct ChatThemeDescriptor {
|
||||
struct ChatThemeKey {
|
||||
uint64 id = 0;
|
||||
bool dark = false;
|
||||
|
||||
explicit operator bool() const {
|
||||
return (id != 0);
|
||||
}
|
||||
};
|
||||
|
||||
inline bool operator<(ChatThemeKey a, ChatThemeKey b) {
|
||||
return (a.id < b.id) || ((a.id == b.id) && (a.dark < b.dark));
|
||||
}
|
||||
inline bool operator>(ChatThemeKey a, ChatThemeKey b) {
|
||||
return (b < a);
|
||||
}
|
||||
inline bool operator<=(ChatThemeKey a, ChatThemeKey b) {
|
||||
return !(b < a);
|
||||
}
|
||||
inline bool operator>=(ChatThemeKey a, ChatThemeKey b) {
|
||||
return !(a < b);
|
||||
}
|
||||
inline bool operator==(ChatThemeKey a, ChatThemeKey b) {
|
||||
return (a.id == b.id) && (a.dark == b.dark);
|
||||
}
|
||||
inline bool operator!=(ChatThemeKey a, ChatThemeKey b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
struct ChatThemeDescriptor {
|
||||
ChatThemeKey key;
|
||||
Fn<void(style::palette&)> preparePalette;
|
||||
ChatThemeBackgroundData backgroundData;
|
||||
ChatThemeBubblesData bubblesData;
|
||||
|
@ -120,7 +148,7 @@ public:
|
|||
|
||||
~ChatTheme();
|
||||
|
||||
[[nodiscard]] uint64 key() const;
|
||||
[[nodiscard]] ChatThemeKey key() const;
|
||||
[[nodiscard]] const style::palette *palette() const {
|
||||
return _palette.get();
|
||||
}
|
||||
|
@ -172,7 +200,7 @@ private:
|
|||
void adjust(const style::color &my, const QColor &by);
|
||||
void adjust(const style::color &my, const style::colorizer &by);
|
||||
|
||||
uint64 _id = 0;
|
||||
ChatThemeKey _key;
|
||||
std::unique_ptr<style::palette> _palette;
|
||||
ChatThemeBackground _mutableBackground;
|
||||
BackgroundState _backgroundState;
|
||||
|
|
|
@ -147,7 +147,7 @@ constexpr auto kDisableElement = "disable"_cs;
|
|||
} // namespace
|
||||
|
||||
struct ChooseThemeController::Entry {
|
||||
uint64 id = 0;
|
||||
Ui::ChatThemeKey key;
|
||||
std::shared_ptr<Ui::ChatTheme> theme;
|
||||
std::shared_ptr<Data::DocumentMedia> media;
|
||||
QImage preview;
|
||||
|
@ -263,7 +263,7 @@ void ChooseThemeController::initButtons() {
|
|||
apply->setClickedCallback([=] {
|
||||
if (const auto chosen = findChosen()) {
|
||||
if (Ui::Emoji::Find(_peer->themeEmoji()) != chosen->emoji) {
|
||||
const auto now = chosen->id ? _chosen : QString();
|
||||
const auto now = chosen->key ? _chosen : QString();
|
||||
_peer->setThemeEmoji(now);
|
||||
if (chosen->theme) {
|
||||
// Remember while changes propagate through event loop.
|
||||
|
@ -337,7 +337,7 @@ void ChooseThemeController::initList() {
|
|||
const auto chosenText = [=](const Entry *entry) {
|
||||
if (!entry) {
|
||||
return QString();
|
||||
} else if (entry->id) {
|
||||
} else if (entry->key) {
|
||||
return entry->emoji->text();
|
||||
} else {
|
||||
return kDisableElement.utf16();
|
||||
|
@ -384,7 +384,7 @@ void ChooseThemeController::initList() {
|
|||
}
|
||||
_chosen = chosen;
|
||||
entry->chosen = true;
|
||||
if (entry->theme || !entry->id) {
|
||||
if (entry->theme || !entry->key) {
|
||||
_controller->overridePeerTheme(_peer, entry->theme);
|
||||
}
|
||||
_inner->update();
|
||||
|
@ -468,7 +468,7 @@ auto ChooseThemeController::findChosen() -> Entry* {
|
|||
return nullptr;
|
||||
}
|
||||
for (auto &entry : _entries) {
|
||||
if (!entry.id && _chosen == kDisableElement.utf16()) {
|
||||
if (!entry.key && _chosen == kDisableElement.utf16()) {
|
||||
return &entry;
|
||||
} else if (_chosen == entry.emoji->text()) {
|
||||
return &entry;
|
||||
|
@ -482,7 +482,7 @@ auto ChooseThemeController::findChosen() const -> const Entry* {
|
|||
}
|
||||
|
||||
void ChooseThemeController::fill(
|
||||
const std::vector<Data::ChatTheme> &themes) {
|
||||
const std::vector<Data::CloudTheme> &themes) {
|
||||
if (themes.empty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -516,30 +516,34 @@ void ChooseThemeController::fill(
|
|||
_entries.front().preview = GenerateEmptyPreview();
|
||||
}, _cachingLifetime);
|
||||
|
||||
const auto type = dark
|
||||
? Data::CloudThemeType::Dark
|
||||
: Data::CloudThemeType::Light;
|
||||
|
||||
x += single.width() + skip;
|
||||
for (const auto &theme : themes) {
|
||||
const auto emoji = Ui::Emoji::Find(theme.emoticon);
|
||||
if (!emoji) {
|
||||
if (!emoji || !theme.settings.contains(type)) {
|
||||
continue;
|
||||
}
|
||||
const auto &used = dark ? theme.dark : theme.light;
|
||||
const auto id = used.id;
|
||||
const auto key = ChatThemeKey{ theme.id, dark };
|
||||
const auto isChosen = (_chosen == emoji->text());
|
||||
_entries.push_back({
|
||||
.id = id,
|
||||
.key = key,
|
||||
.emoji = emoji,
|
||||
.geometry = QRect(QPoint(x, skip), single),
|
||||
.chosen = isChosen,
|
||||
});
|
||||
_controller->cachedChatThemeValue(
|
||||
used
|
||||
theme,
|
||||
type
|
||||
) | rpl::filter([=](const std::shared_ptr<ChatTheme> &data) {
|
||||
return data && (data->key() == id);
|
||||
return data && (data->key() == key);
|
||||
}) | rpl::take(
|
||||
1
|
||||
) | rpl::start_with_next([=](std::shared_ptr<ChatTheme> &&data) {
|
||||
const auto id = data->key();
|
||||
const auto i = ranges::find(_entries, id, &Entry::id);
|
||||
const auto key = data->key();
|
||||
const auto i = ranges::find(_entries, key, &Entry::key);
|
||||
if (i == end(_entries)) {
|
||||
return;
|
||||
}
|
||||
|
@ -560,15 +564,15 @@ void ChooseThemeController::fill(
|
|||
) | rpl::filter([=] {
|
||||
const auto i = ranges::find(
|
||||
_entries,
|
||||
id,
|
||||
&Entry::id);
|
||||
key,
|
||||
&Entry::key);
|
||||
return (i == end(_entries))
|
||||
|| !i->theme->background().prepared.isNull();
|
||||
}) | rpl::take(1) | rpl::start_with_next([=] {
|
||||
const auto i = ranges::find(
|
||||
_entries,
|
||||
id,
|
||||
&Entry::id);
|
||||
key,
|
||||
&Entry::key);
|
||||
if (i == end(_entries)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ class SessionController;
|
|||
} // namespace Window
|
||||
|
||||
namespace Data {
|
||||
struct ChatTheme;
|
||||
struct CloudTheme;
|
||||
} // namespace Data
|
||||
|
||||
namespace Ui {
|
||||
|
@ -48,7 +48,7 @@ private:
|
|||
void init(rpl::producer<QSize> outer);
|
||||
void initButtons();
|
||||
void initList();
|
||||
void fill(const std::vector<Data::ChatTheme> &themes);
|
||||
void fill(const std::vector<Data::CloudTheme> &themes);
|
||||
void close();
|
||||
|
||||
void clearCurrentBackgroundState();
|
||||
|
|
|
@ -37,27 +37,28 @@ namespace {
|
|||
|
||||
[[nodiscard]] auto MaybeChatThemeDataValueFromPeer(
|
||||
not_null<PeerData*> peer)
|
||||
-> rpl::producer<std::optional<Data::ChatTheme>> {
|
||||
-> rpl::producer<std::optional<Data::CloudTheme>> {
|
||||
return PeerThemeEmojiValue(
|
||||
peer
|
||||
) | rpl::map([=](const QString &emoji)
|
||||
-> rpl::producer<std::optional<Data::ChatTheme>> {
|
||||
-> rpl::producer<std::optional<Data::CloudTheme>> {
|
||||
return peer->owner().cloudThemes().themeForEmojiValue(emoji);
|
||||
}) | rpl::flatten_latest();
|
||||
}
|
||||
|
||||
struct ResolvedTheme {
|
||||
std::optional<Data::CloudTheme> theme;
|
||||
bool dark = false;
|
||||
};
|
||||
|
||||
[[nodiscard]] auto MaybeCloudThemeValueFromPeer(
|
||||
not_null<PeerData*> peer)
|
||||
-> rpl::producer<std::optional<Data::CloudTheme>> {
|
||||
-> rpl::producer<ResolvedTheme> {
|
||||
return rpl::combine(
|
||||
MaybeChatThemeDataValueFromPeer(peer),
|
||||
Theme::IsThemeDarkValue() | rpl::distinct_until_changed()
|
||||
) | rpl::map([](std::optional<Data::ChatTheme> theme, bool night) {
|
||||
return !theme
|
||||
? std::nullopt
|
||||
: night
|
||||
? std::make_optional(std::move(theme->dark))
|
||||
: std::make_optional(std::move(theme->light));
|
||||
) | rpl::map([](std::optional<Data::CloudTheme> theme, bool night) {
|
||||
return ResolvedTheme{ std::move(theme), night };
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -296,12 +297,15 @@ auto ChatThemeValueFromPeer(
|
|||
-> rpl::producer<std::shared_ptr<Ui::ChatTheme>> {
|
||||
auto cloud = MaybeCloudThemeValueFromPeer(
|
||||
peer
|
||||
) | rpl::map([=](std::optional<Data::CloudTheme> theme)
|
||||
) | rpl::map([=](ResolvedTheme resolved)
|
||||
-> rpl::producer<std::shared_ptr<Ui::ChatTheme>> {
|
||||
if (!theme) {
|
||||
return rpl::single(controller->defaultChatTheme());
|
||||
}
|
||||
return controller->cachedChatThemeValue(*theme);
|
||||
return resolved.theme
|
||||
? controller->cachedChatThemeValue(
|
||||
*resolved.theme,
|
||||
(resolved.dark
|
||||
? Data::CloudThemeType::Dark
|
||||
: Data::CloudThemeType::Light))
|
||||
: rpl::single(controller->defaultChatTheme());
|
||||
}) | rpl::flatten_latest(
|
||||
) | rpl::distinct_until_changed();
|
||||
|
||||
|
|
|
@ -517,7 +517,7 @@ Fn<void()> SavePreparedTheme(
|
|||
MTP_string(fields.slug),
|
||||
MTP_string(fields.title),
|
||||
document->mtpInput(),
|
||||
MTPInputThemeSettings()
|
||||
MTPVector<MTPInputThemeSettings>()
|
||||
)).done([=](const MTPTheme &result) {
|
||||
finish(result);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
|
@ -540,7 +540,7 @@ Fn<void()> SavePreparedTheme(
|
|||
MTP_string(fields.slug),
|
||||
MTP_string(fields.title),
|
||||
document->mtpInput(),
|
||||
MTPInputThemeSettings()
|
||||
MTPVector<MTPInputThemeSettings>()
|
||||
)).done([=](const MTPTheme &result) {
|
||||
finish(result);
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
|
@ -607,7 +607,7 @@ Fn<void()> SavePreparedTheme(
|
|||
MTP_string(fields.slug),
|
||||
MTP_string(fields.title),
|
||||
MTP_inputDocumentEmpty(),
|
||||
MTPInputThemeSettings()
|
||||
MTPVector<MTPInputThemeSettings>()
|
||||
)).done([=](const MTPTheme &result) {
|
||||
save();
|
||||
}).fail([=](const MTP::Error &error) {
|
||||
|
|
|
@ -109,10 +109,16 @@ constexpr auto kNightBaseFile = ":/gui/night-custom-base.tdesktop-theme"_cs;
|
|||
}
|
||||
|
||||
[[nodiscard]] Ui::ChatThemeBubblesData PrepareBubblesData(
|
||||
const Data::CloudTheme &theme) {
|
||||
const Data::CloudTheme &theme,
|
||||
Data::CloudThemeType type) {
|
||||
const auto i = theme.settings.find(type);
|
||||
return {
|
||||
.colors = theme.outgoingMessagesColors,
|
||||
.accent = theme.outgoingAccentColor,
|
||||
.colors = (i != end(theme.settings)
|
||||
? i->second.outgoingMessagesColors
|
||||
: std::vector<QColor>()),
|
||||
.accent = (i != end(theme.settings)
|
||||
? i->second.outgoingAccentColor
|
||||
: std::optional<QColor>()),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1423,10 +1429,18 @@ void SessionController::openDocument(
|
|||
}
|
||||
|
||||
auto SessionController::cachedChatThemeValue(
|
||||
const Data::CloudTheme &data)
|
||||
const Data::CloudTheme &data,
|
||||
Data::CloudThemeType type)
|
||||
-> rpl::producer<std::shared_ptr<Ui::ChatTheme>> {
|
||||
const auto key = data.id;
|
||||
if (!key || !data.paper || data.paper->backgroundColors().empty()) {
|
||||
const auto key = Ui::ChatThemeKey{
|
||||
data.id,
|
||||
(type == Data::CloudThemeType::Dark),
|
||||
};
|
||||
const auto settings = data.settings.find(type);
|
||||
if (!key
|
||||
|| (settings == end(data.settings))
|
||||
|| !settings->second.paper
|
||||
|| settings->second.paper->backgroundColors().empty()) {
|
||||
return rpl::single(_defaultChatTheme);
|
||||
}
|
||||
const auto i = _customChatThemes.find(key);
|
||||
|
@ -1437,7 +1451,7 @@ auto SessionController::cachedChatThemeValue(
|
|||
}
|
||||
}
|
||||
if (i == end(_customChatThemes) || !i->second.caching) {
|
||||
cacheChatTheme(data);
|
||||
cacheChatTheme(data, type);
|
||||
}
|
||||
const auto limit = Data::CloudThemes::TestingColors() ? (1 << 20) : 1;
|
||||
using namespace rpl::mappers;
|
||||
|
@ -1510,20 +1524,26 @@ void SessionController::pushDefaultChatBackground() {
|
|||
});
|
||||
}
|
||||
|
||||
void SessionController::cacheChatTheme(const Data::CloudTheme &data) {
|
||||
void SessionController::cacheChatTheme(
|
||||
const Data::CloudTheme &data,
|
||||
Data::CloudThemeType type) {
|
||||
Expects(data.id != 0);
|
||||
Expects(data.paper.has_value());
|
||||
Expects(!data.paper->backgroundColors().empty());
|
||||
|
||||
const auto key = data.id;
|
||||
const auto document = data.paper->document();
|
||||
const auto dark = (type == Data::CloudThemeType::Dark);
|
||||
const auto key = Ui::ChatThemeKey{ data.id, dark };
|
||||
const auto i = data.settings.find(type);
|
||||
Assert(i != end(data.settings));
|
||||
const auto &paper = i->second.paper;
|
||||
Assert(paper.has_value());
|
||||
Assert(!paper->backgroundColors().empty());
|
||||
const auto document = paper->document();
|
||||
const auto media = document ? document->createMediaView() : nullptr;
|
||||
data.paper->loadDocument();
|
||||
paper->loadDocument();
|
||||
auto &theme = [&]() -> CachedTheme& {
|
||||
const auto i = _customChatThemes.find(key);
|
||||
if (i != end(_customChatThemes)) {
|
||||
i->second.media = media;
|
||||
i->second.paper = *data.paper;
|
||||
i->second.paper = *paper;
|
||||
i->second.caching = true;
|
||||
return i->second;
|
||||
}
|
||||
|
@ -1531,18 +1551,18 @@ void SessionController::cacheChatTheme(const Data::CloudTheme &data) {
|
|||
key,
|
||||
CachedTheme{
|
||||
.media = media,
|
||||
.paper = *data.paper,
|
||||
.paper = *paper,
|
||||
.caching = true,
|
||||
}).first->second;
|
||||
}();
|
||||
auto descriptor = Ui::ChatThemeDescriptor{
|
||||
.id = key,
|
||||
.key = key,
|
||||
.preparePalette = PreparePaletteCallback(
|
||||
data.basedOnDark,
|
||||
data.accentColor),
|
||||
dark,
|
||||
i->second.accentColor),
|
||||
.backgroundData = backgroundData(theme),
|
||||
.bubblesData = PrepareBubblesData(data),
|
||||
.basedOnDark = data.basedOnDark,
|
||||
.bubblesData = PrepareBubblesData(data, type),
|
||||
.basedOnDark = dark,
|
||||
};
|
||||
crl::async([
|
||||
this,
|
||||
|
|
|
@ -48,6 +48,7 @@ class LayerWidget;
|
|||
enum class ReportReason;
|
||||
class ChatStyle;
|
||||
class ChatTheme;
|
||||
struct ChatThemeKey;
|
||||
struct ChatPaintContext;
|
||||
struct ChatThemeBackground;
|
||||
struct ChatThemeBackgroundData;
|
||||
|
@ -55,6 +56,7 @@ struct ChatThemeBackgroundData;
|
|||
|
||||
namespace Data {
|
||||
struct CloudTheme;
|
||||
enum class CloudThemeType;
|
||||
} // namespace Data
|
||||
|
||||
namespace Window {
|
||||
|
@ -419,7 +421,8 @@ public:
|
|||
return _defaultChatTheme;
|
||||
}
|
||||
[[nodiscard]] auto cachedChatThemeValue(
|
||||
const Data::CloudTheme &data)
|
||||
const Data::CloudTheme &data,
|
||||
Data::CloudThemeType type)
|
||||
-> rpl::producer<std::shared_ptr<Ui::ChatTheme>>;
|
||||
void setChatStyleTheme(const std::shared_ptr<Ui::ChatTheme> &theme);
|
||||
void clearCachedChatThemes();
|
||||
|
@ -479,7 +482,9 @@ private:
|
|||
void checkInvitePeek();
|
||||
|
||||
void pushDefaultChatBackground();
|
||||
void cacheChatTheme(const Data::CloudTheme &data);
|
||||
void cacheChatTheme(
|
||||
const Data::CloudTheme &data,
|
||||
Data::CloudThemeType type);
|
||||
void cacheChatThemeDone(std::shared_ptr<Ui::ChatTheme> result);
|
||||
void updateCustomThemeBackground(CachedTheme &theme);
|
||||
[[nodiscard]] Ui::ChatThemeBackgroundData backgroundData(
|
||||
|
@ -515,7 +520,7 @@ private:
|
|||
rpl::event_stream<> _filtersMenuChanged;
|
||||
|
||||
std::shared_ptr<Ui::ChatTheme> _defaultChatTheme;
|
||||
base::flat_map<uint64, CachedTheme> _customChatThemes;
|
||||
base::flat_map<Ui::ChatThemeKey, CachedTheme> _customChatThemes;
|
||||
rpl::event_stream<std::shared_ptr<Ui::ChatTheme>> _cachedThemesStream;
|
||||
const std::unique_ptr<Ui::ChatStyle> _chatStyle;
|
||||
std::weak_ptr<Ui::ChatTheme> _chatStyleTheme;
|
||||
|
|
Loading…
Add table
Reference in a new issue