mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 10:11:41 -05:00
Allow independently change default / night themes.
This commit is contained in:
parent
d12bd0824d
commit
cb338e330f
12 changed files with 554 additions and 278 deletions
|
@ -519,6 +519,9 @@ void SetAnnotationHex(const std::string &key, const QString &value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetAnnotationRef(const std::string &key, const QString *valuePtr) {
|
void SetAnnotationRef(const std::string &key, const QString *valuePtr) {
|
||||||
|
static QMutex mutex;
|
||||||
|
QMutexLocker lock(&mutex);
|
||||||
|
|
||||||
if (valuePtr) {
|
if (valuePtr) {
|
||||||
ProcessAnnotationRefs[key] = valuePtr;
|
ProcessAnnotationRefs[key] = valuePtr;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -62,13 +62,10 @@ void AdvancedWidget::createControls() {
|
||||||
} else {
|
} else {
|
||||||
style::margins slidedPadding(0, marginLarge.bottom() / 2, 0, marginLarge.bottom() - (marginLarge.bottom() / 2));
|
style::margins slidedPadding(0, marginLarge.bottom() / 2, 0, marginLarge.bottom() - (marginLarge.bottom() / 2));
|
||||||
createChildRow(_useDefaultTheme, marginLarge, slidedPadding, lang(lng_settings_bg_use_default), SLOT(onUseDefaultTheme()));
|
createChildRow(_useDefaultTheme, marginLarge, slidedPadding, lang(lng_settings_bg_use_default), SLOT(onUseDefaultTheme()));
|
||||||
if (!Window::Theme::IsNonDefaultUsed()) {
|
if (!Window::Theme::SuggestThemeReset()) {
|
||||||
_useDefaultTheme->hide(anim::type::instant);
|
_useDefaultTheme->hide(anim::type::instant);
|
||||||
}
|
}
|
||||||
createChildRow(_toggleNightTheme, marginLarge, slidedPadding, getNightThemeToggleText(), SLOT(onToggleNightTheme()));
|
createChildRow(_toggleNightTheme, marginLarge, getNightThemeToggleText(), SLOT(onToggleNightTheme()));
|
||||||
if (Window::Theme::IsNonDefaultUsed()) {
|
|
||||||
_toggleNightTheme->hide(anim::type::instant);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
createChildRow(_telegramFAQ, marginLarge, lang(lng_settings_faq), SLOT(onTelegramFAQ()));
|
createChildRow(_telegramFAQ, marginLarge, lang(lng_settings_faq), SLOT(onTelegramFAQ()));
|
||||||
if (self()) {
|
if (self()) {
|
||||||
|
@ -78,14 +75,13 @@ void AdvancedWidget::createControls() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvancedWidget::checkNonDefaultTheme() {
|
void AdvancedWidget::checkNonDefaultTheme() {
|
||||||
if (self()) return;
|
if (self()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
_useDefaultTheme->toggle(
|
_useDefaultTheme->toggle(
|
||||||
Window::Theme::IsNonDefaultUsed(),
|
Window::Theme::SuggestThemeReset(),
|
||||||
anim::type::normal);
|
|
||||||
_toggleNightTheme->entity()->setText(getNightThemeToggleText());
|
|
||||||
_toggleNightTheme->toggle(
|
|
||||||
!Window::Theme::IsNonDefaultUsed(),
|
|
||||||
anim::type::normal);
|
anim::type::normal);
|
||||||
|
_toggleNightTheme->setText(getNightThemeToggleText());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvancedWidget::onManageLocalStorage() {
|
void AdvancedWidget::onManageLocalStorage() {
|
||||||
|
@ -120,7 +116,7 @@ void AdvancedWidget::onUseDefaultTheme() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvancedWidget::onToggleNightTheme() {
|
void AdvancedWidget::onToggleNightTheme() {
|
||||||
Window::Theme::SwitchNightTheme(!Window::Theme::IsNightTheme());
|
Window::Theme::ToggleNightMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvancedWidget::onAskQuestion() {
|
void AdvancedWidget::onAskQuestion() {
|
||||||
|
@ -149,7 +145,9 @@ void AdvancedWidget::supportGot(const MTPhelp_Support &support) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AdvancedWidget::getNightThemeToggleText() const {
|
QString AdvancedWidget::getNightThemeToggleText() const {
|
||||||
return lang(Window::Theme::IsNightTheme() ? lng_settings_disable_night_theme : lng_settings_enable_night_theme);
|
return lang(Window::Theme::IsNightMode()
|
||||||
|
? lng_settings_disable_night_theme
|
||||||
|
: lng_settings_enable_night_theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvancedWidget::onTelegramFAQ() {
|
void AdvancedWidget::onTelegramFAQ() {
|
||||||
|
|
|
@ -44,7 +44,7 @@ private:
|
||||||
LabeledLink *_connectionType = nullptr;
|
LabeledLink *_connectionType = nullptr;
|
||||||
#endif // !TDESKTOP_DISABLE_NETWORK_PROXY
|
#endif // !TDESKTOP_DISABLE_NETWORK_PROXY
|
||||||
Ui::SlideWrap<Ui::LinkButton> *_useDefaultTheme = nullptr;
|
Ui::SlideWrap<Ui::LinkButton> *_useDefaultTheme = nullptr;
|
||||||
Ui::SlideWrap<Ui::LinkButton> *_toggleNightTheme = nullptr;
|
Ui::LinkButton *_toggleNightTheme = nullptr;
|
||||||
Ui::LinkButton *_askQuestion = nullptr;
|
Ui::LinkButton *_askQuestion = nullptr;
|
||||||
Ui::LinkButton *_telegramFAQ = nullptr;
|
Ui::LinkButton *_telegramFAQ = nullptr;
|
||||||
Ui::LinkButton *_logOut = nullptr;
|
Ui::LinkButton *_logOut = nullptr;
|
||||||
|
|
|
@ -33,15 +33,17 @@ BackgroundRow::BackgroundRow(QWidget *parent) : RpWidget(parent)
|
||||||
connect(_chooseFromFile, SIGNAL(clicked()), this, SIGNAL(chooseFromFile()));
|
connect(_chooseFromFile, SIGNAL(clicked()), this, SIGNAL(chooseFromFile()));
|
||||||
connect(_editTheme, SIGNAL(clicked()), this, SIGNAL(editTheme()));
|
connect(_editTheme, SIGNAL(clicked()), this, SIGNAL(editTheme()));
|
||||||
checkNonDefaultTheme();
|
checkNonDefaultTheme();
|
||||||
subscribe(Window::Theme::Background(), [this](const Window::Theme::BackgroundUpdate &update) {
|
using Update = const Window::Theme::BackgroundUpdate;
|
||||||
if (update.type == Window::Theme::BackgroundUpdate::Type::ApplyingTheme) {
|
subscribe(Window::Theme::Background(), [this](Update &update) {
|
||||||
|
if (update.type == Update::Type::ApplyingTheme
|
||||||
|
|| update.type == Update::Type::New) {
|
||||||
checkNonDefaultTheme();
|
checkNonDefaultTheme();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void BackgroundRow::checkNonDefaultTheme() {
|
void BackgroundRow::checkNonDefaultTheme() {
|
||||||
if (Window::Theme::IsNonDefaultUsed()) {
|
if (Window::Theme::SuggestThemeReset()) {
|
||||||
if (!_useDefaultTheme) {
|
if (!_useDefaultTheme) {
|
||||||
_useDefaultTheme.create(this, lang(lng_settings_bg_use_default), st::boxLinkButton);
|
_useDefaultTheme.create(this, lang(lng_settings_bg_use_default), st::boxLinkButton);
|
||||||
_useDefaultTheme->show();
|
_useDefaultTheme->show();
|
||||||
|
@ -190,7 +192,8 @@ BackgroundWidget::BackgroundWidget(QWidget *parent, UserData *self) : BlockWidge
|
||||||
subscribe(Window::Theme::Background(), [this](const Update &update) {
|
subscribe(Window::Theme::Background(), [this](const Update &update) {
|
||||||
if (update.type == Update::Type::New) {
|
if (update.type == Update::Type::New) {
|
||||||
_background->updateImage();
|
_background->updateImage();
|
||||||
} else if (update.type == Update::Type::Start) {
|
} else if (update.type == Update::Type::Start
|
||||||
|
|| update.type == Update::Type::Changed) {
|
||||||
needBackgroundUpdate(update.tiled);
|
needBackgroundUpdate(update.tiled);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -491,7 +491,7 @@ enum { // Local Storage Keys
|
||||||
lskStickerImages = 0x05, // data: StorageKey location
|
lskStickerImages = 0x05, // data: StorageKey location
|
||||||
lskAudios = 0x06, // data: StorageKey location
|
lskAudios = 0x06, // data: StorageKey location
|
||||||
lskRecentStickersOld = 0x07, // no data
|
lskRecentStickersOld = 0x07, // no data
|
||||||
lskBackground = 0x08, // no data
|
lskBackgroundOld = 0x08, // no data
|
||||||
lskUserSettings = 0x09, // no data
|
lskUserSettings = 0x09, // no data
|
||||||
lskRecentHashtagsAndBots = 0x0a, // no data
|
lskRecentHashtagsAndBots = 0x0a, // no data
|
||||||
lskStickersOld = 0x0b, // no data
|
lskStickersOld = 0x0b, // no data
|
||||||
|
@ -503,6 +503,7 @@ enum { // Local Storage Keys
|
||||||
lskTrustedBots = 0x11, // no data
|
lskTrustedBots = 0x11, // no data
|
||||||
lskFavedStickers = 0x12, // no data
|
lskFavedStickers = 0x12, // no data
|
||||||
lskExportSettings = 0x13, // no data
|
lskExportSettings = 0x13, // no data
|
||||||
|
lskBackground = 0x14, // no data
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -539,7 +540,7 @@ enum {
|
||||||
dbiCompressPastedImage = 0x1e,
|
dbiCompressPastedImage = 0x1e,
|
||||||
dbiLangOld = 0x1f,
|
dbiLangOld = 0x1f,
|
||||||
dbiLangFileOld = 0x20,
|
dbiLangFileOld = 0x20,
|
||||||
dbiTileBackground = 0x21,
|
dbiTileBackgroundOld = 0x21,
|
||||||
dbiAutoLock = 0x22,
|
dbiAutoLock = 0x22,
|
||||||
dbiDialogLastPath = 0x23,
|
dbiDialogLastPath = 0x23,
|
||||||
dbiRecentEmojiOld = 0x24,
|
dbiRecentEmojiOld = 0x24,
|
||||||
|
@ -567,7 +568,7 @@ enum {
|
||||||
dbiNativeNotifications = 0x44,
|
dbiNativeNotifications = 0x44,
|
||||||
dbiNotificationsCount = 0x45,
|
dbiNotificationsCount = 0x45,
|
||||||
dbiNotificationsCorner = 0x46,
|
dbiNotificationsCorner = 0x46,
|
||||||
dbiThemeKey = 0x47,
|
dbiThemeKeyOld = 0x47,
|
||||||
dbiDialogsWidthRatioOld = 0x48,
|
dbiDialogsWidthRatioOld = 0x48,
|
||||||
dbiUseExternalVideoPlayer = 0x49,
|
dbiUseExternalVideoPlayer = 0x49,
|
||||||
dbiDcOptions = 0x4a,
|
dbiDcOptions = 0x4a,
|
||||||
|
@ -580,6 +581,8 @@ enum {
|
||||||
dbiSuggestStickersByEmoji = 0x51,
|
dbiSuggestStickersByEmoji = 0x51,
|
||||||
dbiSuggestEmoji = 0x52,
|
dbiSuggestEmoji = 0x52,
|
||||||
dbiTxtDomainString = 0x53,
|
dbiTxtDomainString = 0x53,
|
||||||
|
dbiThemeKey = 0x54,
|
||||||
|
dbiTileBackground = 0x55,
|
||||||
|
|
||||||
dbiEncryptedWithSalt = 333,
|
dbiEncryptedWithSalt = 333,
|
||||||
dbiEncrypted = 444,
|
dbiEncrypted = 444,
|
||||||
|
@ -624,13 +627,17 @@ FileKey _recentStickersKeyOld = 0;
|
||||||
FileKey _installedStickersKey = 0, _featuredStickersKey = 0, _recentStickersKey = 0, _favedStickersKey = 0, _archivedStickersKey = 0;
|
FileKey _installedStickersKey = 0, _featuredStickersKey = 0, _recentStickersKey = 0, _favedStickersKey = 0, _archivedStickersKey = 0;
|
||||||
FileKey _savedGifsKey = 0;
|
FileKey _savedGifsKey = 0;
|
||||||
|
|
||||||
FileKey _backgroundKey = 0;
|
FileKey _backgroundKeyDay = 0;
|
||||||
bool _backgroundWasRead = false;
|
FileKey _backgroundKeyNight = 0;
|
||||||
bool _backgroundCanWrite = true;
|
bool _backgroundCanWrite = true;
|
||||||
|
|
||||||
FileKey _themeKey = 0;
|
FileKey _themeKeyDay = 0;
|
||||||
QString _themeAbsolutePath;
|
FileKey _themeKeyNight = 0;
|
||||||
QString _themePaletteAbsolutePath;
|
|
||||||
|
// Theme key legacy may be read in start() with settings.
|
||||||
|
// But it should be moved to keyDay or keyNight inside loadTheme()
|
||||||
|
// and never used after.
|
||||||
|
FileKey _themeKeyLegacy = 0;
|
||||||
|
|
||||||
bool _readingUserSettings = false;
|
bool _readingUserSettings = false;
|
||||||
FileKey _userSettingsKey = 0;
|
FileKey _userSettingsKey = 0;
|
||||||
|
@ -1277,12 +1284,23 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
|
||||||
Sandbox::refreshGlobalProxy();
|
Sandbox::refreshGlobalProxy();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case dbiThemeKey: {
|
case dbiThemeKeyOld: {
|
||||||
quint64 themeKey = 0;
|
quint64 key = 0;
|
||||||
stream >> themeKey;
|
stream >> key;
|
||||||
if (!_checkStreamStatus(stream)) return false;
|
if (!_checkStreamStatus(stream)) return false;
|
||||||
|
|
||||||
_themeKey = themeKey;
|
_themeKeyLegacy = key;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case dbiThemeKey: {
|
||||||
|
quint64 keyDay = 0, keyNight = 0;
|
||||||
|
quint32 nightMode = 0;
|
||||||
|
stream >> keyDay >> keyNight >> nightMode;
|
||||||
|
if (!_checkStreamStatus(stream)) return false;
|
||||||
|
|
||||||
|
_themeKeyDay = keyDay;
|
||||||
|
_themeKeyNight = keyNight;
|
||||||
|
Window::Theme::SetNightModeValue(nightMode == 1);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case dbiLangPackKey: {
|
case dbiLangPackKey: {
|
||||||
|
@ -1413,13 +1431,28 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
|
||||||
if (!_checkStreamStatus(stream)) return false;
|
if (!_checkStreamStatus(stream)) return false;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case dbiTileBackground: {
|
case dbiTileBackgroundOld: {
|
||||||
qint32 v;
|
qint32 v;
|
||||||
stream >> v;
|
stream >> v;
|
||||||
if (!_checkStreamStatus(stream)) return false;
|
if (!_checkStreamStatus(stream)) return false;
|
||||||
|
|
||||||
bool tile = (version < 8005 && !_backgroundKey) ? false : (v == 1);
|
bool tile = (version < 8005 && !_backgroundKeyDay)
|
||||||
Window::Theme::Background()->setTile(tile);
|
? false
|
||||||
|
: (v == 1);
|
||||||
|
if (Window::Theme::IsNightMode()) {
|
||||||
|
Window::Theme::Background()->setTileNightValue(tile);
|
||||||
|
} else {
|
||||||
|
Window::Theme::Background()->setTileDayValue(tile);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case dbiTileBackground: {
|
||||||
|
qint32 tileDay, tileNight;
|
||||||
|
stream >> tileDay >> tileNight;
|
||||||
|
if (!_checkStreamStatus(stream)) return false;
|
||||||
|
|
||||||
|
Window::Theme::Background()->setTileDayValue(tileDay == 1);
|
||||||
|
Window::Theme::Background()->setTileNightValue(tileNight == 1);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case dbiAdaptiveForWide: {
|
case dbiAdaptiveForWide: {
|
||||||
|
@ -1873,7 +1906,7 @@ void _writeUserSettings() {
|
||||||
? userDataInstance->serialize()
|
? userDataInstance->serialize()
|
||||||
: QByteArray();
|
: QByteArray();
|
||||||
|
|
||||||
uint32 size = 23 * (sizeof(quint32) + sizeof(qint32));
|
uint32 size = 22 * (sizeof(quint32) + sizeof(qint32));
|
||||||
size += sizeof(quint32) + Serialize::stringSize(Global::AskDownloadPath() ? QString() : Global::DownloadPath()) + Serialize::bytearraySize(Global::AskDownloadPath() ? QByteArray() : Global::DownloadPathBookmark());
|
size += sizeof(quint32) + Serialize::stringSize(Global::AskDownloadPath() ? QString() : Global::DownloadPath()) + Serialize::bytearraySize(Global::AskDownloadPath() ? QByteArray() : Global::DownloadPathBookmark());
|
||||||
|
|
||||||
size += sizeof(quint32) + sizeof(qint32);
|
size += sizeof(quint32) + sizeof(qint32);
|
||||||
|
@ -1886,6 +1919,7 @@ void _writeUserSettings() {
|
||||||
size += sizeof(quint32) + Serialize::stringSize(cDialogLastPath());
|
size += sizeof(quint32) + Serialize::stringSize(cDialogLastPath());
|
||||||
size += sizeof(quint32) + 3 * sizeof(qint32);
|
size += sizeof(quint32) + 3 * sizeof(qint32);
|
||||||
size += sizeof(quint32) + 2 * sizeof(qint32);
|
size += sizeof(quint32) + 2 * sizeof(qint32);
|
||||||
|
size += sizeof(quint32) + 2 * sizeof(qint32);
|
||||||
if (!Global::HiddenPinnedMessages().isEmpty()) {
|
if (!Global::HiddenPinnedMessages().isEmpty()) {
|
||||||
size += sizeof(quint32) + sizeof(qint32) + Global::HiddenPinnedMessages().size() * (sizeof(PeerId) + sizeof(MsgId));
|
size += sizeof(quint32) + sizeof(qint32) + Global::HiddenPinnedMessages().size() * (sizeof(PeerId) + sizeof(MsgId));
|
||||||
}
|
}
|
||||||
|
@ -1895,7 +1929,10 @@ void _writeUserSettings() {
|
||||||
|
|
||||||
EncryptedDescriptor data(size);
|
EncryptedDescriptor data(size);
|
||||||
data.stream << quint32(dbiSendKey) << qint32(cCtrlEnter() ? dbiskCtrlEnter : dbiskEnter);
|
data.stream << quint32(dbiSendKey) << qint32(cCtrlEnter() ? dbiskCtrlEnter : dbiskEnter);
|
||||||
data.stream << quint32(dbiTileBackground) << qint32(Window::Theme::Background()->tileForSave() ? 1 : 0);
|
data.stream
|
||||||
|
<< quint32(dbiTileBackground)
|
||||||
|
<< qint32(Window::Theme::Background()->tileDay() ? 1 : 0)
|
||||||
|
<< qint32(Window::Theme::Background()->tileNight() ? 1 : 0);
|
||||||
data.stream << quint32(dbiAdaptiveForWide) << qint32(Global::AdaptiveForWide() ? 1 : 0);
|
data.stream << quint32(dbiAdaptiveForWide) << qint32(Global::AdaptiveForWide() ? 1 : 0);
|
||||||
data.stream << quint32(dbiAutoLock) << qint32(Global::AutoLock());
|
data.stream << quint32(dbiAutoLock) << qint32(Global::AutoLock());
|
||||||
data.stream << quint32(dbiReplaceEmoji) << qint32(Global::ReplaceEmoji() ? 1 : 0);
|
data.stream << quint32(dbiReplaceEmoji) << qint32(Global::ReplaceEmoji() ? 1 : 0);
|
||||||
|
@ -2076,7 +2113,8 @@ ReadMapState _readMap(const QByteArray &pass) {
|
||||||
quint64 recentStickersKeyOld = 0;
|
quint64 recentStickersKeyOld = 0;
|
||||||
quint64 installedStickersKey = 0, featuredStickersKey = 0, recentStickersKey = 0, favedStickersKey = 0, archivedStickersKey = 0;
|
quint64 installedStickersKey = 0, featuredStickersKey = 0, recentStickersKey = 0, favedStickersKey = 0, archivedStickersKey = 0;
|
||||||
quint64 savedGifsKey = 0;
|
quint64 savedGifsKey = 0;
|
||||||
quint64 backgroundKey = 0, userSettingsKey = 0, recentHashtagsAndBotsKey = 0, savedPeersKey = 0, exportSettingsKey = 0;
|
quint64 backgroundKeyDay = 0, backgroundKeyNight = 0;
|
||||||
|
quint64 userSettingsKey = 0, recentHashtagsAndBotsKey = 0, savedPeersKey = 0, exportSettingsKey = 0;
|
||||||
while (!map.stream.atEnd()) {
|
while (!map.stream.atEnd()) {
|
||||||
quint32 keyType;
|
quint32 keyType;
|
||||||
map.stream >> keyType;
|
map.stream >> keyType;
|
||||||
|
@ -2150,8 +2188,13 @@ ReadMapState _readMap(const QByteArray &pass) {
|
||||||
case lskRecentStickersOld: {
|
case lskRecentStickersOld: {
|
||||||
map.stream >> recentStickersKeyOld;
|
map.stream >> recentStickersKeyOld;
|
||||||
} break;
|
} break;
|
||||||
|
case lskBackgroundOld: {
|
||||||
|
map.stream >> (Window::Theme::IsNightMode()
|
||||||
|
? backgroundKeyNight
|
||||||
|
: backgroundKeyDay);
|
||||||
|
} break;
|
||||||
case lskBackground: {
|
case lskBackground: {
|
||||||
map.stream >> backgroundKey;
|
map.stream >> backgroundKeyDay >> backgroundKeyNight;
|
||||||
} break;
|
} break;
|
||||||
case lskUserSettings: {
|
case lskUserSettings: {
|
||||||
map.stream >> userSettingsKey;
|
map.stream >> userSettingsKey;
|
||||||
|
@ -2212,7 +2255,8 @@ ReadMapState _readMap(const QByteArray &pass) {
|
||||||
_archivedStickersKey = archivedStickersKey;
|
_archivedStickersKey = archivedStickersKey;
|
||||||
_savedGifsKey = savedGifsKey;
|
_savedGifsKey = savedGifsKey;
|
||||||
_savedPeersKey = savedPeersKey;
|
_savedPeersKey = savedPeersKey;
|
||||||
_backgroundKey = backgroundKey;
|
_backgroundKeyDay = backgroundKeyDay;
|
||||||
|
_backgroundKeyNight = backgroundKeyNight;
|
||||||
_userSettingsKey = userSettingsKey;
|
_userSettingsKey = userSettingsKey;
|
||||||
_recentHashtagsAndBotsKey = recentHashtagsAndBotsKey;
|
_recentHashtagsAndBotsKey = recentHashtagsAndBotsKey;
|
||||||
_exportSettingsKey = exportSettingsKey;
|
_exportSettingsKey = exportSettingsKey;
|
||||||
|
@ -2291,7 +2335,7 @@ void _writeMap(WriteMapWhen when) {
|
||||||
if (_favedStickersKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
if (_favedStickersKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||||
if (_savedGifsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
if (_savedGifsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||||
if (_savedPeersKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
if (_savedPeersKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||||
if (_backgroundKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
if (_backgroundKeyDay || _backgroundKeyNight) mapSize += sizeof(quint32) + sizeof(quint64) + sizeof(quint64);
|
||||||
if (_userSettingsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
if (_userSettingsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||||
if (_recentHashtagsAndBotsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
if (_recentHashtagsAndBotsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||||
if (_exportSettingsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
if (_exportSettingsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||||
|
@ -2363,8 +2407,11 @@ void _writeMap(WriteMapWhen when) {
|
||||||
if (_savedPeersKey) {
|
if (_savedPeersKey) {
|
||||||
mapData.stream << quint32(lskSavedPeers) << quint64(_savedPeersKey);
|
mapData.stream << quint32(lskSavedPeers) << quint64(_savedPeersKey);
|
||||||
}
|
}
|
||||||
if (_backgroundKey) {
|
if (_backgroundKeyDay || _backgroundKeyNight) {
|
||||||
mapData.stream << quint32(lskBackground) << quint64(_backgroundKey);
|
mapData.stream
|
||||||
|
<< quint32(lskBackground)
|
||||||
|
<< quint64(_backgroundKeyDay)
|
||||||
|
<< quint64(_backgroundKeyNight);
|
||||||
}
|
}
|
||||||
if (_userSettingsKey) {
|
if (_userSettingsKey) {
|
||||||
mapData.stream << quint32(lskUserSettings) << quint64(_userSettingsKey);
|
mapData.stream << quint32(lskUserSettings) << quint64(_userSettingsKey);
|
||||||
|
@ -2396,7 +2443,7 @@ void finish() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void readTheme();
|
void loadTheme();
|
||||||
void readLangPack();
|
void readLangPack();
|
||||||
|
|
||||||
void start() {
|
void start() {
|
||||||
|
@ -2454,7 +2501,7 @@ void start() {
|
||||||
_oldSettingsVersion = settingsData.version;
|
_oldSettingsVersion = settingsData.version;
|
||||||
_settingsSalt = salt;
|
_settingsSalt = salt;
|
||||||
|
|
||||||
readTheme();
|
loadTheme();
|
||||||
readLangPack();
|
readLangPack();
|
||||||
|
|
||||||
applyReadContext(std::move(context));
|
applyReadContext(std::move(context));
|
||||||
|
@ -2496,9 +2543,8 @@ void writeSettings() {
|
||||||
size += sizeof(qint32) + Serialize::stringSize(proxy.host) + sizeof(qint32) + Serialize::stringSize(proxy.user) + Serialize::stringSize(proxy.password);
|
size += sizeof(qint32) + Serialize::stringSize(proxy.host) + sizeof(qint32) + Serialize::stringSize(proxy.user) + Serialize::stringSize(proxy.password);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_themeKey) {
|
// Theme keys and night mode.
|
||||||
size += sizeof(quint32) + sizeof(quint64);
|
size += sizeof(quint32) + sizeof(quint64) * 2 + sizeof(quint32);
|
||||||
}
|
|
||||||
if (_langPackKey) {
|
if (_langPackKey) {
|
||||||
size += sizeof(quint32) + sizeof(quint64);
|
size += sizeof(quint32) + sizeof(quint64);
|
||||||
}
|
}
|
||||||
|
@ -2534,9 +2580,11 @@ void writeSettings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
data.stream << quint32(dbiTryIPv6) << qint32(Global::TryIPv6());
|
data.stream << quint32(dbiTryIPv6) << qint32(Global::TryIPv6());
|
||||||
if (_themeKey) {
|
data.stream
|
||||||
data.stream << quint32(dbiThemeKey) << quint64(_themeKey);
|
<< quint32(dbiThemeKey)
|
||||||
}
|
<< quint64(_themeKeyDay)
|
||||||
|
<< quint64(_themeKeyNight)
|
||||||
|
<< quint32(Window::Theme::IsNightMode() ? 1 : 0);
|
||||||
if (_langPackKey) {
|
if (_langPackKey) {
|
||||||
data.stream << quint32(dbiLangPackKey) << quint64(_langPackKey);
|
data.stream << quint32(dbiLangPackKey) << quint64(_langPackKey);
|
||||||
}
|
}
|
||||||
|
@ -2640,7 +2688,8 @@ void reset() {
|
||||||
_recentStickersKeyOld = 0;
|
_recentStickersKeyOld = 0;
|
||||||
_installedStickersKey = _featuredStickersKey = _recentStickersKey = _favedStickersKey = _archivedStickersKey = 0;
|
_installedStickersKey = _featuredStickersKey = _recentStickersKey = _favedStickersKey = _archivedStickersKey = 0;
|
||||||
_savedGifsKey = 0;
|
_savedGifsKey = 0;
|
||||||
_backgroundKey = _userSettingsKey = _recentHashtagsAndBotsKey = _savedPeersKey = _exportSettingsKey = 0;
|
_backgroundKeyDay = _backgroundKeyNight = 0;
|
||||||
|
_userSettingsKey = _recentHashtagsAndBotsKey = _savedPeersKey = _exportSettingsKey = 0;
|
||||||
_oldMapVersion = _oldSettingsVersion = 0;
|
_oldMapVersion = _oldSettingsVersion = 0;
|
||||||
StoredAuthSessionCache.reset();
|
StoredAuthSessionCache.reset();
|
||||||
_mapChanged = true;
|
_mapChanged = true;
|
||||||
|
@ -4102,48 +4151,58 @@ void readSavedGifs() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeBackground(int32 id, const QImage &img) {
|
void writeBackground(int32 id, const QImage &img) {
|
||||||
if (!_working() || !_backgroundCanWrite) return;
|
if (!_working() || !_backgroundCanWrite) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!LocalKey) {
|
if (!LocalKey) {
|
||||||
LOG(("App Error: localkey not created in writeBackground()"));
|
LOG(("App Error: localkey not created in writeBackground()"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto &backgroundKey = Window::Theme::IsNightMode()
|
||||||
|
? _backgroundKeyNight
|
||||||
|
: _backgroundKeyDay;
|
||||||
QByteArray bmp;
|
QByteArray bmp;
|
||||||
if (!img.isNull()) {
|
if (!img.isNull()) {
|
||||||
QBuffer buf(&bmp);
|
QBuffer buf(&bmp);
|
||||||
if (!img.save(&buf, "BMP")) return;
|
if (!img.save(&buf, "BMP")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!_backgroundKey) {
|
if (!backgroundKey) {
|
||||||
_backgroundKey = genKey();
|
backgroundKey = genKey();
|
||||||
_mapChanged = true;
|
_mapChanged = true;
|
||||||
_writeMap(WriteMapWhen::Fast);
|
_writeMap(WriteMapWhen::Fast);
|
||||||
}
|
}
|
||||||
quint32 size = sizeof(qint32) + sizeof(quint32) + (bmp.isEmpty() ? 0 : (sizeof(quint32) + bmp.size()));
|
quint32 size = sizeof(qint32)
|
||||||
|
+ sizeof(quint32)
|
||||||
|
+ (bmp.isEmpty() ? 0 : (sizeof(quint32) + bmp.size()));
|
||||||
EncryptedDescriptor data(size);
|
EncryptedDescriptor data(size);
|
||||||
data.stream << qint32(id) << bmp;
|
data.stream << qint32(id) << bmp;
|
||||||
|
|
||||||
FileWriteDescriptor file(_backgroundKey);
|
FileWriteDescriptor file(backgroundKey);
|
||||||
file.writeEncrypted(data);
|
file.writeEncrypted(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool readBackground() {
|
bool readBackground() {
|
||||||
if (_backgroundWasRead) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
_backgroundWasRead = true;
|
|
||||||
|
|
||||||
FileReadDescriptor bg;
|
FileReadDescriptor bg;
|
||||||
if (!readEncryptedFile(bg, _backgroundKey)) {
|
auto &backgroundKey = Window::Theme::IsNightMode()
|
||||||
clearKey(_backgroundKey);
|
? _backgroundKeyNight
|
||||||
_backgroundKey = 0;
|
: _backgroundKeyDay;
|
||||||
_writeMap();
|
if (!readEncryptedFile(bg, backgroundKey)) {
|
||||||
|
if (backgroundKey) {
|
||||||
|
clearKey(backgroundKey);
|
||||||
|
backgroundKey = 0;
|
||||||
|
_mapChanged = true;
|
||||||
|
_writeMap();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray pngData;
|
QByteArray bmpData;
|
||||||
qint32 id;
|
qint32 id;
|
||||||
bg.stream >> id >> pngData;
|
bg.stream >> id >> bmpData;
|
||||||
auto oldEmptyImage = (bg.stream.status() != QDataStream::Ok);
|
auto oldEmptyImage = (bg.stream.status() != QDataStream::Ok);
|
||||||
if (oldEmptyImage
|
if (oldEmptyImage
|
||||||
|| id == Window::Theme::kInitialBackground
|
|| id == Window::Theme::kInitialBackground
|
||||||
|
@ -4157,7 +4216,7 @@ bool readBackground() {
|
||||||
}
|
}
|
||||||
_backgroundCanWrite = true;
|
_backgroundCanWrite = true;
|
||||||
return true;
|
return true;
|
||||||
} else if (id == Window::Theme::kThemeBackground && pngData.isEmpty()) {
|
} else if (id == Window::Theme::kThemeBackground && bmpData.isEmpty()) {
|
||||||
_backgroundCanWrite = false;
|
_backgroundCanWrite = false;
|
||||||
Window::Theme::Background()->setImage(id);
|
Window::Theme::Background()->setImage(id);
|
||||||
_backgroundCanWrite = true;
|
_backgroundCanWrite = true;
|
||||||
|
@ -4165,7 +4224,7 @@ bool readBackground() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage image;
|
QImage image;
|
||||||
QBuffer buf(&pngData);
|
QBuffer buf(&bmpData);
|
||||||
QImageReader reader(&buf);
|
QImageReader reader(&buf);
|
||||||
#ifndef OS_MAC_OLD
|
#ifndef OS_MAC_OLD
|
||||||
reader.setAutoTransform(true);
|
reader.setAutoTransform(true);
|
||||||
|
@ -4179,96 +4238,127 @@ bool readBackground() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool readThemeUsingKey(FileKey key) {
|
Window::Theme::Saved readThemeUsingKey(FileKey key) {
|
||||||
FileReadDescriptor theme;
|
FileReadDescriptor theme;
|
||||||
if (!readEncryptedFile(theme, key, FileOption::Safe, SettingsKey)) {
|
if (!readEncryptedFile(theme, key, FileOption::Safe, SettingsKey)) {
|
||||||
return false;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray themeContent;
|
auto result = Window::Theme::Saved();
|
||||||
QString pathRelative, pathAbsolute;
|
theme.stream >> result.content;
|
||||||
Window::Theme::Cached cache;
|
theme.stream >> result.pathRelative >> result.pathAbsolute;
|
||||||
theme.stream >> themeContent;
|
|
||||||
theme.stream >> pathRelative >> pathAbsolute;
|
|
||||||
if (theme.stream.status() != QDataStream::Ok) {
|
if (theme.stream.status() != QDataStream::Ok) {
|
||||||
return false;
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
_themeAbsolutePath = pathAbsolute;
|
QFile file(result.pathRelative);
|
||||||
_themePaletteAbsolutePath = Window::Theme::IsPaletteTestingPath(pathAbsolute) ? pathAbsolute : QString();
|
if (result.pathRelative.isEmpty() || !file.exists()) {
|
||||||
|
file.setFileName(result.pathAbsolute);
|
||||||
QFile file(pathRelative);
|
|
||||||
if (pathRelative.isEmpty() || !file.exists()) {
|
|
||||||
file.setFileName(pathAbsolute);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto changed = false;
|
auto changed = false;
|
||||||
if (!file.fileName().isEmpty() && file.exists() && file.open(QIODevice::ReadOnly)) {
|
if (!file.fileName().isEmpty()
|
||||||
|
&& file.exists()
|
||||||
|
&& file.open(QIODevice::ReadOnly)) {
|
||||||
if (file.size() > kThemeFileSizeLimit) {
|
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()));
|
LOG(("Error: theme file too large: %1 "
|
||||||
return false;
|
"(should be less than 5 MB, got %2)"
|
||||||
|
).arg(file.fileName()
|
||||||
|
).arg(file.size()));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
auto fileContent = file.readAll();
|
auto fileContent = file.readAll();
|
||||||
file.close();
|
file.close();
|
||||||
if (themeContent != fileContent) {
|
if (result.content != fileContent) {
|
||||||
themeContent = fileContent;
|
result.content = fileContent;
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!changed) {
|
if (!changed) {
|
||||||
quint32 backgroundIsTiled = 0;
|
quint32 backgroundIsTiled = 0;
|
||||||
theme.stream >> cache.paletteChecksum >> cache.contentChecksum >> cache.colors >> cache.background >> backgroundIsTiled;
|
theme.stream
|
||||||
cache.tiled = (backgroundIsTiled == 1);
|
>> result.cache.paletteChecksum
|
||||||
|
>> result.cache.contentChecksum
|
||||||
|
>> result.cache.colors
|
||||||
|
>> result.cache.background
|
||||||
|
>> backgroundIsTiled;
|
||||||
|
result.cache.tiled = (backgroundIsTiled == 1);
|
||||||
if (theme.stream.status() != QDataStream::Ok) {
|
if (theme.stream.status() != QDataStream::Ok) {
|
||||||
return false;
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Window::Theme::Load(pathRelative, pathAbsolute, themeContent, cache);
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeTheme(const QString &pathRelative, const QString &pathAbsolute, const QByteArray &content, const Window::Theme::Cached &cache) {
|
QString loadThemeUsingKey(FileKey key) {
|
||||||
if (content.isEmpty()) {
|
auto read = readThemeUsingKey(key);
|
||||||
_themeAbsolutePath = _themePaletteAbsolutePath = QString();
|
const auto result = read.pathAbsolute;
|
||||||
if (_themeKey) {
|
return (!read.content.isEmpty() && Window::Theme::Load(std::move(read)))
|
||||||
clearKey(_themeKey);
|
? result
|
||||||
_themeKey = 0;
|
: QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void writeTheme(const Window::Theme::Saved &saved) {
|
||||||
|
auto &themeKey = Window::Theme::IsNightMode()
|
||||||
|
? _themeKeyNight
|
||||||
|
: _themeKeyDay;
|
||||||
|
if (saved.content.isEmpty()) {
|
||||||
|
if (themeKey) {
|
||||||
|
clearKey(themeKey);
|
||||||
|
themeKey = 0;
|
||||||
writeSettings();
|
writeSettings();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_themeAbsolutePath = pathAbsolute;
|
if (!themeKey) {
|
||||||
_themePaletteAbsolutePath = Window::Theme::IsPaletteTestingPath(pathAbsolute) ? pathAbsolute : QString();
|
themeKey = genKey(FileOption::Safe);
|
||||||
if (!_themeKey) {
|
|
||||||
_themeKey = genKey(FileOption::Safe);
|
|
||||||
writeSettings();
|
writeSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto backgroundTiled = static_cast<quint32>(cache.tiled ? 1 : 0);
|
auto backgroundTiled = static_cast<quint32>(saved.cache.tiled ? 1 : 0);
|
||||||
quint32 size = Serialize::bytearraySize(content);
|
quint32 size = Serialize::bytearraySize(saved.content);
|
||||||
size += Serialize::stringSize(pathRelative) + Serialize::stringSize(pathAbsolute);
|
size += Serialize::stringSize(saved.pathRelative) + Serialize::stringSize(saved.pathAbsolute);
|
||||||
size += sizeof(int32) * 2 + Serialize::bytearraySize(cache.colors) + Serialize::bytearraySize(cache.background) + sizeof(quint32);
|
size += sizeof(int32) * 2 + Serialize::bytearraySize(saved.cache.colors) + Serialize::bytearraySize(saved.cache.background) + sizeof(quint32);
|
||||||
EncryptedDescriptor data(size);
|
EncryptedDescriptor data(size);
|
||||||
data.stream << content;
|
data.stream << saved.content;
|
||||||
data.stream << pathRelative << pathAbsolute;
|
data.stream << saved.pathRelative << saved.pathAbsolute;
|
||||||
data.stream << cache.paletteChecksum << cache.contentChecksum << cache.colors << cache.background << backgroundTiled;
|
data.stream << saved.cache.paletteChecksum << saved.cache.contentChecksum << saved.cache.colors << saved.cache.background << backgroundTiled;
|
||||||
|
|
||||||
FileWriteDescriptor file(_themeKey, FileOption::Safe);
|
FileWriteDescriptor file(themeKey, FileOption::Safe);
|
||||||
file.writeEncrypted(data, SettingsKey);
|
file.writeEncrypted(data, SettingsKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearTheme() {
|
void clearTheme() {
|
||||||
writeTheme(QString(), QString(), QByteArray(), Window::Theme::Cached());
|
writeTheme(Window::Theme::Saved());
|
||||||
}
|
}
|
||||||
|
|
||||||
void readTheme() {
|
void loadTheme() {
|
||||||
if (_themeKey && !readThemeUsingKey(_themeKey)) {
|
const auto key = (_themeKeyLegacy != 0)
|
||||||
|
? _themeKeyLegacy
|
||||||
|
: (Window::Theme::IsNightMode()
|
||||||
|
? _themeKeyNight
|
||||||
|
: _themeKeyDay);
|
||||||
|
if (!key) {
|
||||||
|
return;
|
||||||
|
} else if (const auto path = loadThemeUsingKey(key); !path.isEmpty()) {
|
||||||
|
if (_themeKeyLegacy) {
|
||||||
|
Window::Theme::SetNightModeValue(path
|
||||||
|
== Window::Theme::NightThemePath());
|
||||||
|
(Window::Theme::IsNightMode()
|
||||||
|
? _themeKeyNight
|
||||||
|
: _themeKeyDay) = base::take(_themeKeyLegacy);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
clearTheme();
|
clearTheme();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasTheme() {
|
Window::Theme::Saved readThemeAfterSwitch() {
|
||||||
return (_themeKey != 0);
|
const auto key = Window::Theme::IsNightMode()
|
||||||
|
? _themeKeyNight
|
||||||
|
: _themeKeyDay;
|
||||||
|
return readThemeUsingKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void readLangPack() {
|
void readLangPack() {
|
||||||
|
@ -4297,21 +4387,16 @@ void writeLangPack() {
|
||||||
file.writeEncrypted(data, SettingsKey);
|
file.writeEncrypted(data, SettingsKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString themePaletteAbsolutePath() {
|
|
||||||
return _themePaletteAbsolutePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString themeAbsolutePath() {
|
|
||||||
return _themeAbsolutePath;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool copyThemeColorsToPalette(const QString &path) {
|
bool copyThemeColorsToPalette(const QString &path) {
|
||||||
if (!_themeKey) {
|
auto &themeKey = Window::Theme::IsNightMode()
|
||||||
|
? _themeKeyNight
|
||||||
|
: _themeKeyDay;
|
||||||
|
if (!themeKey) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileReadDescriptor theme;
|
FileReadDescriptor theme;
|
||||||
if (!readEncryptedFile(theme, _themeKey, FileOption::Safe, SettingsKey)) {
|
if (!readEncryptedFile(theme, themeKey, FileOption::Safe, SettingsKey)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
namespace Window {
|
namespace Window {
|
||||||
namespace Theme {
|
namespace Theme {
|
||||||
struct Cached;
|
struct Saved;
|
||||||
} // namespace Theme
|
} // namespace Theme
|
||||||
} // namespace Window
|
} // namespace Window
|
||||||
|
|
||||||
|
@ -152,12 +152,10 @@ int32 countSavedGifsHash();
|
||||||
void writeBackground(int32 id, const QImage &img);
|
void writeBackground(int32 id, const QImage &img);
|
||||||
bool readBackground();
|
bool readBackground();
|
||||||
|
|
||||||
void writeTheme(const QString &pathRelative, const QString &pathAbsolute, const QByteArray &content, const Window::Theme::Cached &cache);
|
void writeTheme(const Window::Theme::Saved &saved);
|
||||||
void clearTheme();
|
void clearTheme();
|
||||||
bool hasTheme();
|
|
||||||
QString themeAbsolutePath();
|
|
||||||
QString themePaletteAbsolutePath();
|
|
||||||
bool copyThemeColorsToPalette(const QString &file);
|
bool copyThemeColorsToPalette(const QString &file);
|
||||||
|
Window::Theme::Saved readThemeAfterSwitch();
|
||||||
|
|
||||||
void writeLangPack();
|
void writeLangPack();
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "window/themes/window_theme.h"
|
#include "window/themes/window_theme.h"
|
||||||
|
|
||||||
|
#include "window/themes/window_theme_preview.h"
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
#include "storage/localstorage.h"
|
#include "storage/localstorage.h"
|
||||||
#include "base/parse_helper.h"
|
#include "base/parse_helper.h"
|
||||||
|
@ -27,7 +28,8 @@ constexpr auto kNightThemeFile = str_const(":/gui/night.tdesktop-theme");
|
||||||
|
|
||||||
struct Data {
|
struct Data {
|
||||||
struct Applying {
|
struct Applying {
|
||||||
QString path;
|
QString pathRelative;
|
||||||
|
QString pathAbsolute;
|
||||||
QByteArray content;
|
QByteArray content;
|
||||||
QByteArray paletteForRevert;
|
QByteArray paletteForRevert;
|
||||||
Cached cached;
|
Cached cached;
|
||||||
|
@ -195,7 +197,7 @@ void applyBackground(QImage &&background, bool tiled, Instance *out) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool loadThemeFromCache(const QByteArray &content, Cached &cache) {
|
bool loadThemeFromCache(const QByteArray &content, const Cached &cache) {
|
||||||
if (cache.paletteChecksum != style::palette::Checksum()) {
|
if (cache.paletteChecksum != style::palette::Checksum()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -205,8 +207,8 @@ bool loadThemeFromCache(const QByteArray &content, Cached &cache) {
|
||||||
|
|
||||||
QImage background;
|
QImage background;
|
||||||
if (!cache.background.isEmpty()) {
|
if (!cache.background.isEmpty()) {
|
||||||
QBuffer buffer(&cache.background);
|
QDataStream stream(cache.background);
|
||||||
QImageReader reader(&buffer);
|
QImageReader reader(stream.device());
|
||||||
#ifndef OS_MAC_OLD
|
#ifndef OS_MAC_OLD
|
||||||
reader.setAutoTransform(true);
|
reader.setAutoTransform(true);
|
||||||
#endif // OS_MAC_OLD
|
#endif // OS_MAC_OLD
|
||||||
|
@ -364,6 +366,24 @@ void adjustColorsUsingBackground(const QImage &img) {
|
||||||
adjustColor(st::historyScroll.barBgOver, hue, saturation);
|
adjustColor(st::historyScroll.barBgOver, hue, saturation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApplyDefaultWithNightMode(bool nightMode) {
|
||||||
|
if (nightMode) {
|
||||||
|
if (auto preview = PreviewFromFile(NightThemePath())) {
|
||||||
|
Apply(std::move(preview));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
instance.createIfNull();
|
||||||
|
instance->applying.pathRelative = QString();
|
||||||
|
instance->applying.pathAbsolute = QString();
|
||||||
|
instance->applying.content = QByteArray();
|
||||||
|
instance->applying.cached = Cached();
|
||||||
|
if (instance->applying.paletteForRevert.isEmpty()) {
|
||||||
|
instance->applying.paletteForRevert = style::main_palette::save();
|
||||||
|
}
|
||||||
|
Background()->setTestingDefaultTheme();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void ChatBackground::setThemeData(QImage &&themeImage, bool themeTile) {
|
void ChatBackground::setThemeData(QImage &&themeImage, bool themeTile) {
|
||||||
|
@ -380,7 +400,10 @@ void ChatBackground::start() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatBackground::setImage(int32 id, QImage &&image) {
|
void ChatBackground::setImage(int32 id, QImage &&image) {
|
||||||
auto resetPalette = (id == kDefaultBackground && _id != kDefaultBackground && !Local::hasTheme());
|
auto resetPalette = (id == kDefaultBackground)
|
||||||
|
&& (_id != kDefaultBackground)
|
||||||
|
&& !nightMode()
|
||||||
|
&& _themeAbsolutePath.isEmpty();
|
||||||
if (id == kThemeBackground && _themeImage.isNull()) {
|
if (id == kThemeBackground && _themeImage.isNull()) {
|
||||||
id = kDefaultBackground;
|
id = kDefaultBackground;
|
||||||
} else if (resetPalette) {
|
} else if (resetPalette) {
|
||||||
|
@ -392,7 +415,7 @@ void ChatBackground::setImage(int32 id, QImage &&image) {
|
||||||
}
|
}
|
||||||
_id = id;
|
_id = id;
|
||||||
if (_id == kThemeBackground) {
|
if (_id == kThemeBackground) {
|
||||||
_tile = _themeTile;
|
(nightMode() ? _tileNightValue : _tileDayValue) = _themeTile;
|
||||||
setPreparedImage(QImage(_themeImage));
|
setPreparedImage(QImage(_themeImage));
|
||||||
} else if (_id == internal::kTestingThemeBackground
|
} else if (_id == internal::kTestingThemeBackground
|
||||||
|| _id == internal::kTestingDefaultBackground
|
|| _id == internal::kTestingDefaultBackground
|
||||||
|
@ -418,10 +441,10 @@ void ChatBackground::setImage(int32 id, QImage &&image) {
|
||||||
setPreparedImage(prepareBackgroundImage(std::move(image)));
|
setPreparedImage(prepareBackgroundImage(std::move(image)));
|
||||||
}
|
}
|
||||||
Assert(!_pixmap.isNull() && !_pixmapForTiled.isNull());
|
Assert(!_pixmap.isNull() && !_pixmapForTiled.isNull());
|
||||||
notify(BackgroundUpdate(BackgroundUpdate::Type::New, _tile));
|
notify(BackgroundUpdate(BackgroundUpdate::Type::New, tile()));
|
||||||
if (resetPalette) {
|
if (resetPalette) {
|
||||||
notify(BackgroundUpdate(BackgroundUpdate::Type::TestingTheme, _tile), true);
|
notify(BackgroundUpdate(BackgroundUpdate::Type::TestingTheme, tile()), true);
|
||||||
notify(BackgroundUpdate(BackgroundUpdate::Type::ApplyingTheme, _tile), true);
|
notify(BackgroundUpdate(BackgroundUpdate::Type::ApplyingTheme, tile()), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,33 +452,30 @@ void ChatBackground::setPreparedImage(QImage &&image) {
|
||||||
image = std::move(image).convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
image = std::move(image).convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||||
image.setDevicePixelRatio(cRetinaFactor());
|
image.setDevicePixelRatio(cRetinaFactor());
|
||||||
|
|
||||||
auto adjustColors = [this] {
|
auto adjustColors = [&] {
|
||||||
auto someThemeApplied = [] {
|
const auto usingThemeBackground = [&] {
|
||||||
if (AreTestingTheme()) {
|
return (_id == kThemeBackground)
|
||||||
return !instance->applying.path.isEmpty();
|
|| (_id == internal::kTestingThemeBackground);
|
||||||
}
|
|
||||||
return IsNonDefaultUsed() || IsNightTheme();
|
|
||||||
};
|
};
|
||||||
auto usingThemeBackground = [this] {
|
const auto usingDefaultBackground = [&] {
|
||||||
return (_id == kThemeBackground || _id == internal::kTestingThemeBackground);
|
return (_id == kDefaultBackground)
|
||||||
|
|| (_id == internal::kTestingDefaultBackground);
|
||||||
};
|
};
|
||||||
auto usingDefaultBackground = [this] {
|
const auto testingPalette = [&] {
|
||||||
return (_id == kDefaultBackground || _id == internal::kTestingDefaultBackground);
|
const auto path = AreTestingTheme()
|
||||||
};
|
? instance->applying.pathAbsolute
|
||||||
auto testingPalette = [] {
|
: _themeAbsolutePath;
|
||||||
if (AreTestingTheme()) {
|
return IsPaletteTestingPath(path);
|
||||||
return IsPaletteTestingPath(instance->applying.path);
|
|
||||||
}
|
|
||||||
return !Local::themePaletteAbsolutePath().isEmpty();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (someThemeApplied()) {
|
if (testingPalette()) {
|
||||||
return !usingThemeBackground() && !testingPalette();
|
return false;
|
||||||
|
} else if (IsNonDefaultThemeOrBackground() || nightMode()) {
|
||||||
|
return !usingThemeBackground();
|
||||||
}
|
}
|
||||||
return !usingDefaultBackground();
|
return !usingDefaultBackground();
|
||||||
};
|
}();
|
||||||
|
if (adjustColors) {
|
||||||
if (adjustColors()) {
|
|
||||||
adjustColorsUsingBackground(image);
|
adjustColorsUsingBackground(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -494,15 +514,27 @@ int32 ChatBackground::id() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatBackground::tile() const {
|
bool ChatBackground::tile() const {
|
||||||
return _tile;
|
return nightMode() ? _tileNightValue : _tileDayValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChatBackground::tileForSave() const {
|
bool ChatBackground::tileDay() const {
|
||||||
if (_id == internal::kTestingThemeBackground ||
|
if (_id == internal::kTestingThemeBackground ||
|
||||||
_id == internal::kTestingDefaultBackground) {
|
_id == internal::kTestingDefaultBackground) {
|
||||||
return _tileForRevert;
|
if (!nightMode()) {
|
||||||
|
return _tileForRevert;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return tile();
|
return _tileDayValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChatBackground::tileNight() const {
|
||||||
|
if (_id == internal::kTestingThemeBackground ||
|
||||||
|
_id == internal::kTestingDefaultBackground) {
|
||||||
|
if (nightMode()) {
|
||||||
|
return _tileForRevert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _tileNightValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatBackground::ensureStarted() {
|
void ChatBackground::ensureStarted() {
|
||||||
|
@ -515,17 +547,42 @@ void ChatBackground::ensureStarted() {
|
||||||
|
|
||||||
void ChatBackground::setTile(bool tile) {
|
void ChatBackground::setTile(bool tile) {
|
||||||
ensureStarted();
|
ensureStarted();
|
||||||
if (_tile != tile) {
|
const auto old = this->tile();
|
||||||
_tile = tile;
|
if (nightMode()) {
|
||||||
if (_id != internal::kTestingThemeBackground && _id != internal::kTestingDefaultBackground) {
|
setTileNightValue(tile);
|
||||||
|
} else {
|
||||||
|
setTileDayValue(tile);
|
||||||
|
}
|
||||||
|
if (this->tile() != old) {
|
||||||
|
if (_id != internal::kTestingThemeBackground
|
||||||
|
&& _id != internal::kTestingDefaultBackground) {
|
||||||
Local::writeUserSettings();
|
Local::writeUserSettings();
|
||||||
}
|
}
|
||||||
notify(BackgroundUpdate(BackgroundUpdate::Type::Changed, _tile));
|
notify(BackgroundUpdate(BackgroundUpdate::Type::Changed, tile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChatBackground::setTileDayValue(bool tile) {
|
||||||
|
ensureStarted();
|
||||||
|
_tileDayValue = tile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatBackground::setTileNightValue(bool tile) {
|
||||||
|
ensureStarted();
|
||||||
|
_tileNightValue = tile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatBackground::setThemeAbsolutePath(const QString &path) {
|
||||||
|
_themeAbsolutePath = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ChatBackground::themeAbsolutePath() const {
|
||||||
|
return _themeAbsolutePath;
|
||||||
|
}
|
||||||
|
|
||||||
void ChatBackground::reset() {
|
void ChatBackground::reset() {
|
||||||
if (_id == internal::kTestingThemeBackground || _id == internal::kTestingDefaultBackground) {
|
if (_id == internal::kTestingThemeBackground
|
||||||
|
|| _id == internal::kTestingDefaultBackground) {
|
||||||
if (_themeImage.isNull()) {
|
if (_themeImage.isNull()) {
|
||||||
_idForRevert = kDefaultBackground;
|
_idForRevert = kDefaultBackground;
|
||||||
_imageForRevert = QImage();
|
_imageForRevert = QImage();
|
||||||
|
@ -542,10 +599,11 @@ void ChatBackground::reset() {
|
||||||
|
|
||||||
void ChatBackground::saveForRevert() {
|
void ChatBackground::saveForRevert() {
|
||||||
ensureStarted();
|
ensureStarted();
|
||||||
if (_id != internal::kTestingThemeBackground && _id != internal::kTestingDefaultBackground) {
|
if (_id != internal::kTestingThemeBackground
|
||||||
|
&& _id != internal::kTestingDefaultBackground) {
|
||||||
_idForRevert = _id;
|
_idForRevert = _id;
|
||||||
_imageForRevert = std::move(_pixmap).toImage();
|
_imageForRevert = std::move(_pixmap).toImage();
|
||||||
_tileForRevert = _tile;
|
_tileForRevert = tile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,8 +611,10 @@ void ChatBackground::setTestingTheme(Instance &&theme, ChangeMode mode) {
|
||||||
style::main_palette::apply(theme.palette);
|
style::main_palette::apply(theme.palette);
|
||||||
auto switchToThemeBackground = (mode == ChangeMode::SwitchToThemeBackground && !theme.background.isNull())
|
auto switchToThemeBackground = (mode == ChangeMode::SwitchToThemeBackground && !theme.background.isNull())
|
||||||
|| (_id == kThemeBackground)
|
|| (_id == kThemeBackground)
|
||||||
|| (_id == kDefaultBackground && !Local::hasTheme());
|
|| (_id == kDefaultBackground
|
||||||
if (AreTestingTheme() && IsPaletteTestingPath(instance->applying.path)) {
|
&& !nightMode()
|
||||||
|
&& _themeAbsolutePath.isEmpty());
|
||||||
|
if (AreTestingTheme() && IsPaletteTestingPath(instance->applying.pathAbsolute)) {
|
||||||
// Grab current background image if it is not already custom
|
// Grab current background image if it is not already custom
|
||||||
if (_id != kCustomBackground) {
|
if (_id != kCustomBackground) {
|
||||||
saveForRevert();
|
saveForRevert();
|
||||||
|
@ -568,47 +628,61 @@ void ChatBackground::setTestingTheme(Instance &&theme, ChangeMode mode) {
|
||||||
// Apply current background image so that service bg colors are recounted.
|
// Apply current background image so that service bg colors are recounted.
|
||||||
setImage(_id, std::move(_pixmap).toImage());
|
setImage(_id, std::move(_pixmap).toImage());
|
||||||
}
|
}
|
||||||
notify(BackgroundUpdate(BackgroundUpdate::Type::TestingTheme, _tile), true);
|
notify(BackgroundUpdate(BackgroundUpdate::Type::TestingTheme, tile()), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatBackground::setTestingDefaultTheme() {
|
void ChatBackground::setTestingDefaultTheme() {
|
||||||
style::main_palette::reset();
|
style::main_palette::reset();
|
||||||
if (_id == kThemeBackground) {
|
saveForRevert();
|
||||||
saveForRevert();
|
setImage(internal::kTestingDefaultBackground);
|
||||||
setImage(internal::kTestingDefaultBackground);
|
setTile(false);
|
||||||
setTile(false);
|
notify(BackgroundUpdate(BackgroundUpdate::Type::TestingTheme, tile()), true);
|
||||||
} else {
|
|
||||||
// Apply current background image so that service bg colors are recounted.
|
|
||||||
setImage(_id, std::move(_pixmap).toImage());
|
|
||||||
}
|
|
||||||
notify(BackgroundUpdate(BackgroundUpdate::Type::TestingTheme, _tile), true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatBackground::keepApplied() {
|
void ChatBackground::keepApplied(const QString &path, bool write) {
|
||||||
|
setThemeAbsolutePath(path);
|
||||||
if (_id == internal::kTestingEditorBackground) {
|
if (_id == internal::kTestingEditorBackground) {
|
||||||
_id = kCustomBackground;
|
_id = kCustomBackground;
|
||||||
_themeImage = QImage();
|
_themeImage = QImage();
|
||||||
_themeTile = false;
|
_themeTile = false;
|
||||||
writeNewBackgroundSettings();
|
if (write) {
|
||||||
|
writeNewBackgroundSettings();
|
||||||
|
}
|
||||||
} else if (_id == internal::kTestingThemeBackground) {
|
} else if (_id == internal::kTestingThemeBackground) {
|
||||||
_id = kThemeBackground;
|
_id = kThemeBackground;
|
||||||
_themeImage = _pixmap.toImage();
|
_themeImage = _pixmap.toImage();
|
||||||
_themeTile = _tile;
|
_themeTile = tile();
|
||||||
writeNewBackgroundSettings();
|
if (write) {
|
||||||
|
writeNewBackgroundSettings();
|
||||||
|
}
|
||||||
} else if (_id == internal::kTestingDefaultBackground) {
|
} else if (_id == internal::kTestingDefaultBackground) {
|
||||||
_id = kDefaultBackground;
|
_id = kDefaultBackground;
|
||||||
_themeImage = QImage();
|
_themeImage = QImage();
|
||||||
_themeTile = false;
|
_themeTile = false;
|
||||||
writeNewBackgroundSettings();
|
if (write) {
|
||||||
|
writeNewBackgroundSettings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
notify(BackgroundUpdate(BackgroundUpdate::Type::ApplyingTheme, _tile), true);
|
notify(BackgroundUpdate(BackgroundUpdate::Type::ApplyingTheme, tile()), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChatBackground::isNonDefaultThemeOrBackground() const {
|
||||||
|
return nightMode()
|
||||||
|
? (_themeAbsolutePath != NightThemePath()
|
||||||
|
|| _id != kThemeBackground)
|
||||||
|
: (!_themeAbsolutePath.isEmpty()
|
||||||
|
|| _id != kDefaultBackground);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatBackground::writeNewBackgroundSettings() {
|
void ChatBackground::writeNewBackgroundSettings() {
|
||||||
if (_tile != _tileForRevert) {
|
if (tile() != _tileForRevert) {
|
||||||
Local::writeUserSettings();
|
Local::writeUserSettings();
|
||||||
}
|
}
|
||||||
Local::writeBackground(_id, (_id == kThemeBackground || _id == kDefaultBackground) ? QImage() : _pixmap.toImage());
|
Local::writeBackground(
|
||||||
|
_id,
|
||||||
|
((_id == kThemeBackground || _id == kDefaultBackground)
|
||||||
|
? QImage()
|
||||||
|
: _pixmap.toImage()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChatBackground::revert() {
|
void ChatBackground::revert() {
|
||||||
|
@ -621,30 +695,100 @@ void ChatBackground::revert() {
|
||||||
// Apply current background image so that service bg colors are recounted.
|
// Apply current background image so that service bg colors are recounted.
|
||||||
setImage(_id, std::move(_pixmap).toImage());
|
setImage(_id, std::move(_pixmap).toImage());
|
||||||
}
|
}
|
||||||
notify(BackgroundUpdate(BackgroundUpdate::Type::RevertingTheme, _tile), true);
|
notify(BackgroundUpdate(BackgroundUpdate::Type::RevertingTheme, tile()), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChatBackground::setNightModeValue(bool nightMode) {
|
||||||
|
_nightMode = nightMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChatBackground::nightMode() const {
|
||||||
|
return _nightMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatBackground::toggleNightMode() {
|
||||||
|
const auto oldNightMode = _nightMode;
|
||||||
|
const auto newNightMode = !_nightMode;
|
||||||
|
_nightMode = newNightMode;
|
||||||
|
auto read = Local::readThemeAfterSwitch();
|
||||||
|
auto path = read.pathAbsolute;
|
||||||
|
|
||||||
|
_nightMode = oldNightMode;
|
||||||
|
auto oldTileValue = (_nightMode ? _tileNightValue : _tileDayValue);
|
||||||
|
const auto applied = [&] {
|
||||||
|
if (read.content.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto preview = std::make_unique<Preview>();
|
||||||
|
preview->pathAbsolute = std::move(read.pathAbsolute);
|
||||||
|
preview->pathRelative = std::move(read.pathRelative);
|
||||||
|
preview->content = std::move(read.content);
|
||||||
|
preview->instance.cached = std::move(read.cache);
|
||||||
|
const auto loaded = loadTheme(
|
||||||
|
preview->content,
|
||||||
|
preview->instance.cached,
|
||||||
|
&preview->instance);
|
||||||
|
if (!loaded) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Apply(std::move(preview));
|
||||||
|
return true;
|
||||||
|
}();
|
||||||
|
if (!applied) {
|
||||||
|
path = newNightMode ? NightThemePath() : QString();
|
||||||
|
ApplyDefaultWithNightMode(newNightMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Theme editor could have already reverted the testing of this toggle.
|
||||||
|
if (AreTestingTheme()) {
|
||||||
|
_nightMode = newNightMode;
|
||||||
|
if (oldNightMode) {
|
||||||
|
_tileDayValue = _tileNightValue;
|
||||||
|
_tileNightValue = oldTileValue;
|
||||||
|
} else {
|
||||||
|
_tileNightValue = _tileDayValue;
|
||||||
|
_tileDayValue = oldTileValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't call full KeepApplied() here, because
|
||||||
|
// we don't need to write theme or overwrite current background.
|
||||||
|
instance->applying = Data::Applying();
|
||||||
|
Local::writeSettings();
|
||||||
|
keepApplied(path, false);
|
||||||
|
if (tile() != _tileForRevert) {
|
||||||
|
Local::writeUserSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Local::readBackground()) {
|
||||||
|
setImage(kThemeBackground);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ChatBackground *Background() {
|
ChatBackground *Background() {
|
||||||
instance.createIfNull();
|
instance.createIfNull();
|
||||||
return &instance->background;
|
return &instance->background;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Load(const QString &pathRelative, const QString &pathAbsolute, const QByteArray &content, Cached &cache) {
|
bool Load(Saved &&saved) {
|
||||||
if (content.size() < 4) {
|
if (saved.content.size() < 4) {
|
||||||
LOG(("Theme Error: Could not load theme from '%1' (%2)").arg(pathRelative).arg(pathAbsolute));
|
LOG(("Theme Error: Could not load theme from '%1' (%2)"
|
||||||
|
).arg(saved.pathRelative
|
||||||
|
).arg(saved.pathAbsolute));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.createIfNull();
|
instance.createIfNull();
|
||||||
if (loadThemeFromCache(content, cache)) {
|
if (loadThemeFromCache(saved.content, saved.cache)) {
|
||||||
|
Background()->setThemeAbsolutePath(saved.pathAbsolute);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!loadTheme(content, cache)) {
|
if (!loadTheme(saved.content, saved.cache)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Local::writeTheme(pathRelative, pathAbsolute, content, cache);
|
Local::writeTheme(saved);
|
||||||
|
Background()->setThemeAbsolutePath(saved.pathAbsolute);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -653,38 +797,16 @@ void Unload() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Apply(const QString &filepath) {
|
bool Apply(const QString &filepath) {
|
||||||
auto preview = std::make_unique<Preview>();
|
if (auto preview = PreviewFromFile(filepath)) {
|
||||||
preview->path = filepath;
|
return Apply(std::move(preview));
|
||||||
if (!LoadFromFile(preview->path, &preview->instance, &preview->content)) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return Apply(std::move(preview));
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
void SwitchNightTheme(bool enabled) {
|
|
||||||
if (enabled) {
|
|
||||||
auto preview = std::make_unique<Preview>();
|
|
||||||
preview->path = str_const_toString(kNightThemeFile);
|
|
||||||
if (!LoadFromFile(preview->path, &preview->instance, &preview->content)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
instance.createIfNull();
|
|
||||||
instance->applying.path = std::move(preview->path);
|
|
||||||
instance->applying.content = std::move(preview->content);
|
|
||||||
instance->applying.cached = std::move(preview->instance.cached);
|
|
||||||
if (instance->applying.paletteForRevert.isEmpty()) {
|
|
||||||
instance->applying.paletteForRevert = style::main_palette::save();
|
|
||||||
}
|
|
||||||
Background()->setTestingTheme(std::move(preview->instance), ChatBackground::ChangeMode::LeaveCurrentCustomBackground);
|
|
||||||
} else {
|
|
||||||
Window::Theme::ApplyDefault();
|
|
||||||
}
|
|
||||||
KeepApplied();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Apply(std::unique_ptr<Preview> preview) {
|
bool Apply(std::unique_ptr<Preview> preview) {
|
||||||
instance.createIfNull();
|
instance.createIfNull();
|
||||||
instance->applying.path = std::move(preview->path);
|
instance->applying.pathRelative = std::move(preview->pathRelative);
|
||||||
|
instance->applying.pathAbsolute = std::move(preview->pathAbsolute);
|
||||||
instance->applying.content = std::move(preview->content);
|
instance->applying.content = std::move(preview->content);
|
||||||
instance->applying.cached = std::move(preview->instance.cached);
|
instance->applying.cached = std::move(preview->instance.cached);
|
||||||
if (instance->applying.paletteForRevert.isEmpty()) {
|
if (instance->applying.paletteForRevert.isEmpty()) {
|
||||||
|
@ -695,14 +817,7 @@ bool Apply(std::unique_ptr<Preview> preview) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyDefault() {
|
void ApplyDefault() {
|
||||||
instance.createIfNull();
|
ApplyDefaultWithNightMode(IsNightMode());
|
||||||
instance->applying.path = QString();
|
|
||||||
instance->applying.content = QByteArray();
|
|
||||||
instance->applying.cached = Cached();
|
|
||||||
if (instance->applying.paletteForRevert.isEmpty()) {
|
|
||||||
instance->applying.paletteForRevert = style::main_palette::save();
|
|
||||||
}
|
|
||||||
Background()->setTestingDefaultTheme();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ApplyEditedPalette(const QString &path, const QByteArray &content) {
|
bool ApplyEditedPalette(const QString &path, const QByteArray &content) {
|
||||||
|
@ -715,7 +830,12 @@ bool ApplyEditedPalette(const QString &path, const QByteArray &content) {
|
||||||
out.cached.contentChecksum = hashCrc32(content.constData(), content.size());
|
out.cached.contentChecksum = hashCrc32(content.constData(), content.size());
|
||||||
|
|
||||||
instance.createIfNull();
|
instance.createIfNull();
|
||||||
instance->applying.path = path;
|
instance->applying.pathRelative = path.isEmpty()
|
||||||
|
? QString()
|
||||||
|
: QDir().relativeFilePath(path);
|
||||||
|
instance->applying.pathAbsolute = path.isEmpty()
|
||||||
|
? QString()
|
||||||
|
: QFileInfo(path).absoluteFilePath();
|
||||||
instance->applying.content = content;
|
instance->applying.content = content;
|
||||||
instance->applying.cached = out.cached;
|
instance->applying.cached = out.cached;
|
||||||
if (instance->applying.paletteForRevert.isEmpty()) {
|
if (instance->applying.paletteForRevert.isEmpty()) {
|
||||||
|
@ -727,31 +847,52 @@ bool ApplyEditedPalette(const QString &path, const QByteArray &content) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeepApplied() {
|
void KeepApplied() {
|
||||||
if (!instance) {
|
if (!AreTestingTheme()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto filepath = instance->applying.path;
|
auto saved = Saved();
|
||||||
auto pathRelative = filepath.isEmpty() ? QString() : QDir().relativeFilePath(filepath);
|
saved.pathRelative = instance->applying.pathRelative;
|
||||||
auto pathAbsolute = filepath.isEmpty() ? QString() : QFileInfo(filepath).absoluteFilePath();
|
saved.pathAbsolute = instance->applying.pathAbsolute;
|
||||||
Local::writeTheme(pathRelative, pathAbsolute, instance->applying.content, instance->applying.cached);
|
saved.content = std::move(instance->applying.content);
|
||||||
|
saved.cache = std::move(instance->applying.cached);
|
||||||
|
Local::writeTheme(saved);
|
||||||
instance->applying = Data::Applying();
|
instance->applying = Data::Applying();
|
||||||
Background()->keepApplied();
|
Background()->keepApplied(saved.pathAbsolute, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Revert() {
|
void Revert() {
|
||||||
if (!instance->applying.paletteForRevert.isEmpty()) {
|
if (!AreTestingTheme()) {
|
||||||
style::main_palette::load(instance->applying.paletteForRevert);
|
return;
|
||||||
}
|
}
|
||||||
|
style::main_palette::load(instance->applying.paletteForRevert);
|
||||||
instance->applying = Data::Applying();
|
instance->applying = Data::Applying();
|
||||||
Background()->revert();
|
Background()->revert();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsNightTheme() {
|
QString NightThemePath() {
|
||||||
return (Local::themeAbsolutePath() == str_const_toString(kNightThemeFile));
|
return str_const_toString(kNightThemeFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsNonDefaultUsed() {
|
bool IsNonDefaultThemeOrBackground() {
|
||||||
return Local::hasTheme() && !IsNightTheme();
|
return Background()->isNonDefaultThemeOrBackground();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsNightMode() {
|
||||||
|
return instance ? Background()->nightMode() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNightModeValue(bool nightMode) {
|
||||||
|
if (instance || nightMode) {
|
||||||
|
Background()->setNightModeValue(nightMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ToggleNightMode() {
|
||||||
|
Background()->toggleNightMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SuggestThemeReset() {
|
||||||
|
return IsNonDefaultThemeOrBackground();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadFromFile(const QString &path, Instance *out, QByteArray *outContent) {
|
bool LoadFromFile(const QString &path, Instance *out, QByteArray *outContent) {
|
||||||
|
|
|
@ -30,7 +30,13 @@ struct Cached {
|
||||||
int32 paletteChecksum = 0;
|
int32 paletteChecksum = 0;
|
||||||
int32 contentChecksum = 0;
|
int32 contentChecksum = 0;
|
||||||
};
|
};
|
||||||
bool Load(const QString &pathRelative, const QString &pathAbsolute, const QByteArray &content, Cached &cache);
|
struct Saved {
|
||||||
|
QString pathRelative;
|
||||||
|
QString pathAbsolute;
|
||||||
|
QByteArray content;
|
||||||
|
Cached cache;
|
||||||
|
};
|
||||||
|
bool Load(Saved &&saved);
|
||||||
void Unload();
|
void Unload();
|
||||||
|
|
||||||
struct Instance {
|
struct Instance {
|
||||||
|
@ -41,7 +47,8 @@ struct Instance {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Preview {
|
struct Preview {
|
||||||
QString path;
|
QString pathRelative;
|
||||||
|
QString pathAbsolute;
|
||||||
Instance instance;
|
Instance instance;
|
||||||
QByteArray content;
|
QByteArray content;
|
||||||
QImage preview;
|
QImage preview;
|
||||||
|
@ -52,9 +59,12 @@ bool Apply(std::unique_ptr<Preview> preview);
|
||||||
void ApplyDefault();
|
void ApplyDefault();
|
||||||
bool ApplyEditedPalette(const QString &path, const QByteArray &content);
|
bool ApplyEditedPalette(const QString &path, const QByteArray &content);
|
||||||
void KeepApplied();
|
void KeepApplied();
|
||||||
bool IsNonDefaultUsed();
|
QString NightThemePath();
|
||||||
bool IsNightTheme();
|
bool IsNightMode();
|
||||||
void SwitchNightTheme(bool enabled);
|
void SetNightModeValue(bool nightMode);
|
||||||
|
void ToggleNightMode();
|
||||||
|
bool IsNonDefaultThemeOrBackground();
|
||||||
|
bool SuggestThemeReset();
|
||||||
void Revert();
|
void Revert();
|
||||||
|
|
||||||
bool LoadFromFile(const QString &file, Instance *out, QByteArray *outContent);
|
bool LoadFromFile(const QString &file, Instance *out, QByteArray *outContent);
|
||||||
|
@ -88,6 +98,10 @@ public:
|
||||||
void start();
|
void start();
|
||||||
void setImage(int32 id, QImage &&image = QImage());
|
void setImage(int32 id, QImage &&image = QImage());
|
||||||
void setTile(bool tile);
|
void setTile(bool tile);
|
||||||
|
void setTileDayValue(bool tile);
|
||||||
|
void setTileNightValue(bool tile);
|
||||||
|
void setThemeAbsolutePath(const QString &path);
|
||||||
|
QString themeAbsolutePath() const;
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
enum class ChangeMode {
|
enum class ChangeMode {
|
||||||
|
@ -96,7 +110,6 @@ public:
|
||||||
};
|
};
|
||||||
void setTestingTheme(Instance &&theme, ChangeMode mode = ChangeMode::SwitchToThemeBackground);
|
void setTestingTheme(Instance &&theme, ChangeMode mode = ChangeMode::SwitchToThemeBackground);
|
||||||
void setTestingDefaultTheme();
|
void setTestingDefaultTheme();
|
||||||
void keepApplied();
|
|
||||||
void revert();
|
void revert();
|
||||||
|
|
||||||
int32 id() const;
|
int32 id() const;
|
||||||
|
@ -107,7 +120,8 @@ public:
|
||||||
return _pixmapForTiled;
|
return _pixmapForTiled;
|
||||||
}
|
}
|
||||||
bool tile() const;
|
bool tile() const;
|
||||||
bool tileForSave() const;
|
bool tileDay() const;
|
||||||
|
bool tileNight() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ensureStarted();
|
void ensureStarted();
|
||||||
|
@ -115,11 +129,26 @@ private:
|
||||||
void setPreparedImage(QImage &&image);
|
void setPreparedImage(QImage &&image);
|
||||||
void writeNewBackgroundSettings();
|
void writeNewBackgroundSettings();
|
||||||
|
|
||||||
|
void setNightModeValue(bool nightMode);
|
||||||
|
bool nightMode() const;
|
||||||
|
void toggleNightMode();
|
||||||
|
void keepApplied(const QString &path, bool write);
|
||||||
|
bool isNonDefaultThemeOrBackground() const;
|
||||||
|
|
||||||
|
friend bool IsNightMode();
|
||||||
|
friend void SetNightModeValue(bool nightMode);
|
||||||
|
friend void ToggleNightMode();
|
||||||
|
friend void KeepApplied();
|
||||||
|
friend bool IsNonDefaultThemeOrBackground();
|
||||||
|
|
||||||
int32 _id = internal::kUninitializedBackground;
|
int32 _id = internal::kUninitializedBackground;
|
||||||
QPixmap _pixmap;
|
QPixmap _pixmap;
|
||||||
QPixmap _pixmapForTiled;
|
QPixmap _pixmapForTiled;
|
||||||
bool _tile = false;
|
bool _nightMode = false;
|
||||||
|
bool _tileDayValue = false;
|
||||||
|
bool _tileNightValue = true;
|
||||||
|
|
||||||
|
QString _themeAbsolutePath;
|
||||||
QImage _themeImage;
|
QImage _themeImage;
|
||||||
bool _themeTile = false;
|
bool _themeTile = false;
|
||||||
|
|
||||||
|
|
|
@ -785,9 +785,9 @@ void Editor::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::Start() {
|
void Editor::Start() {
|
||||||
auto palettePath = Local::themePaletteAbsolutePath();
|
const auto path = Background()->themeAbsolutePath();
|
||||||
if (palettePath.isEmpty()) {
|
if (path.isEmpty() || !Window::Theme::IsPaletteTestingPath(path)) {
|
||||||
FileDialog::GetWritePath(App::wnd(), lang(lng_theme_editor_save_palette), "Palette (*.tdesktop-palette)", "colors.tdesktop-palette", [](const QString &path) {
|
const auto start = [](const QString &path) {
|
||||||
if (!Local::copyThemeColorsToPalette(path)) {
|
if (!Local::copyThemeColorsToPalette(path)) {
|
||||||
writeDefaultPalette(path);
|
writeDefaultPalette(path);
|
||||||
}
|
}
|
||||||
|
@ -799,9 +799,15 @@ void Editor::Start() {
|
||||||
if (auto window = App::wnd()) {
|
if (auto window = App::wnd()) {
|
||||||
window->showRightColumn(Box<Editor>(path));
|
window->showRightColumn(Box<Editor>(path));
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
FileDialog::GetWritePath(
|
||||||
|
App::wnd(),
|
||||||
|
lang(lng_theme_editor_save_palette),
|
||||||
|
"Palette (*.tdesktop-palette)",
|
||||||
|
"colors.tdesktop-palette",
|
||||||
|
start);
|
||||||
} else if (auto window = App::wnd()) {
|
} else if (auto window = App::wnd()) {
|
||||||
window->showRightColumn(Box<Editor>(palettePath));
|
window->showRightColumn(Box<Editor>(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -889,12 +889,25 @@ void Generator::restoreTextPalette() {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
std::unique_ptr<Preview> PreviewFromFile(const QString &filepath) {
|
||||||
|
auto result = std::make_unique<Preview>();
|
||||||
|
result->pathRelative = filepath.isEmpty()
|
||||||
|
? QString()
|
||||||
|
: QDir().relativeFilePath(filepath);
|
||||||
|
result->pathAbsolute = filepath.isEmpty()
|
||||||
|
? QString()
|
||||||
|
: QFileInfo(filepath).absoluteFilePath();
|
||||||
|
if (!LoadFromFile(filepath, &result->instance, &result->content)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<Preview> GeneratePreview(
|
std::unique_ptr<Preview> GeneratePreview(
|
||||||
const QString &filepath,
|
const QString &filepath,
|
||||||
CurrentData &&data) {
|
CurrentData &&data) {
|
||||||
auto result = std::make_unique<Preview>();
|
auto result = PreviewFromFile(filepath);
|
||||||
result->path = filepath;
|
if (!result) {
|
||||||
if (!LoadFromFile(filepath, &result->instance, &result->content)) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
result->preview = Generator(
|
result->preview = Generator(
|
||||||
|
|
|
@ -18,6 +18,7 @@ struct CurrentData {
|
||||||
bool backgroundTiled = false;
|
bool backgroundTiled = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<Preview> PreviewFromFile(const QString &filepath);
|
||||||
std::unique_ptr<Preview> GeneratePreview(
|
std::unique_ptr<Preview> GeneratePreview(
|
||||||
const QString &filepath,
|
const QString &filepath,
|
||||||
CurrentData &&data);
|
CurrentData &&data);
|
||||||
|
|
|
@ -44,9 +44,10 @@ MainMenu::MainMenu(
|
||||||
checkSelf();
|
checkSelf();
|
||||||
|
|
||||||
_nightThemeSwitch.setCallback([this] {
|
_nightThemeSwitch.setCallback([this] {
|
||||||
if (auto action = *_nightThemeAction) {
|
if (const auto action = *_nightThemeAction) {
|
||||||
if (action->isChecked() != Window::Theme::IsNightTheme()) {
|
const auto nightMode = Window::Theme::IsNightMode();
|
||||||
Window::Theme::SwitchNightTheme(action->isChecked());
|
if (action->isChecked() != nightMode) {
|
||||||
|
Window::Theme::ToggleNightMode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -104,19 +105,17 @@ void MainMenu::refreshMenu() {
|
||||||
App::wnd()->showSettings();
|
App::wnd()->showSettings();
|
||||||
}, &st::mainMenuSettings, &st::mainMenuSettingsOver);
|
}, &st::mainMenuSettings, &st::mainMenuSettingsOver);
|
||||||
|
|
||||||
if (!Window::Theme::IsNonDefaultUsed()) {
|
_nightThemeAction = std::make_shared<QPointer<QAction>>(nullptr);
|
||||||
_nightThemeAction = std::make_shared<QPointer<QAction>>(nullptr);
|
auto action = _menu->addAction(lang(lng_menu_night_mode), [this] {
|
||||||
auto action = _menu->addAction(lang(lng_menu_night_mode), [this] {
|
if (auto action = *_nightThemeAction) {
|
||||||
if (auto action = *_nightThemeAction) {
|
action->setChecked(!action->isChecked());
|
||||||
action->setChecked(!action->isChecked());
|
_nightThemeSwitch.callOnce(st::mainMenu.itemToggle.duration);
|
||||||
_nightThemeSwitch.callOnce(st::mainMenu.itemToggle.duration);
|
}
|
||||||
}
|
}, &st::mainMenuNightMode, &st::mainMenuNightModeOver);
|
||||||
}, &st::mainMenuNightMode, &st::mainMenuNightModeOver);
|
*_nightThemeAction = action;
|
||||||
*_nightThemeAction = action;
|
action->setCheckable(true);
|
||||||
action->setCheckable(true);
|
action->setChecked(Window::Theme::IsNightMode());
|
||||||
action->setChecked(Window::Theme::IsNightTheme());
|
_menu->finishAnimating();
|
||||||
_menu->finishAnimating();
|
|
||||||
}
|
|
||||||
|
|
||||||
updatePhone();
|
updatePhone();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue