feat: save message shot config

This commit is contained in:
AlexeyZavar
2026-02-17 03:20:26 +03:00
parent fede50ef48
commit 1a29b6ac6e
13 changed files with 831 additions and 179 deletions
+2
View File
@@ -210,6 +210,8 @@ set(ayugram_files
ayu/features/streamer_mode/streamer_mode.h ayu/features/streamer_mode/streamer_mode.h
ayu/features/message_shot/message_shot.cpp ayu/features/message_shot/message_shot.cpp
ayu/features/message_shot/message_shot.h ayu/features/message_shot/message_shot.h
ayu/features/message_shot/message_shot_theme_state.cpp
ayu/features/message_shot/message_shot_theme_state.h
ayu/features/forward/ayu_forward.cpp ayu/features/forward/ayu_forward.cpp
ayu/features/forward/ayu_forward.h ayu/features/forward/ayu_forward.h
ayu/features/forward/ayu_sync.cpp ayu/features/forward/ayu_sync.cpp
-4
View File
@@ -13,10 +13,6 @@
#include "ayu/data/ayu_database.h" #include "ayu/data/ayu_database.h"
#include "features/translator/ayu_translator.h" #include "features/translator/ayu_translator.h"
#include "lang/lang_instance.h" #include "lang/lang_instance.h"
#include "main/main_account.h"
#include "main/main_domain.h"
#include "main/main_session.h"
#include "ui/layers/generic_box.h"
#include "utils/rc_manager.h" #include "utils/rc_manager.h"
namespace AyuInfra { namespace AyuInfra {
+127 -1
View File
@@ -193,6 +193,119 @@ void from_json(const nlohmann::json &j, GhostModeAccountSettings &s) {
s._sendOfflinePacketAfterOnlineLocked = j.value("sendOfflinePacketAfterOnlineLocked", false); s._sendOfflinePacketAfterOnlineLocked = j.value("sendOfflinePacketAfterOnlineLocked", false);
} }
void MessageShotSettings::setShowBackground(bool val) {
if (_showBackground.current() == val) return;
_showBackground = val;
AyuSettings::save();
}
void MessageShotSettings::setShowDate(bool val) {
if (_showDate.current() == val) return;
_showDate = val;
AyuSettings::save();
}
void MessageShotSettings::setShowReactions(bool val) {
if (_showReactions.current() == val) return;
_showReactions = val;
AyuSettings::save();
}
void MessageShotSettings::setShowColorfulReplies(bool val) {
if (_showColorfulReplies.current() == val) return;
_showColorfulReplies = val;
AyuSettings::save();
}
bool MessageShotSettings::isCloudThemeEmpty() const {
return !_cloudThemeId.current()
&& !_cloudThemeAccessHash.current()
&& !_cloudThemeDocumentId.current()
&& _cloudThemeTitle.current().isEmpty();
}
void MessageShotSettings::clearCloudThemeData() {
_cloudThemeId = uint64(0);
_cloudThemeAccessHash = uint64(0);
_cloudThemeDocumentId = uint64(0);
_cloudThemeTitle = QString();
_cloudThemeAccountId = uint64(0);
}
void MessageShotSettings::setEmbeddedTheme(int type, uint32 accentColor) {
if (_embeddedThemeType.current() == type
&& _embeddedThemeAccentColor.current() == accentColor
&& isCloudThemeEmpty()) {
return;
}
_embeddedThemeType = type;
_embeddedThemeAccentColor = accentColor;
clearCloudThemeData();
AyuSettings::save();
}
void MessageShotSettings::setCloudTheme(uint64 accountId, uint64 id, uint64 accessHash, uint64 documentId, const QString &title) {
if (_embeddedThemeType.current() == -1
&& _embeddedThemeAccentColor.current() == 0
&& _cloudThemeAccountId.current() == accountId
&& _cloudThemeId.current() == id
&& _cloudThemeAccessHash.current() == accessHash
&& _cloudThemeDocumentId.current() == documentId
&& _cloudThemeTitle.current() == title) {
return;
}
_embeddedThemeType = -1;
_embeddedThemeAccentColor = uint32(0);
_cloudThemeAccountId = accountId;
_cloudThemeId = id;
_cloudThemeAccessHash = accessHash;
_cloudThemeDocumentId = documentId;
_cloudThemeTitle = title;
AyuSettings::save();
}
void MessageShotSettings::clearTheme() {
if (_embeddedThemeType.current() == -1
&& _embeddedThemeAccentColor.current() == 0
&& isCloudThemeEmpty()) {
return;
}
_embeddedThemeType = -1;
_embeddedThemeAccentColor = uint32(0);
clearCloudThemeData();
AyuSettings::save();
}
void to_json(nlohmann::json &j, const MessageShotSettings &s) {
j = nlohmann::json{
{"showBackground", s._showBackground.current()},
{"showDate", s._showDate.current()},
{"showReactions", s._showReactions.current()},
{"showColorfulReplies", s._showColorfulReplies.current()},
{"embeddedThemeType", s._embeddedThemeType.current()},
{"embeddedThemeAccentColor", s._embeddedThemeAccentColor.current()},
{"cloudThemeId", s._cloudThemeId.current()},
{"cloudThemeAccessHash", s._cloudThemeAccessHash.current()},
{"cloudThemeDocumentId", s._cloudThemeDocumentId.current()},
{"cloudThemeTitle", s._cloudThemeTitle.current()},
{"cloudThemeAccountId", s._cloudThemeAccountId.current()},
};
}
void from_json(const nlohmann::json &j, MessageShotSettings &s) {
s._showBackground = j.value("showBackground", true);
s._showDate = j.value("showDate", false);
s._showReactions = j.value("showReactions", false);
s._showColorfulReplies = j.value("showColorfulReplies", false);
s._embeddedThemeType = j.value("embeddedThemeType", j.value("themeType", -1));
s._embeddedThemeAccentColor = j.value("embeddedThemeAccentColor", j.value("themeAccentColor", uint32(0)));
s._cloudThemeId = j.value("cloudThemeId", uint64(0));
s._cloudThemeAccessHash = j.value("cloudThemeAccessHash", uint64(0));
s._cloudThemeDocumentId = j.value("cloudThemeDocumentId", uint64(0));
s._cloudThemeTitle = j.value("cloudThemeTitle", QString());
s._cloudThemeAccountId = j.value("cloudThemeAccountId", uint64(0));
}
AyuSettings::AyuSettings() AyuSettings::AyuSettings()
: _appIcon(AyuAssets::DEFAULT_ICON) : _appIcon(AyuAssets::DEFAULT_ICON)
, _editedMark(Core::IsAppLaunched() ? tr::lng_edited(tr::now) : QString("edited")) { , _editedMark(Core::IsAppLaunched() ? tr::lng_edited(tr::now) : QString("edited")) {
@@ -356,6 +469,14 @@ void AyuSettings::validate() {
validateRange(_wideMultiplier, 0.5, 3.0, defaults._wideMultiplier); validateRange(_wideMultiplier, 0.5, 3.0, defaults._wideMultiplier);
validateRange(_recentStickersCount, 1, 200, defaults._recentStickersCount); validateRange(_recentStickersCount, 1, 200, defaults._recentStickersCount);
const auto embeddedType = _messageShotSettings._embeddedThemeType.current();
auto embeddedTypeValid = (embeddedType == -1) || (embeddedType >= 0 && embeddedType <= 3); // from Window::Theme::EmbeddedType::DayBlue to Window::Theme::EmbeddedType::NightGreen
if (!embeddedTypeValid) {
_messageShotSettings._embeddedThemeType = defaults._messageShotSettings._embeddedThemeType.current();
_messageShotSettings._embeddedThemeAccentColor = defaults._messageShotSettings._embeddedThemeAccentColor.current();
modified = true;
}
if (modified) { if (modified) {
save(); save();
} }
@@ -904,7 +1025,8 @@ void to_json(nlohmann::json &j, const AyuSettings &s) {
{"translationProvider", s._translationProvider.current()}, {"translationProvider", s._translationProvider.current()},
{"adaptiveCoverColor", s._adaptiveCoverColor.current()}, {"adaptiveCoverColor", s._adaptiveCoverColor.current()},
{"improveLinkPreviews", s._improveLinkPreviews.current()}, {"improveLinkPreviews", s._improveLinkPreviews.current()},
{"crashReporting", s._crashReporting.current()} {"crashReporting", s._crashReporting.current()},
{"messageShotSettings", s._messageShotSettings}
}; };
} }
@@ -997,4 +1119,8 @@ void from_json(const nlohmann::json &j, AyuSettings &s) {
s._adaptiveCoverColor = j.value("adaptiveCoverColor", defaults._adaptiveCoverColor.current()); s._adaptiveCoverColor = j.value("adaptiveCoverColor", defaults._adaptiveCoverColor.current());
s._improveLinkPreviews = j.value("improveLinkPreviews", defaults._improveLinkPreviews.current()); s._improveLinkPreviews = j.value("improveLinkPreviews", defaults._improveLinkPreviews.current());
s._crashReporting = j.value("crashReporting", defaults._crashReporting.current()); s._crashReporting = j.value("crashReporting", defaults._crashReporting.current());
if (j.contains("messageShotSettings") && j["messageShotSettings"].is_object()) {
j["messageShotSettings"].get_to(s._messageShotSettings);
}
} }
+55
View File
@@ -135,6 +135,56 @@ private:
void to_json(nlohmann::json &j, const GhostModeAccountSettings &s); void to_json(nlohmann::json &j, const GhostModeAccountSettings &s);
void from_json(const nlohmann::json &j, GhostModeAccountSettings &s); void from_json(const nlohmann::json &j, GhostModeAccountSettings &s);
class MessageShotSettings {
public:
[[nodiscard]] bool showBackground() const { return _showBackground.current(); }
[[nodiscard]] bool showDate() const { return _showDate.current(); }
[[nodiscard]] bool showReactions() const { return _showReactions.current(); }
[[nodiscard]] bool showColorfulReplies() const { return _showColorfulReplies.current(); }
[[nodiscard]] int embeddedThemeType() const { return _embeddedThemeType.current(); }
[[nodiscard]] uint32 embeddedThemeAccentColor() const { return _embeddedThemeAccentColor.current(); }
[[nodiscard]] uint64 cloudThemeId() const { return _cloudThemeId.current(); }
[[nodiscard]] uint64 cloudThemeAccessHash() const { return _cloudThemeAccessHash.current(); }
[[nodiscard]] uint64 cloudThemeDocumentId() const { return _cloudThemeDocumentId.current(); }
[[nodiscard]] const QString &cloudThemeTitle() const { return _cloudThemeTitle.current(); }
[[nodiscard]] uint64 cloudThemeAccountId() const { return _cloudThemeAccountId.current(); }
void setShowBackground(bool val);
void setShowDate(bool val);
void setShowReactions(bool val);
void setShowColorfulReplies(bool val);
void setEmbeddedTheme(int type, uint32 accentColor = 0);
void setCloudTheme(uint64 accountId, uint64 id, uint64 accessHash, uint64 documentId, const QString &title);
void clearTheme();
friend void to_json(nlohmann::json &j, const MessageShotSettings &s);
friend void from_json(const nlohmann::json &j, MessageShotSettings &s);
private:
friend class AyuSettings;
[[nodiscard]] bool isCloudThemeEmpty() const;
void clearCloudThemeData();
rpl::variable<bool> _showBackground = true;
rpl::variable<bool> _showDate = false;
rpl::variable<bool> _showReactions = false;
rpl::variable<bool> _showColorfulReplies = false;
rpl::variable<int> _embeddedThemeType = -1;
rpl::variable<uint32> _embeddedThemeAccentColor = 0;
rpl::variable<uint64> _cloudThemeId = 0;
rpl::variable<uint64> _cloudThemeAccessHash = 0;
rpl::variable<uint64> _cloudThemeDocumentId = 0;
rpl::variable<QString> _cloudThemeTitle;
rpl::variable<uint64> _cloudThemeAccountId = 0;
};
void to_json(nlohmann::json &j, const MessageShotSettings &s);
void from_json(const nlohmann::json &j, MessageShotSettings &s);
class AyuSettings { class AyuSettings {
public: public:
AyuSettings(const AyuSettings &) = delete; AyuSettings(const AyuSettings &) = delete;
@@ -151,6 +201,9 @@ public:
[[nodiscard]] static GhostModeAccountSettings &ghost(not_null<Main::Session*> session); [[nodiscard]] static GhostModeAccountSettings &ghost(not_null<Main::Session*> session);
[[nodiscard]] static GhostModeAccountSettings &ghost(uint64 userId); [[nodiscard]] static GhostModeAccountSettings &ghost(uint64 userId);
[[nodiscard]] static GhostModeAccountSettings &ghost(); [[nodiscard]] static GhostModeAccountSettings &ghost();
[[nodiscard]] MessageShotSettings &messageShotSettings() { return _messageShotSettings; }
[[nodiscard]] const MessageShotSettings &messageShotSettings() const { return _messageShotSettings; }
[[nodiscard]] bool useGlobalGhostMode() const { return _useGlobalGhostMode.current(); } [[nodiscard]] bool useGlobalGhostMode() const { return _useGlobalGhostMode.current(); }
void setUseGlobalGhostMode(bool val); void setUseGlobalGhostMode(bool val);
@@ -477,6 +530,8 @@ private:
rpl::variable<bool> _useGlobalGhostMode = true; rpl::variable<bool> _useGlobalGhostMode = true;
std::map<uint64, std::unique_ptr<GhostModeAccountSettings>> _ghostAccounts; std::map<uint64, std::unique_ptr<GhostModeAccountSettings>> _ghostAccounts;
MessageShotSettings _messageShotSettings;
}; };
void to_json(nlohmann::json &j, const AyuSettings &s); void to_json(nlohmann::json &j, const AyuSettings &s);
@@ -10,10 +10,10 @@
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "qguiapplication.h" #include "qguiapplication.h"
#include "ayu/ayu_settings.h"
#include "ayu/ui/boxes/message_shot_box.h" #include "ayu/ui/boxes/message_shot_box.h"
#include "ayu/utils/telegram_helpers.h" #include "ayu/utils/telegram_helpers.h"
#include "boxes/abstract_box.h" #include "boxes/abstract_box.h"
#include "data/data_cloud_themes.h"
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_document_media.h" #include "data/data_document_media.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
@@ -39,22 +39,11 @@
namespace AyuFeatures::MessageShot { namespace AyuFeatures::MessageShot {
ShotConfig *config; ShotConfig *config = nullptr;
Window::Theme::EmbeddedType defaultSelected = Window::Theme::EmbeddedType(-1);
std::optional<QColor> defaultSelectedColor;
std::optional<Data::CloudTheme> customSelected;
rpl::event_stream<> resetDefaultSelectedStream;
rpl::event_stream<> resetCustomSelectedStream;
bool takingShot = false; bool takingShot = false;
bool choosingTheme = false; bool choosingTheme = false;
rpl::event_stream<Data::CloudTheme> themeChosenStream;
rpl::event_stream<style::palette> paletteChosenStream;
void setShotConfig(ShotConfig &config) { void setShotConfig(ShotConfig &config) {
MessageShot::config = &config; MessageShot::config = &config;
} }
@@ -67,62 +56,15 @@ ShotConfig getShotConfig() {
return *config; return *config;
} }
void setDefaultSelected(const Window::Theme::EmbeddedType type) {
resetCustomSelected();
defaultSelected = type;
}
Window::Theme::EmbeddedType getSelectedFromDefault() {
return defaultSelected;
}
void setDefaultSelectedColor(const QColor color) {
resetCustomSelected();
defaultSelectedColor = color;
}
std::optional<QColor> getSelectedColorFromDefault() {
return defaultSelectedColor;
}
void setCustomSelected(const Data::CloudTheme theme) {
resetDefaultSelected();
customSelected = theme;
}
std::optional<Data::CloudTheme> getSelectedFromCustom() {
return customSelected;
}
void resetDefaultSelected() {
defaultSelected = Window::Theme::EmbeddedType(-1);
resetDefaultSelectedStream.fire({});
}
void resetCustomSelected() {
customSelected = std::nullopt;
resetCustomSelectedStream.fire({});
}
rpl::producer<> resetDefaultSelectedEvents() {
return resetDefaultSelectedStream.events();
}
rpl::producer<> resetCustomSelectedEvents() {
return resetCustomSelectedStream.events();
}
bool ignoreRender(RenderPart part) { bool ignoreRender(RenderPart part) {
if (!config) { if (!config) {
return false; return false;
} }
const auto ignoreDate = !config->showDate; const auto &s = AyuSettings::getInstance().messageShotSettings();
const auto ignoreReactions = !config->showReactions; return isTakingShot()
&& ((part == RenderPart::Date && !s.showDate())
return isTakingShot() && || (part == RenderPart::Reactions && !s.showReactions()));
((part == RenderPart::Date && ignoreDate) ||
(part == RenderPart::Reactions && ignoreReactions));
} }
bool isTakingShot() { bool isTakingShot() {
@@ -138,22 +80,6 @@ bool isChoosingTheme() {
return choosingTheme; return choosingTheme;
} }
rpl::producer<Data::CloudTheme> themeChosen() {
return themeChosenStream.events();
}
void setTheme(Data::CloudTheme theme) {
themeChosenStream.fire(std::move(theme));
}
void setPalette(style::palette &palette) {
paletteChosenStream.fire(std::move(palette));
}
rpl::producer<style::palette> paletteChosen() {
return paletteChosenStream.events();
}
class MessageShotDelegate final : public HistoryView::DefaultElementDelegate class MessageShotDelegate final : public HistoryView::DefaultElementDelegate
{ {
public: public:
@@ -375,7 +301,7 @@ void Make(not_null<QWidget*> box, const ShotConfig &config, const Fn<void(QImage
} }
} }
const auto showBackground = config.showBackground; const auto showBackground = AyuSettings::getInstance().messageShotSettings().showBackground();
auto render = [=, messages = std::move(messages), delegate = std::move(delegate)](bool final) auto render = [=, messages = std::move(messages), delegate = std::move(delegate)](bool final)
{ {
takingShot = true; takingShot = true;
@@ -512,28 +438,38 @@ void Make(not_null<QWidget*> box, const ShotConfig &config, const Fn<void(QImage
} }
} }
void Wrapper(not_null<HistoryView::ListWidget*> widget, Fn<void()> clearSelected) { namespace {
const auto items = widget->getSelectedIds();
if (items.empty()) {
return;
}
const auto session = &widget->session(); // 🥀🥀🥀
const auto controller = widget->session().tryResolveWindow();
if (!controller) {
return;
}
const auto messages = ranges::views::all(items) std::shared_ptr<Ui::ChatStyle> BuildShotChatStyle(
not_null<Window::SessionController*> controller) {
const auto &shot = AyuSettings::getInstance().messageShotSettings();
const auto hasSavedTheme = shot.embeddedThemeType() != -1
|| shot.cloudThemeId() != 0;
const auto persistedPalette = getPersistedPalette();
if (hasSavedTheme && persistedPalette) {
return std::make_shared<Ui::ChatStyle>(persistedPalette.get());
}
return std::make_shared<Ui::ChatStyle>(controller->chatStyle());
}
template <typename ResolveMessage>
void ShowMessageShotBox(
ResolveMessage resolveMessage,
not_null<Window::SessionController*> controller,
const MessageIdsList &ids,
Fn<void()> clearSelected) {
const auto messages = ranges::views::all(ids)
| ranges::views::transform([=](const auto item) | ranges::views::transform([=](const auto item)
{ {
return gsl::not_null(session->data().message(item)); return resolveMessage(item);
}) })
| ranges::to_vector; | ranges::to_vector;
const AyuFeatures::MessageShot::ShotConfig config = { const AyuFeatures::MessageShot::ShotConfig config = {
controller, controller,
std::make_shared<Ui::ChatStyle>(controller->chatStyle()), BuildShotChatStyle(controller),
messages, messages,
}; };
auto box = Box<MessageShotBox>(config); auto box = Box<MessageShotBox>(config);
@@ -545,4 +481,43 @@ void Wrapper(not_null<HistoryView::ListWidget*> widget, Fn<void()> clearSelected
Ui::show(std::move(box)); Ui::show(std::move(box));
} }
template <typename Widget, typename GetIds>
void WrapperImpl(
not_null<Widget*> widget,
GetIds getIds,
Fn<void()> clearSelected) {
const auto items = getIds(widget);
if (items.empty()) {
return;
}
const auto session = &widget->session();
const auto controller = widget->session().tryResolveWindow();
if (!controller) {
return;
}
ShowMessageShotBox(
[=](const auto item) { return gsl::not_null(session->data().message(item)); },
controller,
items,
std::move(clearSelected));
}
}
void Wrapper(not_null<HistoryView::ListWidget*> widget, Fn<void()> clearSelected) {
WrapperImpl(
widget,
[](const auto widget) { return widget->getSelectedIds(); },
std::move(clearSelected));
}
void Wrapper(not_null<HistoryInner*> widget, Fn<void()> clearSelected) {
WrapperImpl(
widget,
[](const auto widget) { return widget->getSelectedItems(); },
std::move(clearSelected));
}
} }
@@ -6,10 +6,12 @@
// Copyright @Radolyn, 2025 // Copyright @Radolyn, 2025
#pragma once #pragma once
#include "ayu/features/message_shot/message_shot_theme_state.h"
#include "history/view/history_view_list_widget.h" #include "history/view/history_view_list_widget.h"
#include "ui/chat/chat_style.h" #include "ui/chat/chat_style.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "window/themes/window_themes_embedded.h"
class HistoryInner;
namespace AyuFeatures::MessageShot { namespace AyuFeatures::MessageShot {
@@ -18,10 +20,6 @@ struct ShotConfig
not_null<Window::SessionController*> controller; not_null<Window::SessionController*> controller;
std::shared_ptr<Ui::ChatStyle> st; std::shared_ptr<Ui::ChatStyle> st;
std::vector<not_null<HistoryItem*>> messages; std::vector<not_null<HistoryItem*>> messages;
bool showBackground = true;
bool showDate;
bool showReactions;
}; };
enum RenderPart enum RenderPart
@@ -34,41 +32,18 @@ void setShotConfig(ShotConfig &config);
void resetShotConfig(); void resetShotConfig();
ShotConfig getShotConfig(); ShotConfig getShotConfig();
// for default themes
void setDefaultSelected(Window::Theme::EmbeddedType type);
Window::Theme::EmbeddedType getSelectedFromDefault();
void setDefaultSelectedColor(QColor color);
std::optional<QColor> getSelectedColorFromDefault();
// for custom themes
void setCustomSelected(Data::CloudTheme theme);
std::optional<Data::CloudTheme> getSelectedFromCustom();
// resets
void resetDefaultSelected();
void resetCustomSelected();
rpl::producer<> resetDefaultSelectedEvents();
rpl::producer<> resetCustomSelectedEvents();
bool ignoreRender(RenderPart part); bool ignoreRender(RenderPart part);
bool isTakingShot(); bool isTakingShot();
bool isChoosingTheme(); bool isChoosingTheme();
bool setChoosingTheme(bool val); bool setChoosingTheme(bool val);
void setTheme(Data::CloudTheme theme);
rpl::producer<Data::CloudTheme> themeChosen();
void setPalette(style::palette &palette);
rpl::producer<style::palette> paletteChosen();
// util // util
QColor makeDefaultBackgroundColor(); QColor makeDefaultBackgroundColor();
void Make(not_null<QWidget*> box, const ShotConfig &config, const Fn<void(QImage&,bool)>& callback); void Make(not_null<QWidget*> box, const ShotConfig &config, const Fn<void(QImage&,bool)>& callback);
void Wrapper(not_null<HistoryView::ListWidget*> widget, Fn<void()> clearSelected); void Wrapper(not_null<HistoryView::ListWidget*> widget, Fn<void()> clearSelected);
void Wrapper(not_null<HistoryInner*> widget, Fn<void()> clearSelected);
} }
@@ -0,0 +1,408 @@
// This is the source code of AyuGram for Desktop.
//
// We do not and cannot prevent the use of our code,
// but be respectful and credit the original author.
//
// Copyright @Radolyn, 2025
#include "message_shot_theme_state.h"
#include "lang_auto.h"
#include "ayu/ayu_settings.h"
#include "ayu/utils/telegram_helpers.h"
#include "data/data_document.h"
#include "data/data_document_media.h"
#include "data/data_file_origin.h"
#include "data/data_session.h"
#include "main/main_session.h"
#include "ui/style/style_palette_colorizer.h"
#include "window/themes/window_theme.h"
#include "window/themes/window_theme_preview.h"
#include <unordered_set>
namespace AyuFeatures::MessageShot {
namespace {
Window::Theme::EmbeddedType defaultSelected = Window::Theme::EmbeddedType(-1);
std::optional<QColor> defaultSelectedColor;
std::optional<Data::CloudTheme> customSelected;
rpl::event_stream<> resetDefaultSelectedStream;
rpl::event_stream<> resetCustomSelectedStream;
rpl::event_stream<Data::CloudTheme> themeChosenStream;
rpl::event_stream<style::palette> paletteChosenStream;
std::shared_ptr<style::palette> persistedPalette;
std::unordered_set<uint64> refreshedThemeAccounts;
std::optional<Data::CloudTheme> findCloudThemeById(
not_null<Main::Session*> session,
uint64 id) {
const auto &chat = session->data().cloudThemes().chatThemes();
const auto &list = session->data().cloudThemes().list();
auto it = ranges::find(chat, id, &Data::CloudTheme::id);
if (it != chat.end()) {
return *it;
}
it = ranges::find(list, id, &Data::CloudTheme::id);
if (it != list.end()) {
return *it;
}
return std::nullopt;
}
bool tryApplyCloudThemePalette(
not_null<Main::Session*> session,
const Data::CloudTheme &theme,
std::shared_ptr<style::palette> palette) {
if (!theme.documentId) {
return false;
}
const auto document = session->data().document(theme.documentId);
const auto documentView = document->createMediaView();
auto preview = Window::Theme::PreviewFromFile(
documentView->bytes(),
document->location().name(),
theme);
if (!preview) {
return false;
}
palette->reset();
palette->load(preview->instance.palette.save());
setCustomSelected(theme);
return true;
}
SavedThemeApplyResult tryApplyEmbeddedThemePalette(
const MessageShotSettings &shot,
std::shared_ptr<style::palette> palette,
Fn<void()> onApplied) {
if (shot.embeddedThemeType() == -1) {
return SavedThemeApplyResult::Failed;
}
const auto type = static_cast<Window::Theme::EmbeddedType>(shot.embeddedThemeType());
const auto themes = Window::Theme::EmbeddedThemes();
const auto it = ranges::find(themes, type, &Window::Theme::EmbeddedScheme::type);
if (it == themes.end()) {
return SavedThemeApplyResult::Failed;
}
const auto accentRgb = shot.embeddedThemeAccentColor();
if (it->path.isEmpty() && type == Window::Theme::EmbeddedType::Default) {
style::palette embeddedPalette;
const auto accent = (accentRgb != 0)
? std::optional<QColor>(QColor::fromRgb(accentRgb))
: std::nullopt;
Window::Theme::PreparePaletteCallback(false, accent)(embeddedPalette);
palette->reset();
palette->load(embeddedPalette.save());
setDefaultSelected(type);
if (accent) {
setDefaultSelectedColor(*accent);
}
if (onApplied) {
onApplied();
}
return SavedThemeApplyResult::AppliedSync;
}
if (accentRgb != 0) {
const auto color = QColor::fromRgb(accentRgb);
const auto colorizer = Window::Theme::ColorizerFrom(*it, color);
auto instance = Window::Theme::Instance();
if (!Window::Theme::LoadFromFile(it->path, &instance, nullptr, nullptr, colorizer)) {
return SavedThemeApplyResult::Failed;
}
palette->reset();
palette->load(instance.palette.save());
setDefaultSelected(type);
setDefaultSelectedColor(color);
if (onApplied) {
onApplied();
}
return SavedThemeApplyResult::AppliedSync;
}
const Data::CloudTheme cloud;
const auto preview = Window::Theme::PreviewFromFile(
QByteArray(),
it->path,
cloud);
if (!preview) {
return SavedThemeApplyResult::Failed;
}
palette->reset();
palette->load(preview->instance.palette.save());
setDefaultSelected(type);
if (onApplied) {
onApplied();
}
return SavedThemeApplyResult::AppliedSync;
}
void applyCloudThemeAsync(
not_null<Window::SessionController*> controller,
not_null<Main::Session*> session,
const Data::CloudTheme &theme,
std::shared_ptr<style::palette> palette,
Fn<void()> onApplied) {
if (!theme.documentId) {
return;
}
const auto weak = base::make_weak(controller);
const auto document = session->data().document(theme.documentId);
const auto documentView = document->createMediaView();
document->save(
Data::FileOriginTheme(theme.id, theme.accessHash),
QString());
const auto apply = [=] {
if (!weak) {
return;
}
auto preview = Window::Theme::PreviewFromFile(
documentView->bytes(),
document->location().name(),
theme);
if (!preview) {
return;
}
palette->reset();
palette->load(preview->instance.palette.save());
setCustomSelected(theme);
if (onApplied) {
onApplied();
}
};
if (documentView->loaded()) {
apply();
return;
}
session->downloaderTaskFinished(
) | rpl::filter([=] {
return documentView->loaded();
}) | rpl::take(1) | rpl::on_next([=] {
apply();
}, controller->lifetime());
}
}
void setDefaultSelected(const Window::Theme::EmbeddedType type) {
resetCustomSelected();
defaultSelected = type;
}
Window::Theme::EmbeddedType getSelectedFromDefault() {
return defaultSelected;
}
void setDefaultSelectedColor(const QColor color) {
resetCustomSelected();
defaultSelectedColor = color;
}
std::optional<QColor> getSelectedColorFromDefault() {
return defaultSelectedColor;
}
void setCustomSelected(const Data::CloudTheme theme) {
resetDefaultSelected();
customSelected = theme;
}
std::optional<Data::CloudTheme> getSelectedFromCustom() {
return customSelected;
}
void resetDefaultSelected() {
defaultSelected = Window::Theme::EmbeddedType(-1);
defaultSelectedColor = std::nullopt;
resetDefaultSelectedStream.fire({});
}
void resetCustomSelected() {
customSelected = std::nullopt;
resetCustomSelectedStream.fire({});
}
rpl::producer<> resetDefaultSelectedEvents() {
return resetDefaultSelectedStream.events();
}
rpl::producer<> resetCustomSelectedEvents() {
return resetCustomSelectedStream.events();
}
void setTheme(Data::CloudTheme theme) {
themeChosenStream.fire(std::move(theme));
}
rpl::producer<Data::CloudTheme> themeChosen() {
return themeChosenStream.events();
}
void setPalette(const style::palette &palette) {
paletteChosenStream.fire_copy(palette);
}
rpl::producer<style::palette> paletteChosen() {
return paletteChosenStream.events();
}
void ensureChatThemesRefreshed() {
const auto accountId = AyuSettings::getInstance().messageShotSettings().cloudThemeAccountId();
if (!accountId) {
return;
}
if (!refreshedThemeAccounts.emplace(accountId).second) {
return;
}
const auto session = getSession(accountId);
if (!session) {
refreshedThemeAccounts.erase(accountId);
return;
}
session->data().cloudThemes().refreshChatThemes();
session->data().cloudThemes().refresh();
}
// from `std::vector<EmbeddedScheme> EmbeddedThemes()`
QString embeddedThemeDisplayName(Window::Theme::EmbeddedType type) {
switch (type) {
case Window::Theme::EmbeddedType::Default:
return tr::lng_settings_theme_classic(tr::now);
case Window::Theme::EmbeddedType::DayBlue:
return tr::lng_settings_theme_day(tr::now);
case Window::Theme::EmbeddedType::Night:
return tr::lng_settings_theme_tinted(tr::now);
case Window::Theme::EmbeddedType::NightGreen:
return tr::lng_settings_theme_night(tr::now);
}
return tr::ayu_MessageShotThemeDefault(tr::now);
}
QString resolveThemeName() {
const auto &shot = AyuSettings::getInstance().messageShotSettings();
if (shot.cloudThemeId() != 0) {
return shot.cloudThemeTitle();
}
if (shot.embeddedThemeType() != -1) {
const auto type = static_cast<Window::Theme::EmbeddedType>(shot.embeddedThemeType());
return embeddedThemeDisplayName(type);
}
return tr::ayu_MessageShotThemeDefault(tr::now);
}
std::shared_ptr<style::palette> getPersistedPalette() {
return persistedPalette;
}
void setPersistedPalette(std::shared_ptr<style::palette> palette) {
persistedPalette = std::move(palette);
}
SavedThemeApplyResult applySavedThemePalette(
std::shared_ptr<style::palette> palette,
Fn<void()> onApplied) {
const auto &shot = AyuSettings::getInstance().messageShotSettings();
if (shot.embeddedThemeType() != -1) {
return tryApplyEmbeddedThemePalette(shot, std::move(palette), std::move(onApplied));
}
if (shot.cloudThemeId() == 0) {
return SavedThemeApplyResult::Failed;
}
const auto session = getSession(shot.cloudThemeAccountId());
if (!session) {
return SavedThemeApplyResult::Failed;
}
if (const auto fromList = findCloudThemeById(session, shot.cloudThemeId())) {
if (tryApplyCloudThemePalette(session, *fromList, palette)) {
if (onApplied) {
onApplied();
}
return SavedThemeApplyResult::AppliedSync;
}
}
Data::CloudTheme saved;
saved.id = shot.cloudThemeId();
saved.accessHash = shot.cloudThemeAccessHash();
saved.documentId = shot.cloudThemeDocumentId();
saved.title = shot.cloudThemeTitle();
if (tryApplyCloudThemePalette(session, saved, palette)) {
if (onApplied) {
onApplied();
}
return SavedThemeApplyResult::AppliedSync;
}
return SavedThemeApplyResult::AwaitingAsync;
}
void subscribeToCloudThemeLoad(
not_null<Window::SessionController*> controller,
std::shared_ptr<style::palette> palette,
Fn<void()> onApplied) {
const auto &shot = AyuSettings::getInstance().messageShotSettings();
if (shot.cloudThemeId() == 0) {
return;
}
const auto session = getSession(shot.cloudThemeAccountId());
if (!session) {
return;
}
if (getSelectedFromCustom().has_value()) {
return;
}
const auto id = shot.cloudThemeId();
const auto weak = base::make_weak(controller);
const auto tryApplyFromTheme = [=](const Data::CloudTheme &theme) {
applyCloudThemeAsync(controller, session, theme, palette, onApplied);
};
if (const auto theme = findCloudThemeById(session, id)) {
tryApplyFromTheme(*theme);
return;
}
const auto found = std::make_shared<bool>(false);
const auto tryFind = [=] {
if (*found || !weak) {
return;
}
if (const auto theme = findCloudThemeById(session, id)) {
*found = true;
tryApplyFromTheme(*theme);
}
};
session->data().cloudThemes().chatThemesUpdated(
) | rpl::on_next(tryFind, controller->lifetime());
session->data().cloudThemes().updated(
) | rpl::on_next(tryFind, controller->lifetime());
}
}
@@ -0,0 +1,59 @@
// This is the source code of AyuGram for Desktop.
//
// We do not and cannot prevent the use of our code,
// but be respectful and credit the original author.
//
// Copyright @Radolyn, 2025
#pragma once
#include "data/data_cloud_themes.h"
#include "window/themes/window_themes_embedded.h"
#include "window/window_session_controller.h"
#include "ui/style/style_core_palette.h"
#include <memory>
#include <optional>
namespace AyuFeatures::MessageShot {
enum class SavedThemeApplyResult {
AppliedSync,
AwaitingAsync,
Failed,
};
void setDefaultSelected(Window::Theme::EmbeddedType type);
Window::Theme::EmbeddedType getSelectedFromDefault();
void setDefaultSelectedColor(QColor color);
std::optional<QColor> getSelectedColorFromDefault();
void setCustomSelected(Data::CloudTheme theme);
std::optional<Data::CloudTheme> getSelectedFromCustom();
void resetDefaultSelected();
void resetCustomSelected();
rpl::producer<> resetDefaultSelectedEvents();
rpl::producer<> resetCustomSelectedEvents();
void setTheme(Data::CloudTheme theme);
rpl::producer<Data::CloudTheme> themeChosen();
void setPalette(const style::palette &palette);
rpl::producer<style::palette> paletteChosen();
void ensureChatThemesRefreshed();
QString resolveThemeName();
QString embeddedThemeDisplayName(Window::Theme::EmbeddedType type);
std::shared_ptr<style::palette> getPersistedPalette();
void setPersistedPalette(std::shared_ptr<style::palette> palette);
SavedThemeApplyResult applySavedThemePalette(
std::shared_ptr<style::palette> palette,
Fn<void()> onApplied);
void subscribeToCloudThemeLoad(
not_null<Window::SessionController*> controller,
std::shared_ptr<style::palette> palette,
Fn<void()> onApplied);
}
@@ -6,6 +6,7 @@
// Copyright @Radolyn, 2025 // Copyright @Radolyn, 2025
#include "message_shot_box.h" #include "message_shot_box.h"
#include <memory>
#include <QFileDialog> #include <QFileDialog>
#include <QGuiApplication> #include <QGuiApplication>
#include "styles/style_ayu_styles.h" #include "styles/style_ayu_styles.h"
@@ -16,8 +17,6 @@
#include "ayu/ui/components/image_view.h" #include "ayu/ui/components/image_view.h"
#include "ayu/utils/telegram_helpers.h" #include "ayu/utils/telegram_helpers.h"
#include "boxes/abstract_box.h" #include "boxes/abstract_box.h"
#include "core/core_settings.h"
#include "data/data_session.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "settings/settings_common.h" #include "settings/settings_common.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
@@ -37,13 +36,36 @@ void MessageShotBox::prepare() {
} }
void MessageShotBox::setupContent() { void MessageShotBox::setupContent() {
_selectedPalette = std::make_shared<style::palette>(); _selectedPalette = AyuFeatures::MessageShot::getPersistedPalette();
if (!_selectedPalette) {
_selectedPalette = std::make_shared<style::palette>();
}
AyuFeatures::MessageShot::setPersistedPalette(_selectedPalette);
const auto &settings = AyuSettings::getInstance(); AyuFeatures::MessageShot::ensureChatThemesRefreshed();
const auto savedShowColorfulReplies = !settings.simpleQuotesAndReplies();
auto &settings = AyuSettings::getInstance();
auto &shotSettings = settings.messageShotSettings();
const auto savedSimpleQuotesAndReplies = settings.simpleQuotesAndReplies();
settings.setSimpleQuotesAndReplies(!shotSettings.showColorfulReplies());
using namespace Settings; using namespace Settings;
auto savedThemeApplyResult = AyuFeatures::MessageShot::SavedThemeApplyResult::Failed;
const auto hasSavedTheme = shotSettings.embeddedThemeType() != -1
|| shotSettings.cloudThemeId() != 0;
if (hasSavedTheme) {
savedThemeApplyResult = AyuFeatures::MessageShot::applySavedThemePalette(
_selectedPalette,
nullptr);
if (savedThemeApplyResult != AyuFeatures::MessageShot::SavedThemeApplyResult::Failed) {
_config.st = std::make_shared<Ui::ChatStyle>(_selectedPalette.get());
} else {
shotSettings.clearTheme();
_config.st = std::make_shared<Ui::ChatStyle>(_config.controller->chatStyle());
}
}
AyuFeatures::MessageShot::setShotConfig(_config); AyuFeatures::MessageShot::setShotConfig(_config);
setTitle(rpl::single(QString("Message Shot"))); setTitle(rpl::single(QString("Message Shot")));
@@ -81,8 +103,23 @@ void MessageShotBox::setupContent() {
}); });
}; };
if (savedThemeApplyResult == AyuFeatures::MessageShot::SavedThemeApplyResult::AwaitingAsync) {
const auto weakBox = base::make_weak(this);
AyuFeatures::MessageShot::subscribeToCloudThemeLoad(
_config.controller,
_selectedPalette,
[=] {
if (!weakBox) {
return;
}
_config.st = std::make_shared<Ui::ChatStyle>(_selectedPalette.get());
updatePreview();
});
}
auto selectedTheme = auto selectedTheme =
content->lifetime().make_state<rpl::variable<QString>>(tr::ayu_MessageShotThemeDefault(tr::now)); content->lifetime().make_state<rpl::variable<QString>>(
AyuFeatures::MessageShot::resolveThemeName());
AddButtonWithLabel( AddButtonWithLabel(
content, content,
@@ -101,8 +138,20 @@ void MessageShotBox::setupContent() {
_selectedPalette->reset(); _selectedPalette->reset();
_selectedPalette->load(palette.save()); _selectedPalette->load(palette.save());
_config.st = std::make_shared<Ui::ChatStyle>( _config.st = std::make_shared<Ui::ChatStyle>(_selectedPalette.get());
_selectedPalette.get());
auto &shot = AyuSettings::getInstance().messageShotSettings();
const auto embedded = AyuFeatures::MessageShot::getSelectedFromDefault();
const auto cloud = AyuFeatures::MessageShot::getSelectedFromCustom();
if (cloud.has_value()) {
const auto accountId = _config.controller->session().userId().bare;
shot.setCloudTheme(accountId, cloud->id, cloud->accessHash, cloud->documentId, cloud->title);
} else if (embedded != Window::Theme::EmbeddedType(-1)) {
const auto color = AyuFeatures::MessageShot::getSelectedColorFromDefault();
shot.setEmbeddedTheme(static_cast<int>(embedded), color ? color->rgb() : 0);
} else {
shot.clearTheme();
}
updatePreview(); updatePreview();
}, },
@@ -128,13 +177,12 @@ void MessageShotBox::setupContent() {
content, content,
tr::ayu_MessageShotShowBackground(), tr::ayu_MessageShotShowBackground(),
st::settingsButtonNoIcon st::settingsButtonNoIcon
)->toggleOn(rpl::single(_config.showBackground) )->toggleOn(rpl::single(shotSettings.showBackground())
)->toggledValue( )->toggledValue(
) | on_next( ) | rpl::skip(1) | on_next(
[=](bool enabled) [=](bool enabled)
{ {
_config.showBackground = enabled; AyuSettings::getInstance().messageShotSettings().setShowBackground(enabled);
updatePreview(); updatePreview();
}, },
content->lifetime()); content->lifetime());
@@ -143,13 +191,12 @@ void MessageShotBox::setupContent() {
content, content,
tr::ayu_MessageShotShowDate(), tr::ayu_MessageShotShowDate(),
st::settingsButtonNoIcon st::settingsButtonNoIcon
)->toggleOn(rpl::single(_config.showDate) )->toggleOn(rpl::single(shotSettings.showDate())
)->toggledValue( )->toggledValue(
) | on_next( ) | rpl::skip(1) | on_next(
[=](bool enabled) [=](bool enabled)
{ {
_config.showDate = enabled; AyuSettings::getInstance().messageShotSettings().setShowDate(enabled);
updatePreview(); updatePreview();
}, },
content->lifetime()); content->lifetime());
@@ -158,13 +205,12 @@ void MessageShotBox::setupContent() {
content, content,
tr::ayu_MessageShotShowReactions(), tr::ayu_MessageShotShowReactions(),
st::settingsButtonNoIcon st::settingsButtonNoIcon
)->toggleOn(rpl::single(_config.showReactions) )->toggleOn(rpl::single(shotSettings.showReactions())
)->toggledValue( )->toggledValue(
) | on_next( ) | rpl::skip(1) | on_next(
[=](bool enabled) [=](bool enabled)
{ {
_config.showReactions = enabled; AyuSettings::getInstance().messageShotSettings().setShowReactions(enabled);
updatePreview(); updatePreview();
}, },
content->lifetime()); content->lifetime());
@@ -174,12 +220,14 @@ void MessageShotBox::setupContent() {
tr::ayu_MessageShotShowColorfulReplies(), tr::ayu_MessageShotShowColorfulReplies(),
st::settingsButtonNoIcon st::settingsButtonNoIcon
); );
latestToggle->toggleOn(rpl::single(savedShowColorfulReplies) latestToggle->toggleOn(rpl::single(shotSettings.showColorfulReplies())
)->toggledValue( )->toggledValue(
) | on_next( ) | rpl::skip(1) | on_next(
[=](bool enabled) [=](bool enabled)
{ {
AyuSettings::getInstance().setSimpleQuotesAndReplies(!enabled); auto &currentSettings = AyuSettings::getInstance();
currentSettings.messageShotSettings().setShowColorfulReplies(enabled);
currentSettings.setSimpleQuotesAndReplies(!enabled);
_config.st = std::make_shared<Ui::ChatStyle>(_config.st.get()); _config.st = std::make_shared<Ui::ChatStyle>(_config.st.get());
updatePreview(); updatePreview();
@@ -226,12 +274,11 @@ void MessageShotBox::setupContent() {
AyuFeatures::MessageShot::resetDefaultSelected(); AyuFeatures::MessageShot::resetDefaultSelected();
AyuFeatures::MessageShot::resetShotConfig(); AyuFeatures::MessageShot::resetShotConfig();
AyuSettings::getInstance().setSimpleQuotesAndReplies(!savedShowColorfulReplies); AyuSettings::getInstance().setSimpleQuotesAndReplies(savedSimpleQuotesAndReplies);
}, },
content->lifetime()); content->lifetime());
setDimensionsToContent(boxWidth, content); setDimensionsToContent(boxWidth, content);
// scroll to the end
scrollToWidget(latestToggle); scrollToWidget(latestToggle);
} }
@@ -7,7 +7,7 @@
#include "theme_selector_box.h" #include "theme_selector_box.h"
#include "lang_auto.h" #include "lang_auto.h"
#include "ayu/features/message_shot/message_shot.h" #include "ayu/features/message_shot/message_shot_theme_state.h"
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_document_media.h" #include "data/data_document_media.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
@@ -140,6 +140,9 @@ void ThemeSelectorBox::setupContent() {
documentView->bytes(), documentView->bytes(),
document->location().name(), document->location().name(),
theme); theme);
if (!preview) {
return;
}
_selectedPalette = preview->instance.palette; _selectedPalette = preview->instance.palette;
@@ -168,7 +171,11 @@ void ThemeSelectorBox::setupContent() {
AyuFeatures::MessageShot::paletteChosen( AyuFeatures::MessageShot::paletteChosen(
) | rpl::on_next([=](const auto &palette) ) | rpl::on_next([=](const auto &palette)
{ {
_themeNames.fire(tr::ayu_MessageShotThemeDefault(tr::now)); const auto type = AyuFeatures::MessageShot::getSelectedFromDefault();
const auto name = (type != Window::Theme::EmbeddedType(-1))
? AyuFeatures::MessageShot::embeddedThemeDisplayName(type)
: tr::ayu_MessageShotThemeDefault(tr::now);
_themeNames.fire(QString(name));
_selectedPalette = palette; _selectedPalette = palette;
}, },
lifetime()); lifetime());
@@ -75,6 +75,9 @@ const auto kZalgoPattern = QStringLiteral(
} }
Main::Session *getSession(ID userId) { Main::Session *getSession(ID userId) {
if (!userId) {
return nullptr;
}
for (const auto &[index, account] : Core::App().domain().accounts()) { for (const auto &[index, account] : Core::App().domain().accounts()) {
if (const auto session = account->maybeSession()) { if (const auto session = account->maybeSession()) {
if (session->userId().bare == userId) { if (session->userId().bare == userId) {
@@ -196,7 +196,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ayu/utils/telegram_helpers.h" #include "ayu/utils/telegram_helpers.h"
#include "ayu/features/message_shot/message_shot.h" #include "ayu/features/message_shot/message_shot.h"
#include "ayu/features/forward/ayu_forward.h" #include "ayu/features/forward/ayu_forward.h"
#include "ayu/ui/boxes/message_shot_box.h"
#include "boxes/abstract_box.h" #include "boxes/abstract_box.h"
@@ -9401,32 +9400,13 @@ void HistoryWidget::confirmDeleteSelected() {
} }
void HistoryWidget::messageShotSelected() { void HistoryWidget::messageShotSelected() {
if (!_list) return; if (!_list) {
auto items = getSelectedItems();
if (items.empty()) {
return; return;
} }
const auto messages = ranges::views::all(items) AyuFeatures::MessageShot::Wrapper(
| ranges::views::transform([this](const auto fullId) _list.data(),
{ [=] { clearSelected(); });
return gsl::not_null(session().data().message(fullId));
})
| ranges::to_vector;
const AyuFeatures::MessageShot::ShotConfig config = {
controller(),
std::make_shared<Ui::ChatStyle>(controller()->chatStyle()),
messages
};
auto box = Box<MessageShotBox>(config);
const auto raw = box.data();
raw->boxClosing() | rpl::on_next([=]
{
if (raw->tookShot()) clearSelected();
}, raw->lifetime());
Ui::show(std::move(box));
} }
void HistoryWidget::escape() { void HistoryWidget::escape() {
@@ -1529,6 +1529,25 @@ void SetupDefaultThemes(
const auto updateMessageShotPalette = [=](const QString &path) const auto updateMessageShotPalette = [=](const QString &path)
{ {
if (path.isEmpty()) { // for Default theme (otherwise doesn't dispaly name properly)
style::palette embeddedPalette;
const auto color = AyuFeatures::MessageShot::getSelectedColorFromDefault();
Window::Theme::PreparePaletteCallback(false, color)(embeddedPalette);
AyuFeatures::MessageShot::setPalette(embeddedPalette);
return;
}
if (const auto color = AyuFeatures::MessageShot::getSelectedColorFromDefault()) {
const auto type = AyuFeatures::MessageShot::getSelectedFromDefault();
const auto scheme = ranges::find(kSchemesList, type, &Scheme::type);
if (scheme != end(kSchemesList)) {
const auto colorizer = ColorizerFrom(*scheme, *color);
auto instance = Window::Theme::Instance();
if (Window::Theme::LoadFromFile(path, &instance, nullptr, nullptr, colorizer)) {
AyuFeatures::MessageShot::setPalette(instance.palette);
return;
}
}
}
const Data::CloudTheme theme; const Data::CloudTheme theme;
if (const auto preview = PreviewFromFile(QByteArray(), path, theme)) { if (const auto preview = PreviewFromFile(QByteArray(), path, theme)) {
AyuFeatures::MessageShot::setPalette(preview->instance.palette); AyuFeatures::MessageShot::setPalette(preview->instance.palette);