mirror of
https://github.com/vale981/tdesktop
synced 2025-03-05 17:51:41 -05:00
Apply cloud themes.
This commit is contained in:
parent
ac8f924909
commit
4929de2bfb
12 changed files with 280 additions and 152 deletions
|
@ -8,11 +8,28 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_cloud_themes.h"
|
#include "data/data_cloud_themes.h"
|
||||||
|
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
|
#include "data/data_document.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
||||||
|
CloudTheme CloudTheme::Parse(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
const MTPDtheme &data) {
|
||||||
|
const auto document = data.vdocument();
|
||||||
|
return {
|
||||||
|
data.vid().v,
|
||||||
|
data.vaccess_hash().v,
|
||||||
|
qs(data.vslug()),
|
||||||
|
qs(data.vtitle()),
|
||||||
|
(document
|
||||||
|
? session->data().processDocument(*document)->id
|
||||||
|
: DocumentId(0)),
|
||||||
|
data.is_creator() ? session->userId() : UserId(0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
QString CloudThemes::Format() {
|
QString CloudThemes::Format() {
|
||||||
static const auto kResult = QString::fromLatin1("tdesktop");
|
static const auto kResult = QString::fromLatin1("tdesktop");
|
||||||
return kResult;
|
return kResult;
|
||||||
|
@ -46,17 +63,7 @@ void CloudThemes::parseThemes(const QVector<MTPTheme> &list) {
|
||||||
_list.reserve(list.size());
|
_list.reserve(list.size());
|
||||||
for (const auto &theme : list) {
|
for (const auto &theme : list) {
|
||||||
theme.match([&](const MTPDtheme &data) {
|
theme.match([&](const MTPDtheme &data) {
|
||||||
const auto document = data.vdocument();
|
_list.push_back(CloudTheme::Parse(_session, data));
|
||||||
_list.push_back({
|
|
||||||
data.vid().v,
|
|
||||||
data.vaccess_hash().v,
|
|
||||||
qs(data.vslug()),
|
|
||||||
qs(data.vtitle()),
|
|
||||||
(document
|
|
||||||
? _session->data().processDocument(*document).get()
|
|
||||||
: nullptr),
|
|
||||||
data.is_creator()
|
|
||||||
});
|
|
||||||
}, [&](const MTPDthemeDocumentNotModified &data) {
|
}, [&](const MTPDthemeDocumentNotModified &data) {
|
||||||
LOG(("API Error: Unexpected themeDocumentNotModified."));
|
LOG(("API Error: Unexpected themeDocumentNotModified."));
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,8 +18,12 @@ struct CloudTheme {
|
||||||
uint64 accessHash = 0;
|
uint64 accessHash = 0;
|
||||||
QString slug;
|
QString slug;
|
||||||
QString title;
|
QString title;
|
||||||
DocumentData *document = nullptr;
|
DocumentId documentId = 0;
|
||||||
bool creator = false;
|
UserId createdBy = 0;
|
||||||
|
|
||||||
|
static CloudTheme Parse(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
const MTPDtheme &data);
|
||||||
};
|
};
|
||||||
|
|
||||||
class CloudThemes final {
|
class CloudThemes final {
|
||||||
|
|
|
@ -318,7 +318,7 @@ void DocumentOpenClickHandler::Open(
|
||||||
LaunchWithWarning(location.name(), context);
|
LaunchWithWarning(location.name(), context);
|
||||||
};
|
};
|
||||||
const auto &location = data->location(true);
|
const auto &location = data->location(true);
|
||||||
if (data->isTheme() && !location.isEmpty() && location.accessEnable()) {
|
if (data->isTheme() && data->loaded(DocumentData::FilePathResolve::Checked)) {
|
||||||
Core::App().showDocument(data, context);
|
Core::App().showDocument(data, context);
|
||||||
location.accessDisable();
|
location.accessDisable();
|
||||||
} else if (data->canBePlayed()) {
|
} else if (data->canBePlayed()) {
|
||||||
|
|
|
@ -2192,8 +2192,10 @@ void OverlayWidget::playbackWaitingChange(bool waiting) {
|
||||||
void OverlayWidget::initThemePreview() {
|
void OverlayWidget::initThemePreview() {
|
||||||
Assert(_doc && _doc->isTheme());
|
Assert(_doc && _doc->isTheme());
|
||||||
|
|
||||||
|
const auto bytes = _doc->data();
|
||||||
auto &location = _doc->location();
|
auto &location = _doc->location();
|
||||||
if (location.isEmpty() || !location.accessEnable()) {
|
if (bytes.isEmpty()
|
||||||
|
&& (location.isEmpty() || !location.accessEnable())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_themePreviewShown = true;
|
_themePreviewShown = true;
|
||||||
|
@ -2203,12 +2205,21 @@ void OverlayWidget::initThemePreview() {
|
||||||
current.backgroundImage = Window::Theme::Background()->createCurrentImage();
|
current.backgroundImage = Window::Theme::Background()->createCurrentImage();
|
||||||
current.backgroundTiled = Window::Theme::Background()->tile();
|
current.backgroundTiled = Window::Theme::Background()->tile();
|
||||||
|
|
||||||
|
const auto &cloudList = _doc->session().data().cloudThemes().list();
|
||||||
|
const auto i = ranges::find(
|
||||||
|
cloudList,
|
||||||
|
_doc->id,
|
||||||
|
&Data::CloudTheme::documentId);
|
||||||
|
const auto cloud = (i != end(cloudList)) ? *i : Data::CloudTheme();
|
||||||
|
|
||||||
const auto path = _doc->location().name();
|
const auto path = _doc->location().name();
|
||||||
const auto id = _themePreviewId = rand_value<uint64>();
|
const auto id = _themePreviewId = rand_value<uint64>();
|
||||||
const auto weak = make_weak(this);
|
const auto weak = make_weak(this);
|
||||||
crl::async([=, data = std::move(current)]() mutable {
|
crl::async([=, data = std::move(current)]() mutable {
|
||||||
auto preview = Window::Theme::GeneratePreview(
|
auto preview = Window::Theme::GeneratePreview(
|
||||||
path,
|
path,
|
||||||
|
bytes,
|
||||||
|
cloud,
|
||||||
std::move(data));
|
std::move(data));
|
||||||
crl::on_main(weak, [=, result = std::move(preview)]() mutable {
|
crl::on_main(weak, [=, result = std::move(preview)]() mutable {
|
||||||
if (id != _themePreviewId) {
|
if (id != _themePreviewId) {
|
||||||
|
|
|
@ -998,9 +998,9 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
|
||||||
container.get());
|
container.get());
|
||||||
|
|
||||||
const auto chosen = [] {
|
const auto chosen = [] {
|
||||||
const auto path = Window::Theme::Background()->themeAbsolutePath();
|
const auto &object = Window::Theme::Background()->themeObject();
|
||||||
for (const auto &scheme : kSchemesList) {
|
for (const auto &scheme : kSchemesList) {
|
||||||
if (path == scheme.path) {
|
if (object.pathAbsolute == scheme.path) {
|
||||||
return scheme.type;
|
return scheme.type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1013,7 +1013,8 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
|
||||||
const auto type = scheme.type;
|
const auto type = scheme.type;
|
||||||
return (type != Type::DayBlue) && (type != Type::Default);
|
return (type != Type::DayBlue) && (type != Type::Default);
|
||||||
};
|
};
|
||||||
const auto currentlyIsCustom = (chosen() == Type(-1));
|
const auto currentlyIsCustom = (chosen() == Type(-1))
|
||||||
|
&& !Window::Theme::Background()->themeObject().cloud.id;
|
||||||
if (Window::Theme::IsNightMode() == isNight(scheme)) {
|
if (Window::Theme::IsNightMode() == isNight(scheme)) {
|
||||||
Window::Theme::ApplyDefaultWithPath(scheme.path);
|
Window::Theme::ApplyDefaultWithPath(scheme.path);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -67,6 +67,8 @@ constexpr auto kStickersVersionTag = quint32(-1);
|
||||||
constexpr auto kStickersSerializeVersion = 1;
|
constexpr auto kStickersSerializeVersion = 1;
|
||||||
constexpr auto kMaxSavedStickerSetsCount = 1000;
|
constexpr auto kMaxSavedStickerSetsCount = 1000;
|
||||||
|
|
||||||
|
const auto kThemeNewPathRelativeTag = qstr("special://new_tag");
|
||||||
|
|
||||||
using Database = Storage::Cache::Database;
|
using Database = Storage::Cache::Database;
|
||||||
using FileKey = quint64;
|
using FileKey = quint64;
|
||||||
|
|
||||||
|
@ -4182,50 +4184,74 @@ bool readBackground() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::Theme::Saved readThemeUsingKey(FileKey key) {
|
Window::Theme::Saved readThemeUsingKey(FileKey key) {
|
||||||
|
using namespace Window::Theme;
|
||||||
|
|
||||||
FileReadDescriptor theme;
|
FileReadDescriptor theme;
|
||||||
if (!readEncryptedFile(theme, key, FileOption::Safe, SettingsKey)) {
|
if (!readEncryptedFile(theme, key, FileOption::Safe, SettingsKey)) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = Window::Theme::Saved();
|
auto tag = QString();
|
||||||
theme.stream >> result.content;
|
auto result = Saved();
|
||||||
theme.stream >> result.pathRelative >> result.pathAbsolute;
|
auto &object = result.object;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
object.pathRelative = tag;
|
||||||
|
}
|
||||||
if (theme.stream.status() != QDataStream::Ok) {
|
if (theme.stream.status() != QDataStream::Ok) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QFile file(result.pathRelative);
|
auto ignoreCache = false;
|
||||||
if (result.pathRelative.isEmpty() || !file.exists()) {
|
if (!isCloud) {
|
||||||
file.setFileName(result.pathAbsolute);
|
QFile file(object.pathRelative);
|
||||||
}
|
if (object.pathRelative.isEmpty() || !file.exists()) {
|
||||||
|
file.setFileName(object.pathAbsolute);
|
||||||
auto changed = false;
|
|
||||||
if (!file.fileName().isEmpty()
|
|
||||||
&& file.exists()
|
|
||||||
&& file.open(QIODevice::ReadOnly)) {
|
|
||||||
if (file.size() > kThemeFileSizeLimit) {
|
|
||||||
LOG(("Error: theme file too large: %1 "
|
|
||||||
"(should be less than 5 MB, got %2)"
|
|
||||||
).arg(file.fileName()
|
|
||||||
).arg(file.size()));
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
auto fileContent = file.readAll();
|
if (!file.fileName().isEmpty()
|
||||||
file.close();
|
&& file.exists()
|
||||||
if (result.content != fileContent) {
|
&& file.open(QIODevice::ReadOnly)) {
|
||||||
result.content = fileContent;
|
if (file.size() > kThemeFileSizeLimit) {
|
||||||
changed = true;
|
LOG(("Error: theme file too large: %1 "
|
||||||
|
"(should be less than 5 MB, got %2)"
|
||||||
|
).arg(file.fileName()
|
||||||
|
).arg(file.size()));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
auto fileContent = file.readAll();
|
||||||
|
file.close();
|
||||||
|
if (object.content != fileContent) {
|
||||||
|
object.content = fileContent;
|
||||||
|
ignoreCache = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!changed) {
|
if (!ignoreCache) {
|
||||||
quint32 backgroundIsTiled = 0;
|
quint32 backgroundIsTiled = 0;
|
||||||
theme.stream
|
theme.stream
|
||||||
>> result.cache.paletteChecksum
|
>> cache.paletteChecksum
|
||||||
>> result.cache.contentChecksum
|
>> cache.contentChecksum
|
||||||
>> result.cache.colors
|
>> cache.colors
|
||||||
>> result.cache.background
|
>> cache.background
|
||||||
>> backgroundIsTiled;
|
>> backgroundIsTiled;
|
||||||
result.cache.tiled = (backgroundIsTiled == 1);
|
cache.tiled = (backgroundIsTiled == 1);
|
||||||
if (theme.stream.status() != QDataStream::Ok) {
|
if (theme.stream.status() != QDataStream::Ok) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -4235,20 +4261,24 @@ Window::Theme::Saved readThemeUsingKey(FileKey key) {
|
||||||
|
|
||||||
QString loadThemeUsingKey(FileKey key) {
|
QString loadThemeUsingKey(FileKey key) {
|
||||||
auto read = readThemeUsingKey(key);
|
auto read = readThemeUsingKey(key);
|
||||||
const auto result = read.pathAbsolute;
|
const auto result = read.object.pathAbsolute;
|
||||||
return (!read.content.isEmpty() && Window::Theme::Load(std::move(read)))
|
if (read.object.content.isEmpty()
|
||||||
? result
|
|| !Window::Theme::Load(std::move(read))) {
|
||||||
: QString();
|
return QString();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeTheme(const Window::Theme::Saved &saved) {
|
void writeTheme(const Window::Theme::Saved &saved) {
|
||||||
|
using namespace Window::Theme;
|
||||||
|
|
||||||
if (_themeKeyLegacy) {
|
if (_themeKeyLegacy) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto &themeKey = Window::Theme::IsNightMode()
|
auto &themeKey = IsNightMode()
|
||||||
? _themeKeyNight
|
? _themeKeyNight
|
||||||
: _themeKeyDay;
|
: _themeKeyDay;
|
||||||
if (saved.content.isEmpty()) {
|
if (saved.object.content.isEmpty()) {
|
||||||
if (themeKey) {
|
if (themeKey) {
|
||||||
clearKey(themeKey);
|
clearKey(themeKey);
|
||||||
themeKey = 0;
|
themeKey = 0;
|
||||||
|
@ -4262,14 +4292,41 @@ void writeTheme(const Window::Theme::Saved &saved) {
|
||||||
writeSettings();
|
writeSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto backgroundTiled = static_cast<quint32>(saved.cache.tiled ? 1 : 0);
|
const auto &object = saved.object;
|
||||||
quint32 size = Serialize::bytearraySize(saved.content);
|
const auto &cache = saved.cache;
|
||||||
size += Serialize::stringSize(saved.pathRelative) + Serialize::stringSize(saved.pathAbsolute);
|
const auto tag = QString(kThemeNewPathRelativeTag);
|
||||||
size += sizeof(int32) * 2 + Serialize::bytearraySize(saved.cache.colors) + Serialize::bytearraySize(saved.cache.background) + sizeof(quint32);
|
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);
|
||||||
EncryptedDescriptor data(size);
|
EncryptedDescriptor data(size);
|
||||||
data.stream << saved.content;
|
data.stream << object.content;
|
||||||
data.stream << saved.pathRelative << saved.pathAbsolute;
|
data.stream << tag << object.pathAbsolute;
|
||||||
data.stream << saved.cache.paletteChecksum << saved.cache.contentChecksum << saved.cache.colors << saved.cache.background << backgroundTiled;
|
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
|
||||||
|
<< cache.paletteChecksum
|
||||||
|
<< cache.contentChecksum
|
||||||
|
<< cache.colors
|
||||||
|
<< cache.background
|
||||||
|
<< quint32(cache.tiled ? 1 : 0);
|
||||||
|
|
||||||
FileWriteDescriptor file(themeKey, FileOption::Safe);
|
FileWriteDescriptor file(themeKey, FileOption::Safe);
|
||||||
file.writeEncrypted(data, SettingsKey);
|
file.writeEncrypted(data, SettingsKey);
|
||||||
|
|
|
@ -50,8 +50,8 @@ void AbstractCheckView::setChecked(bool checked, anim::type animated) {
|
||||||
_checked ? 1. : 0.,
|
_checked ? 1. : 0.,
|
||||||
_duration);
|
_duration);
|
||||||
}
|
}
|
||||||
|
checkedChangedHook(animated);
|
||||||
if (changed) {
|
if (changed) {
|
||||||
checkedChangedHook(animated);
|
|
||||||
_checks.fire_copy(_checked);
|
_checks.fire_copy(_checked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -575,7 +575,7 @@ void Checkbox::paintEvent(QPaintEvent *e) {
|
||||||
availableTextWidth,
|
availableTextWidth,
|
||||||
width());
|
width());
|
||||||
}
|
}
|
||||||
} else {
|
} else if (_allowMultiline || _text.countHeight(width() - _st.margin.left() - _st.margin.right()) < 2 * _st.style.font->height) {
|
||||||
_text.drawLeft(
|
_text.drawLeft(
|
||||||
p,
|
p,
|
||||||
_st.margin.left(),
|
_st.margin.left(),
|
||||||
|
@ -583,6 +583,13 @@ void Checkbox::paintEvent(QPaintEvent *e) {
|
||||||
width() - _st.margin.left() - _st.margin.right(),
|
width() - _st.margin.left() - _st.margin.right(),
|
||||||
width(),
|
width(),
|
||||||
style::al_top);
|
style::al_top);
|
||||||
|
} else {
|
||||||
|
_text.drawLeftElided(
|
||||||
|
p,
|
||||||
|
_st.margin.left(),
|
||||||
|
textTop,
|
||||||
|
width() - _st.margin.left() - _st.margin.right(),
|
||||||
|
width());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -636,7 +643,9 @@ int Checkbox::resizeGetHeight(int newWidth) {
|
||||||
? (newWidth - _st.margin.left() - _st.margin.right())
|
? (newWidth - _st.margin.left() - _st.margin.right())
|
||||||
: qMax(width() - leftSkip, 1);
|
: qMax(width() - leftSkip, 1);
|
||||||
const auto textBottom = _st.textPosition.y()
|
const auto textBottom = _st.textPosition.y()
|
||||||
+ _text.countHeight(availableTextWidth);
|
+ ((centered && !_allowMultiline)
|
||||||
|
? _st.style.font->height
|
||||||
|
: _text.countHeight(availableTextWidth));
|
||||||
return std::max(result, textBottom);
|
return std::max(result, textBottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,11 +37,8 @@ constexpr auto kNightThemeFile = str_const(":/gui/night.tdesktop-theme");
|
||||||
constexpr auto kMinimumTiledSize = 512;
|
constexpr auto kMinimumTiledSize = 512;
|
||||||
|
|
||||||
struct Applying {
|
struct Applying {
|
||||||
QString pathRelative;
|
Saved data;
|
||||||
QString pathAbsolute;
|
|
||||||
QByteArray content;
|
|
||||||
QByteArray paletteForRevert;
|
QByteArray paletteForRevert;
|
||||||
Cached cached;
|
|
||||||
Fn<void()> overrideKeep;
|
Fn<void()> overrideKeep;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -383,15 +380,6 @@ QImage validateBackgroundImage(QImage image) {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteAppliedTheme() {
|
|
||||||
auto saved = Saved();
|
|
||||||
saved.pathRelative = GlobalApplying.pathRelative;
|
|
||||||
saved.pathAbsolute = GlobalApplying.pathAbsolute;
|
|
||||||
saved.content = std::move(GlobalApplying.content);
|
|
||||||
saved.cache = std::move(GlobalApplying.cached);
|
|
||||||
Local::writeTheme(saved);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClearApplying() {
|
void ClearApplying() {
|
||||||
GlobalApplying = Applying();
|
GlobalApplying = Applying();
|
||||||
}
|
}
|
||||||
|
@ -556,7 +544,7 @@ void ChatBackground::set(const Data::WallPaper &paper, QImage image) {
|
||||||
const auto needResetAdjustable = Data::IsDefaultWallPaper(paper)
|
const auto needResetAdjustable = Data::IsDefaultWallPaper(paper)
|
||||||
&& !Data::IsDefaultWallPaper(_paper)
|
&& !Data::IsDefaultWallPaper(_paper)
|
||||||
&& !nightMode()
|
&& !nightMode()
|
||||||
&& _themeAbsolutePath.isEmpty();
|
&& _themeObject.pathAbsolute.isEmpty();
|
||||||
if (Data::IsThemeWallPaper(paper) && _themeImage.isNull()) {
|
if (Data::IsThemeWallPaper(paper) && _themeImage.isNull()) {
|
||||||
setPaper(Data::DefaultWallPaper());
|
setPaper(Data::DefaultWallPaper());
|
||||||
} else {
|
} else {
|
||||||
|
@ -711,10 +699,10 @@ bool ChatBackground::adjustPaletteRequired() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatBackground::isEditingTheme() const {
|
bool ChatBackground::isEditingTheme() const {
|
||||||
const auto path = AreTestingTheme()
|
const auto &object = AreTestingTheme()
|
||||||
? GlobalApplying.pathAbsolute
|
? GlobalApplying.data.object
|
||||||
: _themeAbsolutePath;
|
: _themeObject;
|
||||||
return IsEditingTheme(path);
|
return IsEditingTheme(object.pathAbsolute);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatBackground::adjustPaletteUsingBackground(const QImage &image) {
|
void ChatBackground::adjustPaletteUsingBackground(const QImage &image) {
|
||||||
|
@ -812,12 +800,12 @@ void ChatBackground::setTileNightValue(bool tile) {
|
||||||
_tileNightValue = tile;
|
_tileNightValue = tile;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatBackground::setThemeAbsolutePath(const QString &path) {
|
void ChatBackground::setThemeObject(const Object &object) {
|
||||||
_themeAbsolutePath = path;
|
_themeObject = object;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ChatBackground::themeAbsolutePath() const {
|
const Object &ChatBackground::themeObject() const {
|
||||||
return _themeAbsolutePath;
|
return _themeObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatBackground::reset() {
|
void ChatBackground::reset() {
|
||||||
|
@ -871,7 +859,7 @@ void ChatBackground::setTestingTheme(Instance &&theme) {
|
||||||
|| Data::IsThemeWallPaper(_paper)
|
|| Data::IsThemeWallPaper(_paper)
|
||||||
|| (Data::IsDefaultWallPaper(_paper)
|
|| (Data::IsDefaultWallPaper(_paper)
|
||||||
&& !nightMode()
|
&& !nightMode()
|
||||||
&& _themeAbsolutePath.isEmpty());
|
&& _themeObject.pathAbsolute.isEmpty());
|
||||||
if (AreTestingTheme() && isEditingTheme()) {
|
if (AreTestingTheme() && isEditingTheme()) {
|
||||||
// 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
|
||||||
|
@ -905,8 +893,8 @@ void ChatBackground::setTestingDefaultTheme() {
|
||||||
notify(BackgroundUpdate(BackgroundUpdate::Type::TestingTheme, tile()), true);
|
notify(BackgroundUpdate(BackgroundUpdate::Type::TestingTheme, tile()), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatBackground::keepApplied(const QString &path, bool write) {
|
void ChatBackground::keepApplied(const Object &object, bool write) {
|
||||||
setThemeAbsolutePath(path);
|
setThemeObject(object);
|
||||||
if (Data::details::IsTestingEditorWallPaper(_paper)) {
|
if (Data::details::IsTestingEditorWallPaper(_paper)) {
|
||||||
setPaper(Data::CustomWallPaper());
|
setPaper(Data::CustomWallPaper());
|
||||||
_themeImage = QImage();
|
_themeImage = QImage();
|
||||||
|
@ -935,15 +923,15 @@ void ChatBackground::keepApplied(const QString &path, bool write) {
|
||||||
bool ChatBackground::isNonDefaultThemeOrBackground() {
|
bool ChatBackground::isNonDefaultThemeOrBackground() {
|
||||||
start();
|
start();
|
||||||
return nightMode()
|
return nightMode()
|
||||||
? (_themeAbsolutePath != NightThemePath()
|
? (_themeObject.pathAbsolute != NightThemePath()
|
||||||
|| !Data::IsThemeWallPaper(_paper))
|
|| !Data::IsThemeWallPaper(_paper))
|
||||||
: (!_themeAbsolutePath.isEmpty()
|
: (!_themeObject.pathAbsolute.isEmpty()
|
||||||
|| !Data::IsDefaultWallPaper(_paper));
|
|| !Data::IsDefaultWallPaper(_paper));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatBackground::isNonDefaultBackground() {
|
bool ChatBackground::isNonDefaultBackground() {
|
||||||
start();
|
start();
|
||||||
return _themeAbsolutePath.isEmpty()
|
return _themeObject.pathAbsolute.isEmpty()
|
||||||
? !Data::IsDefaultWallPaper(_paper)
|
? !Data::IsDefaultWallPaper(_paper)
|
||||||
: !Data::IsThemeWallPaper(_paper);
|
: !Data::IsThemeWallPaper(_paper);
|
||||||
}
|
}
|
||||||
|
@ -987,21 +975,19 @@ void ChatBackground::toggleNightMode(std::optional<QString> themePath) {
|
||||||
const auto newNightMode = !_nightMode;
|
const auto newNightMode = !_nightMode;
|
||||||
_nightMode = newNightMode;
|
_nightMode = newNightMode;
|
||||||
auto read = settingDefault ? Saved() : Local::readThemeAfterSwitch();
|
auto read = settingDefault ? Saved() : Local::readThemeAfterSwitch();
|
||||||
auto path = read.pathAbsolute;
|
auto path = read.object.pathAbsolute;
|
||||||
|
|
||||||
_nightMode = oldNightMode;
|
_nightMode = oldNightMode;
|
||||||
auto oldTileValue = (_nightMode ? _tileNightValue : _tileDayValue);
|
auto oldTileValue = (_nightMode ? _tileNightValue : _tileDayValue);
|
||||||
const auto alreadyOnDisk = [&] {
|
const auto alreadyOnDisk = [&] {
|
||||||
if (read.content.isEmpty()) {
|
if (read.object.content.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto preview = std::make_unique<Preview>();
|
auto preview = std::make_unique<Preview>();
|
||||||
preview->pathAbsolute = std::move(read.pathAbsolute);
|
preview->object = std::move(read.object);
|
||||||
preview->pathRelative = std::move(read.pathRelative);
|
|
||||||
preview->content = std::move(read.content);
|
|
||||||
preview->instance.cached = std::move(read.cache);
|
preview->instance.cached = std::move(read.cache);
|
||||||
const auto loaded = loadTheme(
|
const auto loaded = loadTheme(
|
||||||
preview->content,
|
preview->object.content,
|
||||||
preview->instance.cached,
|
preview->instance.cached,
|
||||||
ColorizerForTheme(path),
|
ColorizerForTheme(path),
|
||||||
&preview->instance);
|
&preview->instance);
|
||||||
|
@ -1026,12 +1012,13 @@ void ChatBackground::toggleNightMode(std::optional<QString> themePath) {
|
||||||
// Restore the value, it was set inside theme testing.
|
// Restore the value, it was set inside theme testing.
|
||||||
(oldNightMode ? _tileNightValue : _tileDayValue) = oldTileValue;
|
(oldNightMode ? _tileNightValue : _tileDayValue) = oldTileValue;
|
||||||
|
|
||||||
|
const auto saved = std::move(GlobalApplying.data);
|
||||||
if (!alreadyOnDisk) {
|
if (!alreadyOnDisk) {
|
||||||
// First-time switch to default night mode should write it.
|
// First-time switch to default night mode should write it.
|
||||||
WriteAppliedTheme();
|
Local::writeTheme(saved);
|
||||||
}
|
}
|
||||||
ClearApplying();
|
ClearApplying();
|
||||||
keepApplied(path, settingDefault);
|
keepApplied(saved.object, settingDefault);
|
||||||
if (tile() != _tileForRevert) {
|
if (tile() != _tileForRevert) {
|
||||||
Local::writeUserSettings();
|
Local::writeUserSettings();
|
||||||
}
|
}
|
||||||
|
@ -1049,25 +1036,25 @@ ChatBackground *Background() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Load(Saved &&saved) {
|
bool Load(Saved &&saved) {
|
||||||
if (saved.content.size() < 4) {
|
if (saved.object.content.size() < 4) {
|
||||||
LOG(("Theme Error: Could not load theme from '%1' (%2)"
|
LOG(("Theme Error: Could not load theme from '%1' (%2)"
|
||||||
).arg(saved.pathRelative
|
).arg(saved.object.pathRelative
|
||||||
).arg(saved.pathAbsolute));
|
).arg(saved.object.pathAbsolute));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalBackground.createIfNull();
|
GlobalBackground.createIfNull();
|
||||||
if (loadThemeFromCache(saved.content, saved.cache)) {
|
if (loadThemeFromCache(saved.object.content, saved.cache)) {
|
||||||
Background()->setThemeAbsolutePath(saved.pathAbsolute);
|
Background()->setThemeObject(saved.object);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto colorizer = ColorizerForTheme(saved.pathAbsolute);
|
const auto colorizer = ColorizerForTheme(saved.object.pathAbsolute);
|
||||||
if (!loadTheme(saved.content, saved.cache, colorizer)) {
|
if (!loadTheme(saved.object.content, saved.cache, colorizer)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Local::writeTheme(saved);
|
Local::writeTheme(saved);
|
||||||
Background()->setThemeAbsolutePath(saved.pathAbsolute);
|
Background()->setThemeObject(saved.object);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1077,17 +1064,15 @@ void Unload() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Apply(const QString &filepath) {
|
bool Apply(const QString &filepath) {
|
||||||
if (auto preview = PreviewFromFile(filepath)) {
|
if (auto preview = PreviewFromFile(filepath, {}, {})) {
|
||||||
return Apply(std::move(preview));
|
return Apply(std::move(preview));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Apply(std::unique_ptr<Preview> preview) {
|
bool Apply(std::unique_ptr<Preview> preview) {
|
||||||
GlobalApplying.pathRelative = std::move(preview->pathRelative);
|
GlobalApplying.data.object = std::move(preview->object);
|
||||||
GlobalApplying.pathAbsolute = std::move(preview->pathAbsolute);
|
GlobalApplying.data.cache = std::move(preview->instance.cached);
|
||||||
GlobalApplying.content = std::move(preview->content);
|
|
||||||
GlobalApplying.cached = std::move(preview->instance.cached);
|
|
||||||
if (GlobalApplying.paletteForRevert.isEmpty()) {
|
if (GlobalApplying.paletteForRevert.isEmpty()) {
|
||||||
GlobalApplying.paletteForRevert = style::main_palette::save();
|
GlobalApplying.paletteForRevert = style::main_palette::save();
|
||||||
}
|
}
|
||||||
|
@ -1097,14 +1082,11 @@ bool Apply(std::unique_ptr<Preview> preview) {
|
||||||
|
|
||||||
void ApplyDefaultWithPath(const QString &themePath) {
|
void ApplyDefaultWithPath(const QString &themePath) {
|
||||||
if (!themePath.isEmpty()) {
|
if (!themePath.isEmpty()) {
|
||||||
if (auto preview = PreviewFromFile(themePath)) {
|
if (auto preview = PreviewFromFile(themePath, {}, {})) {
|
||||||
Apply(std::move(preview));
|
Apply(std::move(preview));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GlobalApplying.pathRelative = QString();
|
GlobalApplying.data = Saved();
|
||||||
GlobalApplying.pathAbsolute = QString();
|
|
||||||
GlobalApplying.content = QByteArray();
|
|
||||||
GlobalApplying.cached = Cached();
|
|
||||||
if (GlobalApplying.paletteForRevert.isEmpty()) {
|
if (GlobalApplying.paletteForRevert.isEmpty()) {
|
||||||
GlobalApplying.paletteForRevert = style::main_palette::save();
|
GlobalApplying.paletteForRevert = style::main_palette::save();
|
||||||
}
|
}
|
||||||
|
@ -1123,14 +1105,14 @@ bool ApplyEditedPalette(const QString &path, const QByteArray &content) {
|
||||||
content.constData(),
|
content.constData(),
|
||||||
content.size());
|
content.size());
|
||||||
|
|
||||||
GlobalApplying.pathRelative = path.isEmpty()
|
GlobalApplying.data.object.pathRelative = path.isEmpty()
|
||||||
? QString()
|
? QString()
|
||||||
: QDir().relativeFilePath(path);
|
: QDir().relativeFilePath(path);
|
||||||
GlobalApplying.pathAbsolute = path.isEmpty()
|
GlobalApplying.data.object.pathAbsolute = path.isEmpty()
|
||||||
? QString()
|
? QString()
|
||||||
: QFileInfo(path).absoluteFilePath();
|
: QFileInfo(path).absoluteFilePath();
|
||||||
GlobalApplying.content = content;
|
GlobalApplying.data.object.content = content;
|
||||||
GlobalApplying.cached = out.cached;
|
GlobalApplying.data.cache = out.cached;
|
||||||
if (GlobalApplying.paletteForRevert.isEmpty()) {
|
if (GlobalApplying.paletteForRevert.isEmpty()) {
|
||||||
GlobalApplying.paletteForRevert = style::main_palette::save();
|
GlobalApplying.paletteForRevert = style::main_palette::save();
|
||||||
}
|
}
|
||||||
|
@ -1150,10 +1132,10 @@ void KeepApplied() {
|
||||||
onstack();
|
onstack();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto path = GlobalApplying.pathAbsolute;
|
const auto saved = std::move(GlobalApplying.data);
|
||||||
WriteAppliedTheme();
|
Local::writeTheme(saved);
|
||||||
ClearApplying();
|
ClearApplying();
|
||||||
Background()->keepApplied(path, true);
|
Background()->keepApplied(saved.object, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Revert() {
|
void Revert() {
|
||||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "data/data_wall_paper.h"
|
#include "data/data_wall_paper.h"
|
||||||
|
#include "data/data_cloud_themes.h"
|
||||||
|
|
||||||
namespace Main {
|
namespace Main {
|
||||||
class Session;
|
class Session;
|
||||||
|
@ -16,8 +17,15 @@ class Session;
|
||||||
namespace Window {
|
namespace Window {
|
||||||
namespace Theme {
|
namespace Theme {
|
||||||
|
|
||||||
constexpr auto kThemeSchemeSizeLimit = 1024 * 1024;
|
inline constexpr auto kThemeSchemeSizeLimit = 1024 * 1024;
|
||||||
|
inline const auto kThemePathAbsoluteCloud = qstr("special://cloud");
|
||||||
|
|
||||||
|
struct Object {
|
||||||
|
QString pathRelative;
|
||||||
|
QString pathAbsolute;
|
||||||
|
QByteArray content;
|
||||||
|
Data::CloudTheme cloud;
|
||||||
|
};
|
||||||
struct Cached {
|
struct Cached {
|
||||||
QByteArray colors;
|
QByteArray colors;
|
||||||
QByteArray background;
|
QByteArray background;
|
||||||
|
@ -26,9 +34,7 @@ struct Cached {
|
||||||
int32 contentChecksum = 0;
|
int32 contentChecksum = 0;
|
||||||
};
|
};
|
||||||
struct Saved {
|
struct Saved {
|
||||||
QString pathRelative;
|
Object object;
|
||||||
QString pathAbsolute;
|
|
||||||
QByteArray content;
|
|
||||||
Cached cache;
|
Cached cache;
|
||||||
};
|
};
|
||||||
bool Load(Saved &&saved);
|
bool Load(Saved &&saved);
|
||||||
|
@ -42,10 +48,8 @@ struct Instance {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Preview {
|
struct Preview {
|
||||||
QString pathRelative;
|
Object object;
|
||||||
QString pathAbsolute;
|
|
||||||
Instance instance;
|
Instance instance;
|
||||||
QByteArray content;
|
|
||||||
QImage preview;
|
QImage preview;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -107,8 +111,8 @@ public:
|
||||||
void setTile(bool tile);
|
void setTile(bool tile);
|
||||||
void setTileDayValue(bool tile);
|
void setTileDayValue(bool tile);
|
||||||
void setTileNightValue(bool tile);
|
void setTileNightValue(bool tile);
|
||||||
void setThemeAbsolutePath(const QString &path);
|
void setThemeObject(const Object &object);
|
||||||
[[nodiscard]] QString themeAbsolutePath() const;
|
[[nodiscard]] const Object &themeObject() const;
|
||||||
[[nodiscard]] bool isEditingTheme() const;
|
[[nodiscard]] bool isEditingTheme() const;
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
@ -159,7 +163,7 @@ private:
|
||||||
void setNightModeValue(bool nightMode);
|
void setNightModeValue(bool nightMode);
|
||||||
[[nodiscard]] bool nightMode() const;
|
[[nodiscard]] bool nightMode() const;
|
||||||
void toggleNightMode(std::optional<QString> themePath);
|
void toggleNightMode(std::optional<QString> themePath);
|
||||||
void keepApplied(const QString &path, bool write);
|
void keepApplied(const Object &object, bool write);
|
||||||
[[nodiscard]] bool isNonDefaultThemeOrBackground();
|
[[nodiscard]] bool isNonDefaultThemeOrBackground();
|
||||||
[[nodiscard]] bool isNonDefaultBackground();
|
[[nodiscard]] bool isNonDefaultBackground();
|
||||||
void checkUploadWallPaper();
|
void checkUploadWallPaper();
|
||||||
|
@ -183,7 +187,7 @@ private:
|
||||||
|
|
||||||
bool _isMonoColorImage = false;
|
bool _isMonoColorImage = false;
|
||||||
|
|
||||||
QString _themeAbsolutePath;
|
Object _themeObject;
|
||||||
QImage _themeImage;
|
QImage _themeImage;
|
||||||
bool _themeTile = false;
|
bool _themeTile = false;
|
||||||
|
|
||||||
|
|
|
@ -908,24 +908,42 @@ void Generator::restoreTextPalette() {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
std::unique_ptr<Preview> PreviewFromFile(const QString &filepath) {
|
std::unique_ptr<Preview> PreviewFromFile(
|
||||||
|
const QString &filepath,
|
||||||
|
const QByteArray &bytes,
|
||||||
|
const Data::CloudTheme &cloud) {
|
||||||
auto result = std::make_unique<Preview>();
|
auto result = std::make_unique<Preview>();
|
||||||
result->pathRelative = filepath.isEmpty()
|
auto &object = result->object;
|
||||||
? QString()
|
object.cloud = cloud;
|
||||||
: QDir().relativeFilePath(filepath);
|
if (cloud.documentId || filepath.isEmpty()) {
|
||||||
result->pathAbsolute = filepath.isEmpty()
|
object.pathRelative = QString();
|
||||||
? QString()
|
object.pathAbsolute = QString(kThemePathAbsoluteCloud);
|
||||||
: QFileInfo(filepath).absoluteFilePath();
|
} else {
|
||||||
if (!LoadFromFile(filepath, &result->instance, &result->content)) {
|
object.pathRelative = filepath.isEmpty()
|
||||||
return nullptr;
|
? QString()
|
||||||
|
: QDir().relativeFilePath(filepath);
|
||||||
|
object.pathAbsolute = filepath.isEmpty()
|
||||||
|
? QString()
|
||||||
|
: QFileInfo(filepath).absoluteFilePath();
|
||||||
|
}
|
||||||
|
if (bytes.isEmpty()) {
|
||||||
|
if (!LoadFromFile(filepath, &result->instance, &object.content)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!LoadFromContent(bytes, &result->instance)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Preview> GeneratePreview(
|
std::unique_ptr<Preview> GeneratePreview(
|
||||||
const QString &filepath,
|
const QString &filepath,
|
||||||
|
const QByteArray &bytes,
|
||||||
|
const Data::CloudTheme &cloud,
|
||||||
CurrentData &&data) {
|
CurrentData &&data) {
|
||||||
auto result = PreviewFromFile(filepath);
|
auto result = PreviewFromFile(filepath, bytes, cloud);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "window/themes/window_theme.h"
|
#include "window/themes/window_theme.h"
|
||||||
|
|
||||||
|
namespace Data {
|
||||||
|
struct CloudTheme;
|
||||||
|
} // namespace Data
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
namespace Theme {
|
namespace Theme {
|
||||||
|
|
||||||
|
@ -18,9 +22,14 @@ struct CurrentData {
|
||||||
bool backgroundTiled = false;
|
bool backgroundTiled = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<Preview> PreviewFromFile(const QString &filepath);
|
std::unique_ptr<Preview> PreviewFromFile(
|
||||||
|
const QString &filepath,
|
||||||
|
const QByteArray &bytes,
|
||||||
|
const Data::CloudTheme &cloud);
|
||||||
std::unique_ptr<Preview> GeneratePreview(
|
std::unique_ptr<Preview> GeneratePreview(
|
||||||
const QString &filepath,
|
const QString &filepath,
|
||||||
|
const QByteArray &bytes,
|
||||||
|
const Data::CloudTheme &cloud,
|
||||||
CurrentData &&data);
|
CurrentData &&data);
|
||||||
|
|
||||||
int DefaultPreviewTitleHeight();
|
int DefaultPreviewTitleHeight();
|
||||||
|
|
|
@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_cloud_themes.h"
|
#include "data/data_cloud_themes.h"
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "styles/style_settings.h"
|
#include "styles/style_settings.h"
|
||||||
|
@ -222,6 +223,11 @@ void CloudListBox(
|
||||||
box->setTitle(tr::lng_settings_bg_cloud_themes());
|
box->setTitle(tr::lng_settings_bg_cloud_themes());
|
||||||
box->setWidth(st::boxWideWidth);
|
box->setWidth(st::boxWideWidth);
|
||||||
|
|
||||||
|
const auto currentId = Background()->themeObject().cloud.documentId;
|
||||||
|
ranges::stable_sort(list, std::less<>(), [&](const Data::CloudTheme &t) {
|
||||||
|
return !t.documentId ? 2 : (t.documentId == currentId) ? 0 : 1;
|
||||||
|
});
|
||||||
|
|
||||||
const auto content = box->addRow(
|
const auto content = box->addRow(
|
||||||
object_ptr<Ui::RpWidget>(box),
|
object_ptr<Ui::RpWidget>(box),
|
||||||
style::margins(
|
style::margins(
|
||||||
|
@ -229,7 +235,27 @@ void CloudListBox(
|
||||||
0,
|
0,
|
||||||
st::settingsSubsectionTitlePadding.right(),
|
st::settingsSubsectionTitlePadding.right(),
|
||||||
0));
|
0));
|
||||||
const auto group = std::make_shared<Ui::RadiobuttonGroup>(-1);
|
const auto group = std::make_shared<Ui::RadiobuttonGroup>();
|
||||||
|
const auto resolveCurrent = [=] {
|
||||||
|
const auto currentId = Background()->themeObject().cloud.id;
|
||||||
|
const auto i = currentId
|
||||||
|
? ranges::find(list, currentId, &Data::CloudTheme::id)
|
||||||
|
: end(list);
|
||||||
|
group->setValue(i - begin(list));
|
||||||
|
};
|
||||||
|
|
||||||
|
resolveCurrent();
|
||||||
|
auto checker = Background()->add_subscription([=](const BackgroundUpdate &update) {
|
||||||
|
if (update.type == BackgroundUpdate::Type::ApplyingTheme
|
||||||
|
|| update.type == BackgroundUpdate::Type::New) {
|
||||||
|
resolveCurrent();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
group->setChangedCallback([=](int selected) {
|
||||||
|
resolveCurrent();
|
||||||
|
});
|
||||||
|
Ui::AttachAsChild(box, std::move(checker));
|
||||||
|
|
||||||
const auto waiting = std::make_shared<std::vector<WaitingPair>>();
|
const auto waiting = std::make_shared<std::vector<WaitingPair>>();
|
||||||
const auto fallback = std::make_shared<QImage>();
|
const auto fallback = std::make_shared<QImage>();
|
||||||
const auto buttonsMap = std::make_shared<base::flat_map<
|
const auto buttonsMap = std::make_shared<base::flat_map<
|
||||||
|
@ -248,13 +274,13 @@ void CloudListBox(
|
||||||
list
|
list
|
||||||
) | ranges::view::transform([&](const Data::CloudTheme &theme)
|
) | ranges::view::transform([&](const Data::CloudTheme &theme)
|
||||||
-> not_null<Ui::RpWidget*> {
|
-> not_null<Ui::RpWidget*> {
|
||||||
const auto document = theme.document;
|
if (!theme.documentId) {
|
||||||
if (!document) {
|
index++;
|
||||||
return Ui::CreateChild<Ui::RpWidget>(content);
|
return Ui::CreateChild<Ui::RpWidget>(content);
|
||||||
}
|
}
|
||||||
if (document) {
|
const auto document = window->session().data().document(
|
||||||
document->save(Data::FileOrigin(), QString()); // #TODO themes
|
theme.documentId);
|
||||||
}
|
document->save(Data::FileOrigin(), QString()); // #TODO themes
|
||||||
auto colors = ColorsFromTheme(
|
auto colors = ColorsFromTheme(
|
||||||
document->filepath(),
|
document->filepath(),
|
||||||
document->data());
|
document->data());
|
||||||
|
|
Loading…
Add table
Reference in a new issue