Show not supported themes placeholders.

This commit is contained in:
John Preston 2019-09-05 23:21:44 +03:00
parent 639b4bdd27
commit 910f16312c
12 changed files with 194 additions and 90 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -34,7 +34,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h" #include "main/main_session.h"
#include "window/themes/window_theme.h" #include "window/themes/window_theme.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "window/themes/window_theme_editor.h"
#include "base/flags.h" #include "base/flags.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "history/history.h" #include "history/history.h"
@ -4479,26 +4478,30 @@ std::vector<Lang::Language> readRecentLanguages() {
return result; return result;
} }
bool copyThemeColorsToPalette(const QString &destination) { Window::Theme::Object ReadThemeContent() {
using namespace Window::Theme; using namespace Window::Theme;
auto &themeKey = IsNightMode() ? _themeKeyNight : _themeKeyDay; auto &themeKey = IsNightMode() ? _themeKeyNight : _themeKeyDay;
if (!themeKey) { if (!themeKey) {
return false; return Object();
} }
FileReadDescriptor theme; FileReadDescriptor theme;
if (!readEncryptedFile(theme, themeKey, FileOption::Safe, SettingsKey)) { if (!readEncryptedFile(theme, themeKey, FileOption::Safe, SettingsKey)) {
return false; return Object();
} }
QByteArray themeContent; QByteArray content;
QString pathRelative, pathAbsolute; QString pathRelative, pathAbsolute;
theme.stream >> themeContent >> pathRelative >> pathAbsolute; theme.stream >> content >> pathRelative >> pathAbsolute;
if (theme.stream.status() != QDataStream::Ok) { if (theme.stream.status() != QDataStream::Ok) {
return false; return Object();
} }
return CopyColorsToPalette(destination, pathAbsolute, themeContent); auto result = Object();
result.pathAbsolute = pathAbsolute;
result.content = content;
return result;
} }
void writeRecentHashtagsAndBots() { void writeRecentHashtagsAndBots() {

View File

@ -26,6 +26,7 @@ class EncryptionKey;
namespace Window { namespace Window {
namespace Theme { namespace Theme {
struct Object;
struct Saved; struct Saved;
} // namespace Theme } // namespace Theme
} // namespace Window } // namespace Window
@ -152,8 +153,9 @@ bool readBackground();
void writeTheme(const Window::Theme::Saved &saved); void writeTheme(const Window::Theme::Saved &saved);
void clearTheme(); void clearTheme();
bool copyThemeColorsToPalette(const QString &destination); [[nodiscard]] Window::Theme::Saved readThemeAfterSwitch();
Window::Theme::Saved readThemeAfterSwitch();
[[nodiscard]] Window::Theme::Object ReadThemeContent();
void writeLangPack(); void writeLangPack();
void pushRecentLanguage(const Lang::Language &language); void pushRecentLanguage(const Lang::Language &language);

View File

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/themes/window_theme_preview.h" #include "window/themes/window_theme_preview.h"
#include "window/themes/window_themes_embedded.h" #include "window/themes/window_themes_embedded.h"
#include "window/themes/window_theme_editor.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "apiwrap.h" #include "apiwrap.h"
@ -49,14 +50,6 @@ Applying GlobalApplying;
inline bool AreTestingTheme() { inline bool AreTestingTheme() {
return !GlobalApplying.paletteForRevert.isEmpty(); return !GlobalApplying.paletteForRevert.isEmpty();
};
[[nodiscard]] bool IsEditingTheme(const QString &path) {
static const auto kEditingPath = QFileInfo(
EditingPalettePath()
).absoluteFilePath();
return !path.compare(kEditingPath, Qt::CaseInsensitive)
&& QFileInfo(path).exists();
} }
bool CalculateIsMonoColorImage(const QImage &image) { bool CalculateIsMonoColorImage(const QImage &image) {
@ -408,7 +401,7 @@ bool InitializeFromSaved(Saved &&saved) {
return false; return false;
} }
if (editing) { if (editing) {
Background()->setIsEditingTheme(true); Background()->setEditingTheme(ReadCloudFromText(*editing));
} else { } else {
Local::writeTheme(saved); Local::writeTheme(saved);
} }
@ -544,7 +537,7 @@ void ChatBackground::checkUploadWallPaper() {
} }
if (!Data::IsCustomWallPaper(_paper) if (!Data::IsCustomWallPaper(_paper)
|| _original.isNull() || _original.isNull()
|| isEditingTheme()) { || _editingTheme.has_value()) {
return; return;
} }
@ -734,7 +727,7 @@ bool ChatBackground::adjustPaletteRequired() {
|| Data::details::IsTestingDefaultWallPaper(_paper); || Data::details::IsTestingDefaultWallPaper(_paper);
}; };
if (isEditingTheme()) { if (_editingTheme.has_value()) {
return false; return false;
} else if (isNonDefaultThemeOrBackground() || nightMode()) { } else if (isNonDefaultThemeOrBackground() || nightMode()) {
return !usingThemeBackground(); return !usingThemeBackground();
@ -742,12 +735,13 @@ bool ChatBackground::adjustPaletteRequired() {
return !usingDefaultBackground(); return !usingDefaultBackground();
} }
bool ChatBackground::isEditingTheme() const { std::optional<Data::CloudTheme> ChatBackground::editingTheme() const {
return _editingTheme; return _editingTheme;
} }
void ChatBackground::setIsEditingTheme(bool editing) { void ChatBackground::setEditingTheme(
if (_editingTheme == editing) { std::optional<Data::CloudTheme> editing) {
if (!_editingTheme && !editing) {
return; return;
} }
_editingTheme = editing; _editingTheme = editing;
@ -913,7 +907,7 @@ void ChatBackground::setTestingTheme(Instance &&theme) {
|| (Data::IsDefaultWallPaper(_paper) || (Data::IsDefaultWallPaper(_paper)
&& !nightMode() && !nightMode()
&& _themeObject.pathAbsolute.isEmpty()); && _themeObject.pathAbsolute.isEmpty());
if (AreTestingTheme() && isEditingTheme()) { if (AreTestingTheme() && _editingTheme.has_value()) {
// Grab current background image if it is not already custom // Grab current background image if it is not already custom
// Use prepared pixmap, not original image, because we're // Use prepared pixmap, not original image, because we're
// for sure switching to a non-pattern wall-paper (testing editor). // for sure switching to a non-pattern wall-paper (testing editor).

View File

@ -120,8 +120,8 @@ public:
void setTileNightValue(bool tile); void setTileNightValue(bool tile);
void setThemeObject(const Object &object); void setThemeObject(const Object &object);
[[nodiscard]] const Object &themeObject() const; [[nodiscard]] const Object &themeObject() const;
[[nodiscard]] bool isEditingTheme() const; [[nodiscard]] std::optional<Data::CloudTheme> editingTheme() const;
void setIsEditingTheme(bool editing); void setEditingTheme(std::optional<Data::CloudTheme> editing);
void reset(); void reset();
void setTestingTheme(Instance &&theme); void setTestingTheme(Instance &&theme);
@ -201,7 +201,7 @@ private:
Object _themeObject; Object _themeObject;
QImage _themeImage; QImage _themeImage;
bool _themeTile = false; bool _themeTile = false;
bool _editingTheme = false; std::optional<Data::CloudTheme> _editingTheme;
Data::WallPaper _paperForRevert Data::WallPaper _paperForRevert
= Data::details::UninitializedWallPaper(); = Data::details::UninitializedWallPaper();
@ -221,11 +221,6 @@ ChatBackground *Background();
void ComputeBackgroundRects(QRect wholeFill, QSize imageSize, QRect &to, QRect &from); void ComputeBackgroundRects(QRect wholeFill, QSize imageSize, QRect &to, QRect &from);
bool CopyColorsToPalette(
const QString &destination,
const QString &themePath,
const QByteArray &themeContent);
bool ReadPaletteValues(const QByteArray &content, Fn<bool(QLatin1String name, QLatin1String value)> callback); bool ReadPaletteValues(const QByteArray &content, Fn<bool(QLatin1String name, QLatin1String value)> callback);
} // namespace Theme } // namespace Theme

View File

@ -35,6 +35,14 @@ namespace Window {
namespace Theme { namespace Theme {
namespace { namespace {
template <size_t Size>
QByteArray qba(const char(&string)[Size]) {
return QByteArray::fromRawData(string, Size - 1);
}
const auto kCloudInTextStart = qba("// THEME EDITOR SERVICE INFO START\n");
const auto kCloudInTextEnd = qba("// THEME EDITOR SERVICE INFO END\n\n");
struct ReadColorResult { struct ReadColorResult {
ReadColorResult(QColor color, bool error = false) : color(color), error(error) { ReadColorResult(QColor color, bool error = false) : color(color), error(error) {
} }
@ -186,7 +194,7 @@ QByteArray replaceValueInContent(const QByteArray &content, const QByteArray &na
return QByteArray(); return QByteArray();
} }
QByteArray ColorizeInContent( [[nodiscard]] QByteArray ColorizeInContent(
QByteArray content, QByteArray content,
const Colorizer &colorizer) { const Colorizer &colorizer) {
auto validNames = OrderedSet<QLatin1String>(); auto validNames = OrderedSet<QLatin1String>();
@ -294,44 +302,41 @@ private:
}; };
bool CopyColorsToPalette( [[nodiscard]] QByteArray WriteCloudToText(const Data::CloudTheme &cloud) {
const QString &destination, auto result = QByteArray();
const QString &themePath, const auto add = [&](const QByteArray &key, const QString &value) {
const QByteArray &themeContent) { result.append("// " + key + ": " + value.toLatin1() + "\n");
auto paletteContent = themeContent; };
result.append(kCloudInTextStart);
add("ID", QString::number(cloud.id));
add("ACCESS", QString::number(cloud.accessHash));
result.append(kCloudInTextEnd);
return result;
}
zlib::FileToRead file(themeContent); [[nodiscard]] Data::CloudTheme ReadCloudFromText(const QByteArray &text) {
const auto index = text.indexOf(kCloudInTextEnd);
unz_global_info globalInfo = { 0 }; if (index <= 1) {
file.getGlobalInfo(&globalInfo); return Data::CloudTheme();
if (file.error() == UNZ_OK) { }
paletteContent = file.readFileContent("colors.tdesktop-theme", zlib::kCaseInsensitive, kThemeSchemeSizeLimit); auto result = Data::CloudTheme();
if (file.error() == UNZ_END_OF_LIST_OF_FILE) { const auto list = text.mid(0, index - 1).split('\n');
file.clearError(); const auto take = [&](uint64 &value, int index) {
paletteContent = file.readFileContent("colors.tdesktop-palette", zlib::kCaseInsensitive, kThemeSchemeSizeLimit); if (list.size() <= index) {
}
if (file.error() != UNZ_OK) {
LOG(("Theme Error: could not read 'colors.tdesktop-theme' or 'colors.tdesktop-palette' in the theme file, while copying to '%1'.").arg(destination));
return false; return false;
} }
const auto &entry = list[index];
const auto position = entry.indexOf(": ");
if (position < 0) {
return false;
}
value = QString::fromLatin1(entry.mid(position + 2)).toULongLong();
return true;
};
if (!take(result.id, 1) || !take(result.accessHash, 2)) {
return Data::CloudTheme();
} }
return result;
QFile f(destination);
if (!f.open(QIODevice::WriteOnly)) {
LOG(("Theme Error: could not open file for write '%1'").arg(destination));
return false;
}
if (const auto colorizer = ColorizerForTheme(themePath)) {
paletteContent = ColorizeInContent(
std::move(paletteContent),
colorizer);
}
if (f.write(paletteContent) != paletteContent.size()) {
LOG(("Theme Error: could not write palette to '%1'").arg(destination));
return false;
}
return true;
} }
Editor::Inner::Inner(QWidget *parent, const QString &path) : TWidget(parent) Editor::Inner::Inner(QWidget *parent, const QString &path) : TWidget(parent)
@ -680,12 +685,22 @@ Editor::Editor(
resizeToWidth(st::windowMinWidth); resizeToWidth(st::windowMinWidth);
} }
QByteArray Editor::ColorizeInContent(
QByteArray content,
const Colorizer &colorizer) {
return Window::Theme::ColorizeInContent(content, colorizer);
}
void Editor::save() { void Editor::save() {
if (!_window->account().sessionExists()) { if (!_window->account().sessionExists()) {
Ui::Toast::Show(tr::lng_theme_editor_need_auth(tr::now)); Ui::Toast::Show(tr::lng_theme_editor_need_auth(tr::now));
return; return;
} else if (_saving) {
return;
} }
Ui::show(Box(SaveThemeBox, _window, _cloud, _inner->paletteContent())); _saving = true;
const auto unlock = crl::guard(this, [=] { _saving = false; });
SaveTheme(_window, _cloud, _inner->paletteContent(), unlock);
} }
void Editor::resizeEvent(QResizeEvent *e) { void Editor::resizeEvent(QResizeEvent *e) {
@ -776,7 +791,7 @@ void Editor::paintEvent(QPaintEvent *e) {
void Editor::closeEditor() { void Editor::closeEditor() {
if (const auto window = App::wnd()) { if (const auto window = App::wnd()) {
window->showRightColumn(nullptr); window->showRightColumn(nullptr);
Background()->setIsEditingTheme(false); Background()->setEditingTheme(std::nullopt);
} }
} }

View File

@ -23,10 +23,10 @@ class Controller;
namespace Theme { namespace Theme {
bool CopyColorsToPalette( struct Colorizer;
const QString &destination,
const QString &themePath, [[nodiscard]] QByteArray WriteCloudToText(const Data::CloudTheme &cloud);
const QByteArray &themeContent); [[nodiscard]] Data::CloudTheme ReadCloudFromText(const QByteArray &text);
class Editor : public TWidget { class Editor : public TWidget {
public: public:
@ -35,6 +35,10 @@ public:
not_null<Window::Controller*> window, not_null<Window::Controller*> window,
const Data::CloudTheme &cloud); const Data::CloudTheme &cloud);
[[nodiscard]] static QByteArray ColorizeInContent(
QByteArray content,
const Colorizer &colorizer);
protected: protected:
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
@ -57,6 +61,7 @@ private:
object_ptr<Ui::PlainShadow> _leftShadow; object_ptr<Ui::PlainShadow> _leftShadow;
object_ptr<Ui::PlainShadow> _topShadow; object_ptr<Ui::PlainShadow> _topShadow;
object_ptr<Ui::FlatButton> _save; object_ptr<Ui::FlatButton> _save;
bool _saving = false;
}; };

View File

@ -86,6 +86,7 @@ private:
QByteArray _backgroundContent; QByteArray _backgroundContent;
bool _isPng = false; bool _isPng = false;
QString _imageText; QString _imageText;
int _thumbnailSize = 0;
QPixmap _thumbnail; QPixmap _thumbnail;
}; };
@ -112,12 +113,12 @@ BackgroundSelector::BackgroundSelector(
formatSizeText(_backgroundContent.size())); formatSizeText(_backgroundContent.size()));
_chooseFromFile->setClickedCallback([=] { chooseBackgroundFromFile(); }); _chooseFromFile->setClickedCallback([=] { chooseBackgroundFromFile(); });
const auto height = st::boxTextFont->height _thumbnailSize = st::boxTextFont->height
+ st::themesSmallSkip + st::themesSmallSkip
+ _chooseFromFile->heightNoMargins() + _chooseFromFile->heightNoMargins()
+ st::themesSmallSkip + st::themesSmallSkip
+ _tileBackground->heightNoMargins(); + _tileBackground->heightNoMargins();
resize(width(), height); resize(width(), _thumbnailSize + st::themesSmallSkip);
updateThumbnail(); updateThumbnail();
} }
@ -125,7 +126,7 @@ BackgroundSelector::BackgroundSelector(
void BackgroundSelector::paintEvent(QPaintEvent *e) { void BackgroundSelector::paintEvent(QPaintEvent *e) {
Painter p(this); Painter p(this);
const auto left = height() + st::themesSmallSkip; const auto left = _thumbnailSize + st::themesSmallSkip;
p.setPen(st::boxTextFg); p.setPen(st::boxTextFg);
p.setFont(st::boxTextFont); p.setFont(st::boxTextFont);
@ -135,14 +136,14 @@ void BackgroundSelector::paintEvent(QPaintEvent *e) {
} }
int BackgroundSelector::resizeGetHeight(int newWidth) { int BackgroundSelector::resizeGetHeight(int newWidth) {
const auto left = height() + st::themesSmallSkip; const auto left = _thumbnailSize + st::themesSmallSkip;
_chooseFromFile->moveToLeft(left, st::boxTextFont->height + st::themesSmallSkip); _chooseFromFile->moveToLeft(left, st::boxTextFont->height + st::themesSmallSkip);
_tileBackground->moveToLeft(left, st::boxTextFont->height + st::themesSmallSkip + _chooseFromFile->height() + st::themesSmallSkip); _tileBackground->moveToLeft(left, st::boxTextFont->height + st::themesSmallSkip + _chooseFromFile->height() + st::themesSmallSkip);
return height(); return height();
} }
void BackgroundSelector::updateThumbnail() { void BackgroundSelector::updateThumbnail() {
const auto size = height(); const auto size = _thumbnailSize;
auto back = QImage( auto back = QImage(
QSize(size, size) * cIntRetinaFactor(), QSize(size, size) * cIntRetinaFactor(),
QImage::Format_ARGB32_Premultiplied); QImage::Format_ARGB32_Premultiplied);
@ -233,11 +234,55 @@ void ImportFromFile(
crl::guard(parent, callback)); crl::guard(parent, callback));
} }
QString BytesToUTF8(QLatin1String string) { [[nodiscard]] QString BytesToUTF8(QLatin1String string) {
return QString::fromUtf8(string.data(), string.size()); return QString::fromUtf8(string.data(), string.size());
} }
bool WriteDefaultPalette(const QString &path) { [[nodiscard]] bool CopyColorsToPalette(
const QString &destination,
const QString &themePath,
const QByteArray &themeContent,
const Data::CloudTheme &cloud) {
auto paletteContent = themeContent;
zlib::FileToRead file(themeContent);
unz_global_info globalInfo = { 0 };
file.getGlobalInfo(&globalInfo);
if (file.error() == UNZ_OK) {
paletteContent = file.readFileContent("colors.tdesktop-theme", zlib::kCaseInsensitive, kThemeSchemeSizeLimit);
if (file.error() == UNZ_END_OF_LIST_OF_FILE) {
file.clearError();
paletteContent = file.readFileContent("colors.tdesktop-palette", zlib::kCaseInsensitive, kThemeSchemeSizeLimit);
}
if (file.error() != UNZ_OK) {
LOG(("Theme Error: could not read 'colors.tdesktop-theme' or 'colors.tdesktop-palette' in the theme file, while copying to '%1'.").arg(destination));
return false;
}
}
QFile f(destination);
if (!f.open(QIODevice::WriteOnly)) {
LOG(("Theme Error: could not open file for write '%1'").arg(destination));
return false;
}
if (const auto colorizer = ColorizerForTheme(themePath)) {
paletteContent = Editor::ColorizeInContent(
std::move(paletteContent),
colorizer);
}
paletteContent = WriteCloudToText(cloud) + paletteContent;
if (f.write(paletteContent) != paletteContent.size()) {
LOG(("Theme Error: could not write palette to '%1'").arg(destination));
return false;
}
return true;
}
bool WriteDefaultPalette(
const QString &path,
const Data::CloudTheme &cloud) {
QFile f(path); QFile f(path);
if (!f.open(QIODevice::WriteOnly)) { if (!f.open(QIODevice::WriteOnly)) {
LOG(("Theme Error: could not open '%1' for writing.").arg(path)); LOG(("Theme Error: could not open '%1' for writing.").arg(path));
@ -247,6 +292,8 @@ bool WriteDefaultPalette(const QString &path) {
QTextStream stream(&f); QTextStream stream(&f);
stream.setCodec("UTF-8"); stream.setCodec("UTF-8");
stream << QString::fromLatin1(WriteCloudToText(cloud));
auto rows = style::main_palette::data(); auto rows = style::main_palette::data();
for (const auto &row : std::as_const(rows)) { for (const auto &row : std::as_const(rows)) {
stream stream
@ -396,7 +443,7 @@ SendMediaReady PrepareThemeMedia(
0); 0);
} }
Fn<void()> SaveTheme( Fn<void()> SavePreparedTheme(
not_null<Window::Controller*> window, not_null<Window::Controller*> window,
const QByteArray &palette, const QByteArray &palette,
const PreparedBackground &background, const PreparedBackground &background,
@ -494,12 +541,15 @@ void StartEditor(
not_null<Window::Controller*> window, not_null<Window::Controller*> window,
const Data::CloudTheme &cloud) { const Data::CloudTheme &cloud) {
const auto path = EditingPalettePath(); const auto path = EditingPalettePath();
if (!Local::copyThemeColorsToPalette(path) auto object = Local::ReadThemeContent();
&& !WriteDefaultPalette(path)) { const auto written = object.content.isEmpty()
? WriteDefaultPalette(path, cloud)
: CopyColorsToPalette(path, object.pathAbsolute, object.content, cloud);
if (!written) {
window->show(Box<InformBox>(tr::lng_theme_editor_error(tr::now))); window->show(Box<InformBox>(tr::lng_theme_editor_error(tr::now)));
return; return;
} }
Background()->setIsEditingTheme(true); Background()->setEditingTheme(cloud);
window->showRightColumn(Box<Editor>(window, cloud)); window->showRightColumn(Box<Editor>(window, cloud));
} }
@ -561,6 +611,40 @@ void CreateForExistingBox(
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
} }
void SaveTheme(
not_null<Window::Controller*> window,
const Data::CloudTheme &cloud,
const QByteArray &palette,
Fn<void()> unlock) {
Expects(window->account().sessionExists());
using Data::CloudTheme;
const auto save = [=](const CloudTheme &fields) {
window->show(Box(SaveThemeBox, window, fields, palette));
};
if (cloud.id) {
window->account().session().api().request(MTPaccount_GetTheme(
MTP_string(Data::CloudThemes::Format()),
MTP_inputTheme(MTP_long(cloud.id), MTP_long(cloud.accessHash)),
MTP_long(0)
)).done([=](const MTPTheme &result) {
unlock();
result.match([&](const MTPDtheme &data) {
save(CloudTheme::Parse(&window->account().session(), data));
}, [&](const MTPDthemeDocumentNotModified &data) {
LOG(("API Error: Unexpected themeDocumentNotModified."));
save(CloudTheme());
});
}).fail([=](const RPCError &error) {
unlock();
save(CloudTheme());
}).send();
} else {
save(CloudTheme());
}
}
void SaveThemeBox( void SaveThemeBox(
not_null<GenericBox*> box, not_null<GenericBox*> box,
not_null<Window::Controller*> window, not_null<Window::Controller*> window,
@ -594,7 +678,7 @@ void SaveThemeBox(
linkWrap, linkWrap,
st::createThemeLink, st::createThemeLink,
rpl::single(qsl("link")), rpl::single(qsl("link")),
cloud.slug, cloud.slug.isEmpty() ? GenerateSlug() : cloud.slug,
true); true);
linkWrap->widthValue( linkWrap->widthValue(
) | rpl::start_with_next([=](int width) { ) | rpl::start_with_next([=](int width) {
@ -657,6 +741,7 @@ void SaveThemeBox(
const auto fail = crl::guard(box, [=]( const auto fail = crl::guard(box, [=](
SaveErrorType type, SaveErrorType type,
const QString &text) { const QString &text) {
*saving = false;
if (!text.isEmpty()) { if (!text.isEmpty()) {
Ui::Toast::Show(text); Ui::Toast::Show(text);
} }
@ -666,7 +751,7 @@ void SaveThemeBox(
link->showError(); link->showError();
} }
}); });
*cancel = SaveTheme( *cancel = SavePreparedTheme(
window, window,
palette, palette,
back->result(), back->result(),

View File

@ -29,6 +29,11 @@ void CreateForExistingBox(
not_null<GenericBox*> box, not_null<GenericBox*> box,
not_null<Window::Controller*> window, not_null<Window::Controller*> window,
const Data::CloudTheme &cloud); const Data::CloudTheme &cloud);
void SaveTheme(
not_null<Window::Controller*> window,
const Data::CloudTheme &cloud,
const QByteArray &palette,
Fn<void()> unlock);
void SaveThemeBox( void SaveThemeBox(
not_null<GenericBox*> box, not_null<GenericBox*> box,
not_null<Window::Controller*> window, not_null<Window::Controller*> window,

View File

@ -46,9 +46,9 @@ void Controller::firstShow() {
void Controller::checkThemeEditor() { void Controller::checkThemeEditor() {
using namespace Window::Theme; using namespace Window::Theme;
if (Background()->isEditingTheme()) {
showRightColumn( if (const auto editing = Background()->editingTheme()) {
Box<Editor>(this, Background()->themeObject().cloud)); showRightColumn(Box<Editor>(this, *editing));
} }
} }