Open theme editor for existing themes.

This commit is contained in:
John Preston 2019-09-05 08:18:21 +03:00
parent dd74f57a66
commit 03bdd80b2f
11 changed files with 111 additions and 91 deletions

View File

@ -337,8 +337,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_bg_use_default" = "Use default color theme";
"lng_settings_bg_from_gallery" = "Choose from gallery";
"lng_settings_bg_from_file" = "Choose from file";
"lng_settings_bg_edit_theme" = "Launch theme editor";
"lng_settings_bg_create_theme" = "Create new theme";
"lng_settings_bg_theme_edit" = "Edit theme";
"lng_settings_bg_theme_create" = "Create new theme";
"lng_settings_bg_cloud_themes" = "Custom themes";
"lng_settings_bg_show_all" = "Show all themes";
"lng_settings_bg_tile" = "Tile background";

View File

@ -1084,8 +1084,7 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
base::ObservableViewer(
*Window::Theme::Background()
) | rpl::filter([](const Update &update) {
return (update.type == Update::Type::ApplyingTheme
|| update.type == Update::Type::New);
return (update.type == Update::Type::ApplyingTheme);
}) | rpl::map([=] {
return chosen();
}) | rpl::start_with_next([=](Type type) {
@ -1149,6 +1148,8 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
void SetupThemeOptions(
not_null<Window::SessionController*> controller,
not_null<Ui::VerticalLayout*> container) {
using namespace Window::Theme;
AddSkip(container, st::settingsPrivacySkip);
AddSubsectionTitle(container, tr::lng_settings_themes());
@ -1156,20 +1157,38 @@ void SetupThemeOptions(
AddSkip(container, st::settingsThemesTopSkip);
SetupDefaultThemes(container);
AddSkip(container, st::settingsThemesBottomSkip);
auto canEdit = rpl::single(false);
const auto canEditCurrent = [=] {
const auto userId = controller->session().userId();
return (Background()->themeObject().cloud.createdBy == userId);
};
auto canEdit = rpl::single(BackgroundUpdate(
BackgroundUpdate::Type::ApplyingTheme,
Background()->tile()
)) | rpl::then(base::ObservableViewer(
*Background()
)) | rpl::filter([](const BackgroundUpdate &update) {
return (update.type == BackgroundUpdate::Type::ApplyingTheme);
}) | rpl::map([=] {
return canEditCurrent();
});
AddButton(
container,
rpl::conditional(
std::move(canEdit),
tr::lng_settings_bg_edit_theme(),
tr::lng_settings_bg_create_theme()),
tr::lng_settings_bg_theme_edit(),
tr::lng_settings_bg_theme_create()),
st::settingsChatButton,
&st::settingsIconThemes,
st::settingsChatIconLeft
)->addClickHandler([=] {
controller->window().show(Box(
Window::Theme::CreateBox,
&controller->window()));
if (canEditCurrent()) {
StartEditor(
&controller->window(),
Background()->themeObject().cloud);
} else {
controller->window().show(Box(CreateBox, &controller->window()));
}
});
AddSkip(container);

View File

@ -4201,21 +4201,17 @@ Window::Theme::Saved readThemeUsingKey(FileKey key) {
auto &cache = result.cache;
theme.stream >> object.content;
theme.stream >> tag >> object.pathAbsolute;
const auto isCloud = (object.pathAbsolute == kThemePathAbsoluteCloud);
if (tag == kThemeNewPathRelativeTag) {
if (isCloud) {
auto creator = qint32();
theme.stream
>> object.cloud.id
>> object.cloud.accessHash
>> object.cloud.slug
>> object.cloud.title
>> object.cloud.documentId
>> creator;
object.cloud.createdBy = creator;
} else {
theme.stream >> object.pathRelative;
}
auto creator = qint32();
theme.stream
>> object.pathRelative
>> object.cloud.id
>> object.cloud.accessHash
>> object.cloud.slug
>> object.cloud.title
>> object.cloud.documentId
>> creator;
object.cloud.createdBy = creator;
} else {
object.pathRelative = tag;
}
@ -4224,7 +4220,7 @@ Window::Theme::Saved readThemeUsingKey(FileKey key) {
}
auto ignoreCache = false;
if (!isCloud) {
if (!object.cloud.id) {
QFile file(object.pathRelative);
if (object.pathRelative.isEmpty() || !file.exists()) {
file.setFileName(object.pathAbsolute);
@ -4299,33 +4295,30 @@ void writeTheme(const Window::Theme::Saved &saved) {
const auto &object = saved.object;
const auto &cache = saved.cache;
const auto tag = QString(kThemeNewPathRelativeTag);
const auto isCloud = (saved.object.pathAbsolute == kThemePathAbsoluteCloud);
quint32 size = Serialize::bytearraySize(object.content);
size += Serialize::stringSize(tag) + Serialize::stringSize(object.pathAbsolute);
if (isCloud) {
size += sizeof(uint64) * 3
+ Serialize::stringSize(object.cloud.slug)
+ Serialize::stringSize(object.cloud.title)
+ sizeof(qint32);
} else {
size += Serialize::stringSize(object.pathRelative);
}
size += sizeof(int32) * 2 + Serialize::bytearraySize(cache.colors) + Serialize::bytearraySize(cache.background) + sizeof(quint32);
quint32 size = Serialize::bytearraySize(object.content)
+ Serialize::stringSize(tag)
+ Serialize::stringSize(object.pathAbsolute)
+ Serialize::stringSize(object.pathRelative)
+ sizeof(uint64) * 3
+ Serialize::stringSize(object.cloud.slug)
+ Serialize::stringSize(object.cloud.title)
+ sizeof(qint32)
+ sizeof(qint32) * 2
+ Serialize::bytearraySize(cache.colors)
+ Serialize::bytearraySize(cache.background)
+ sizeof(quint32);
EncryptedDescriptor data(size);
data.stream << object.content;
data.stream << tag << object.pathAbsolute;
if (isCloud) {
data.stream
<< object.cloud.id
<< object.cloud.accessHash
<< object.cloud.slug
<< object.cloud.title
<< object.cloud.documentId
<< qint32(object.cloud.createdBy);
} else {
data.stream << object.pathRelative;
}
data.stream
<< object.content
<< tag
<< object.pathAbsolute
<< object.pathRelative
<< object.cloud.id
<< object.cloud.accessHash
<< object.cloud.slug
<< object.cloud.title
<< object.cloud.documentId
<< qint32(object.cloud.createdBy)
<< cache.paletteChecksum
<< cache.contentChecksum
<< cache.colors

View File

@ -413,7 +413,7 @@ Checkbox::Checkbox(
text,
_checkboxOptions,
countTextMinWidth()) {
_check->setUpdateCallback([=] { updateCheck(); });
_check->setUpdateCallback([=] { update(); });
resizeToText();
setCursor(style::cur_pointer);
}

View File

@ -590,8 +590,8 @@ void MainWindow::reActivateWindow() {
}
void MainWindow::showRightColumn(object_ptr<TWidget> widget) {
auto wasWidth = width();
auto wasRightWidth = _rightColumn ? _rightColumn->width() : 0;
const auto wasWidth = width();
const auto wasRightWidth = _rightColumn ? _rightColumn->width() : 0;
_rightColumn = std::move(widget);
if (_rightColumn) {
_rightColumn->setParent(this);
@ -600,13 +600,14 @@ void MainWindow::showRightColumn(object_ptr<TWidget> widget) {
} else if (App::wnd()) {
App::wnd()->setInnerFocus();
}
auto nowRightWidth = _rightColumn ? _rightColumn->width() : 0;
setMinimumWidth(st::windowMinWidth + nowRightWidth);
const auto nowRightWidth = _rightColumn ? _rightColumn->width() : 0;
const auto wasMaximized = isMaximized();
if (!isMaximized()) {
tryToExtendWidthBy(wasWidth + nowRightWidth - wasRightWidth - width());
} else {
updateControlsGeometry();
}
setMinimumWidth(st::windowMinWidth + nowRightWidth);
}
int MainWindow::maximalExtendBy() const {

View File

@ -1065,8 +1065,10 @@ void Unload() {
GlobalApplying = Applying();
}
bool Apply(const QString &filepath) {
if (auto preview = PreviewFromFile(filepath, {}, {})) {
bool Apply(
const QString &filepath,
const Data::CloudTheme &cloud) {
if (auto preview = PreviewFromFile(filepath, {}, cloud)) {
return Apply(std::move(preview));
}
return false;

View File

@ -18,7 +18,6 @@ namespace Window {
namespace Theme {
inline constexpr auto kThemeSchemeSizeLimit = 1024 * 1024;
inline const auto kThemePathAbsoluteCloud = qstr("special://cloud");
struct Object {
QString pathRelative;
@ -53,7 +52,9 @@ struct Preview {
QImage preview;
};
bool Apply(const QString &filepath);
bool Apply(
const QString &filepath,
const Data::CloudTheme &cloud = Data::CloudTheme());
bool Apply(std::unique_ptr<Preview> preview);
void ApplyDefaultWithPath(const QString &themePath);
bool ApplyEditedPalette(const QString &path, const QByteArray &content);

View File

@ -262,21 +262,6 @@ void WriteDefaultPalette(const QString &path) {
}
}
void StartEditor(
not_null<Window::Controller*> window,
const QString &title) {
const auto path = EditingPalettePath();
if (!Local::copyThemeColorsToPalette(path)) {
WriteDefaultPalette(path);
}
if (!Apply(path)) {
window->show(Box<InformBox>(tr::lng_theme_editor_error(tr::now)));
return;
}
KeepApplied();
window->showRightColumn(Box<Editor>(window));
}
[[nodiscard]] QString GenerateSlug() {
const auto letters = uint8('Z' + 1 - 'A');
const auto digits = uint8('9' + 1 - '0');
@ -500,6 +485,21 @@ Fn<void()> SaveTheme(
} // namespace
void StartEditor(
not_null<Window::Controller*> window,
const Data::CloudTheme &cloud) {
const auto path = EditingPalettePath();
if (!Local::copyThemeColorsToPalette(path)) {
WriteDefaultPalette(path);
}
if (!Apply(path, cloud)) {
window->show(Box<InformBox>(tr::lng_theme_editor_error(tr::now)));
return;
}
KeepApplied();
window->showRightColumn(Box<Editor>(window));
}
void CreateBox(
not_null<GenericBox*> box,
not_null<Window::Controller*> window) {
@ -542,7 +542,9 @@ void CreateBox(
return;
}
box->closeBox();
StartEditor(window, title);
auto cloud = Data::CloudTheme();
cloud.title = title;
StartEditor(window, cloud);
};
Ui::Connect(name, &Ui::InputField::submitted, done);
box->addButton(tr::lng_box_done(), done);

View File

@ -9,12 +9,19 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/generic_box.h"
namespace Data {
struct CloudTheme;
} // namespace Data
namespace Window {
class Controller;
namespace Theme {
void StartEditor(
not_null<Window::Controller*> window,
const Data::CloudTheme &cloud);
void CreateBox(
not_null<GenericBox*> box,
not_null<Window::Controller*> window);

View File

@ -915,17 +915,12 @@ std::unique_ptr<Preview> PreviewFromFile(
auto result = std::make_unique<Preview>();
auto &object = result->object;
object.cloud = cloud;
if (cloud.documentId || filepath.isEmpty()) {
object.pathRelative = QString();
object.pathAbsolute = QString(kThemePathAbsoluteCloud);
} else {
object.pathRelative = filepath.isEmpty()
? QString()
: QDir().relativeFilePath(filepath);
object.pathAbsolute = filepath.isEmpty()
? QString()
: QFileInfo(filepath).absoluteFilePath();
}
object.pathRelative = filepath.isEmpty()
? QString()
: QDir().relativeFilePath(filepath);
object.pathAbsolute = filepath.isEmpty()
? QString()
: QFileInfo(filepath).absoluteFilePath();
if (bytes.isEmpty()) {
if (!LoadFromFile(filepath, &result->instance, &object.content)) {
return nullptr;

View File

@ -154,13 +154,13 @@ void CloudList::setup() {
_window->session().data().cloudThemes().updated()
);
auto themeChanges = rpl::single(
BackgroundUpdate(BackgroundUpdate::Type::New, Background()->tile())
) | rpl::then(base::ObservableViewer(
auto themeChanges = rpl::single(BackgroundUpdate(
BackgroundUpdate::Type::ApplyingTheme,
Background()->tile()
)) | rpl::then(base::ObservableViewer(
*Background()
)) | rpl::filter([](const BackgroundUpdate &update) {
return (update.type == BackgroundUpdate::Type::ApplyingTheme)
|| (update.type == BackgroundUpdate::Type::New);
return (update.type == BackgroundUpdate::Type::ApplyingTheme);
});
rpl::combine(