Save embedded themes accent colors.

This commit is contained in:
John Preston 2019-08-23 16:52:59 +03:00
parent 7de28fc4bd
commit c2117e7722
18 changed files with 1484 additions and 1019 deletions

View File

@ -336,6 +336,10 @@ bool Application::eventFilter(QObject *object, QEvent *e) {
return QObject::eventFilter(object, e);
}
void Application::saveSettingsDelayed(crl::time delay) {
_saveSettingsTimer.callOnce(delay);
}
void Application::setCurrentProxy(
const ProxyData &proxy,
ProxyData::Settings settings) {
@ -381,6 +385,7 @@ void Application::startLocalStorage() {
}
}
});
_saveSettingsTimer.setCallback([=] { Local::writeSettings(); });
}
void Application::forceLogOut(const TextWithEntities &explanation) {

View File

@ -7,8 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "base/observer.h"
#include "core/core_settings.h"
#include "mtproto/auth_key.h"
#include "base/observer.h"
#include "base/timer.h"
class MainWindow;
@ -94,9 +95,6 @@ public:
bool closeActiveWindow();
bool minimizeActiveWindow();
QWidget *getFileDialogParent();
QWidget *getGlobalShortcutParent() {
return &_globalShortcutParent;
}
// Media view interface.
void checkMediaViewActivation();
@ -115,7 +113,13 @@ public:
return _logoNoMargin;
}
// MTProto components.
[[nodiscard]] Settings &settings() {
return _settings;
}
void moveSettingsFrom(Settings &&other);
void saveSettingsDelayed(crl::time delay = kDefaultSaveDelay);
// Dc options and proxy.
MTP::DcOptions *dcOptions() {
return _dcOptions.get();
}
@ -221,6 +225,8 @@ protected:
bool eventFilter(QObject *object, QEvent *event) override;
private:
static constexpr auto kDefaultSaveDelay = crl::time(1000);
friend bool IsAppLaunched();
friend Application &App();
@ -251,8 +257,7 @@ private:
// Some fields are just moved from the declaration.
struct Private;
const std::unique_ptr<Private> _private;
QWidget _globalShortcutParent;
Settings _settings;
const std::unique_ptr<Storage::Databases> _databases;
const std::unique_ptr<Ui::Animations::Manager> _animationsManager;
@ -276,6 +281,7 @@ private:
std::unique_ptr<Window::TermsLock> _termsLock;
base::DelayedCallTimer _callDelayedTimer;
base::Timer _saveSettingsTimer;
struct LeaveSubscription {
LeaveSubscription(

View File

@ -0,0 +1,51 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "core/core_settings.h"
#include "storage/serialize_common.h"
namespace Core {
Settings::Variables::Variables() {
}
QByteArray Settings::serialize() const {
const auto themesAccentColors = _variables.themesAccentColors.serialize();
auto size = Serialize::bytearraySize(themesAccentColors);
auto result = QByteArray();
result.reserve(size);
{
QDataStream stream(&result, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_5_1);
stream << themesAccentColors;
}
return result;
}
void Settings::constructFromSerialized(const QByteArray &serialized) {
if (serialized.isEmpty()) {
return;
}
QDataStream stream(serialized);
stream.setVersion(QDataStream::Qt_5_1);
QByteArray themesAccentColors;
stream >> themesAccentColors;
if (stream.status() != QDataStream::Ok) {
LOG(("App Error: "
"Bad data for Core::Settings::constructFromSerialized()"));
return;
}
if (!_variables.themesAccentColors.setFromSerialized(themesAccentColors)) {
return;
}
}
} // namespace Core

View File

@ -0,0 +1,40 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "window/themes/window_themes_embedded.h"
namespace Core {
class Settings final {
public:
void moveFrom(Settings &&other) {
_variables = std::move(other._variables);
}
[[nodiscard]] QByteArray serialize() const;
void constructFromSerialized(const QByteArray &serialized);
void setThemesAccentColors(Window::Theme::AccentColors &&colors) {
_variables.themesAccentColors = std::move(colors);
}
[[nodiscard]] Window::Theme::AccentColors &themesAccentColors() {
return _variables.themesAccentColors;
}
private:
struct Variables {
Variables();
Window::Theme::AccentColors themesAccentColors;
};
Variables _variables;
};
} // namespace Core

View File

@ -1587,7 +1587,7 @@ void UpdateApplication() {
Window::SectionShow());
} else {
window->showSpecialLayer(
Box<Settings::LayerWidget>(),
Box<::Settings::LayerWidget>(),
anim::type::normal);
}
window->showFromTray();

View File

@ -12,23 +12,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/changelogs.h"
#include "main/main_account.h"
#include "main/main_app_config.h"
#include "chat_helpers/stickers_emoji_pack.h"
#include "storage/file_download.h"
#include "storage/file_upload.h"
#include "storage/localstorage.h"
#include "storage/storage_facade.h"
#include "storage/serialize_common.h"
#include "data/data_session.h"
#include "data/data_user.h"
#include "window/notifications_manager.h"
#include "window/themes/window_theme.h"
#include "platform/platform_specific.h"
//#include "platform/platform_specific.h"
#include "calls/calls_instance.h"
#include "window/section_widget.h"
#include "chat_helpers/tabbed_selector.h"
#include "chat_helpers/stickers_emoji_pack.h"
#include "boxes/send_files_box.h"
#include "ui/widgets/input_fields.h"
#include "support/support_common.h"
#include "support/support_helper.h"
#include "observer_peer.h"
@ -40,475 +34,11 @@ constexpr auto kLegacyCallsPeerToPeerNobody = 4;
} // namespace
Settings::Variables::Variables()
: sendFilesWay(SendFilesWay::Album)
, selectorTab(ChatHelpers::SelectorTab::Emoji)
, floatPlayerColumn(Window::Column::Second)
, floatPlayerCorner(RectPart::TopRight)
, sendSubmitWay(Ui::InputSubmitSettings::Enter)
, supportSwitch(Support::SwitchSettings::Next) {
}
QByteArray Settings::serialize() const {
const auto autoDownload = _variables.autoDownload.serialize();
auto size = sizeof(qint32) * 30;
for (auto i = _variables.soundOverrides.cbegin(), e = _variables.soundOverrides.cend(); i != e; ++i) {
size += Serialize::stringSize(i.key()) + Serialize::stringSize(i.value());
}
size += _variables.groupStickersSectionHidden.size() * sizeof(quint64);
size += Serialize::bytearraySize(autoDownload);
auto result = QByteArray();
result.reserve(size);
{
QDataStream stream(&result, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_5_1);
stream << static_cast<qint32>(_variables.selectorTab);
stream << qint32(_variables.lastSeenWarningSeen ? 1 : 0);
stream << qint32(_variables.tabbedSelectorSectionEnabled ? 1 : 0);
stream << qint32(_variables.soundOverrides.size());
for (auto i = _variables.soundOverrides.cbegin(), e = _variables.soundOverrides.cend(); i != e; ++i) {
stream << i.key() << i.value();
}
stream << qint32(_variables.tabbedSelectorSectionTooltipShown);
stream << qint32(_variables.floatPlayerColumn);
stream << qint32(_variables.floatPlayerCorner);
stream << qint32(_variables.groupStickersSectionHidden.size());
for (auto peerId : _variables.groupStickersSectionHidden) {
stream << quint64(peerId);
}
stream << qint32(_variables.thirdSectionInfoEnabled ? 1 : 0);
stream << qint32(_variables.smallDialogsList ? 1 : 0);
stream << qint32(snap(
qRound(_variables.dialogsWidthRatio.current() * 1000000),
0,
1000000));
stream << qint32(_variables.thirdColumnWidth.current());
stream << qint32(_variables.thirdSectionExtendedBy);
stream << qint32(_variables.sendFilesWay);
stream << qint32(0);// LEGACY _variables.callsPeerToPeer.current());
stream << qint32(_variables.sendSubmitWay);
stream << qint32(_variables.supportSwitch);
stream << qint32(_variables.supportFixChatsOrder ? 1 : 0);
stream << qint32(_variables.supportTemplatesAutocomplete ? 1 : 0);
stream << qint32(_variables.supportChatsTimeSlice.current());
stream << qint32(_variables.includeMutedCounter ? 1 : 0);
stream << qint32(_variables.countUnreadMessages ? 1 : 0);
stream << qint32(_variables.exeLaunchWarning ? 1 : 0);
stream << autoDownload;
stream << qint32(_variables.supportAllSearchResults.current() ? 1 : 0);
stream << qint32(_variables.archiveCollapsed.current() ? 1 : 0);
stream << qint32(_variables.notifyAboutPinned.current() ? 1 : 0);
stream << qint32(_variables.archiveInMainMenu.current() ? 1 : 0);
stream << qint32(_variables.skipArchiveInSearch.current() ? 1 : 0);
stream << qint32(_variables.autoplayGifs ? 1 : 0);
stream << qint32(_variables.loopAnimatedStickers ? 1 : 0);
stream << qint32(_variables.largeEmoji.current() ? 1 : 0);
stream << qint32(_variables.replaceEmoji.current() ? 1 : 0);
stream << qint32(_variables.suggestEmoji ? 1 : 0);
stream << qint32(_variables.suggestStickersByEmoji ? 1 : 0);
}
return result;
}
void Settings::constructFromSerialized(const QByteArray &serialized) {
if (serialized.isEmpty()) {
return;
}
QDataStream stream(serialized);
stream.setVersion(QDataStream::Qt_5_1);
qint32 selectorTab = static_cast<qint32>(ChatHelpers::SelectorTab::Emoji);
qint32 lastSeenWarningSeen = 0;
qint32 tabbedSelectorSectionEnabled = 1;
qint32 tabbedSelectorSectionTooltipShown = 0;
qint32 floatPlayerColumn = static_cast<qint32>(Window::Column::Second);
qint32 floatPlayerCorner = static_cast<qint32>(RectPart::TopRight);
QMap<QString, QString> soundOverrides;
base::flat_set<PeerId> groupStickersSectionHidden;
qint32 thirdSectionInfoEnabled = 0;
qint32 smallDialogsList = 0;
float64 dialogsWidthRatio = _variables.dialogsWidthRatio.current();
int thirdColumnWidth = _variables.thirdColumnWidth.current();
int thirdSectionExtendedBy = _variables.thirdSectionExtendedBy;
qint32 sendFilesWay = static_cast<qint32>(_variables.sendFilesWay);
qint32 legacyCallsPeerToPeer = qint32(0);
qint32 sendSubmitWay = static_cast<qint32>(_variables.sendSubmitWay);
qint32 supportSwitch = static_cast<qint32>(_variables.supportSwitch);
qint32 supportFixChatsOrder = _variables.supportFixChatsOrder ? 1 : 0;
qint32 supportTemplatesAutocomplete = _variables.supportTemplatesAutocomplete ? 1 : 0;
qint32 supportChatsTimeSlice = _variables.supportChatsTimeSlice.current();
qint32 includeMutedCounter = _variables.includeMutedCounter ? 1 : 0;
qint32 countUnreadMessages = _variables.countUnreadMessages ? 1 : 0;
qint32 exeLaunchWarning = _variables.exeLaunchWarning ? 1 : 0;
QByteArray autoDownload;
qint32 supportAllSearchResults = _variables.supportAllSearchResults.current() ? 1 : 0;
qint32 archiveCollapsed = _variables.archiveCollapsed.current() ? 1 : 0;
qint32 notifyAboutPinned = _variables.notifyAboutPinned.current() ? 1 : 0;
qint32 archiveInMainMenu = _variables.archiveInMainMenu.current() ? 1 : 0;
qint32 skipArchiveInSearch = _variables.skipArchiveInSearch.current() ? 1 : 0;
qint32 autoplayGifs = _variables.autoplayGifs ? 1 : 0;
qint32 loopAnimatedStickers = _variables.loopAnimatedStickers ? 1 : 0;
qint32 largeEmoji = _variables.largeEmoji.current() ? 1 : 0;
qint32 replaceEmoji = _variables.replaceEmoji.current() ? 1 : 0;
qint32 suggestEmoji = _variables.suggestEmoji ? 1 : 0;
qint32 suggestStickersByEmoji = _variables.suggestStickersByEmoji ? 1 : 0;
stream >> selectorTab;
stream >> lastSeenWarningSeen;
if (!stream.atEnd()) {
stream >> tabbedSelectorSectionEnabled;
}
if (!stream.atEnd()) {
auto count = qint32(0);
stream >> count;
if (stream.status() == QDataStream::Ok) {
for (auto i = 0; i != count; ++i) {
QString key, value;
stream >> key >> value;
soundOverrides[key] = value;
}
}
}
if (!stream.atEnd()) {
stream >> tabbedSelectorSectionTooltipShown;
}
if (!stream.atEnd()) {
stream >> floatPlayerColumn >> floatPlayerCorner;
}
if (!stream.atEnd()) {
auto count = qint32(0);
stream >> count;
if (stream.status() == QDataStream::Ok) {
for (auto i = 0; i != count; ++i) {
quint64 peerId;
stream >> peerId;
groupStickersSectionHidden.insert(peerId);
}
}
}
if (!stream.atEnd()) {
stream >> thirdSectionInfoEnabled;
stream >> smallDialogsList;
}
if (!stream.atEnd()) {
qint32 value = 0;
stream >> value;
dialogsWidthRatio = snap(value / 1000000., 0., 1.);
stream >> value;
thirdColumnWidth = value;
stream >> value;
thirdSectionExtendedBy = value;
}
if (!stream.atEnd()) {
stream >> sendFilesWay;
}
if (!stream.atEnd()) {
stream >> legacyCallsPeerToPeer;
}
if (!stream.atEnd()) {
stream >> sendSubmitWay;
stream >> supportSwitch;
stream >> supportFixChatsOrder;
}
if (!stream.atEnd()) {
stream >> supportTemplatesAutocomplete;
}
if (!stream.atEnd()) {
stream >> supportChatsTimeSlice;
}
if (!stream.atEnd()) {
stream >> includeMutedCounter;
stream >> countUnreadMessages;
}
if (!stream.atEnd()) {
stream >> exeLaunchWarning;
}
if (!stream.atEnd()) {
stream >> autoDownload;
}
if (!stream.atEnd()) {
stream >> supportAllSearchResults;
}
if (!stream.atEnd()) {
stream >> archiveCollapsed;
}
if (!stream.atEnd()) {
stream >> notifyAboutPinned;
}
if (!stream.atEnd()) {
stream >> archiveInMainMenu;
}
if (!stream.atEnd()) {
stream >> skipArchiveInSearch;
}
if (!stream.atEnd()) {
stream >> autoplayGifs;
stream >> loopAnimatedStickers;
stream >> largeEmoji;
stream >> replaceEmoji;
stream >> suggestEmoji;
stream >> suggestStickersByEmoji;
}
if (stream.status() != QDataStream::Ok) {
LOG(("App Error: "
"Bad data for Settings::constructFromSerialized()"));
return;
}
if (!autoDownload.isEmpty()
&& !_variables.autoDownload.setFromSerialized(autoDownload)) {
return;
}
auto uncheckedTab = static_cast<ChatHelpers::SelectorTab>(selectorTab);
switch (uncheckedTab) {
case ChatHelpers::SelectorTab::Emoji:
case ChatHelpers::SelectorTab::Stickers:
case ChatHelpers::SelectorTab::Gifs: _variables.selectorTab = uncheckedTab; break;
}
_variables.lastSeenWarningSeen = (lastSeenWarningSeen == 1);
_variables.tabbedSelectorSectionEnabled = (tabbedSelectorSectionEnabled == 1);
_variables.soundOverrides = std::move(soundOverrides);
_variables.tabbedSelectorSectionTooltipShown = tabbedSelectorSectionTooltipShown;
auto uncheckedColumn = static_cast<Window::Column>(floatPlayerColumn);
switch (uncheckedColumn) {
case Window::Column::First:
case Window::Column::Second:
case Window::Column::Third: _variables.floatPlayerColumn = uncheckedColumn; break;
}
auto uncheckedCorner = static_cast<RectPart>(floatPlayerCorner);
switch (uncheckedCorner) {
case RectPart::TopLeft:
case RectPart::TopRight:
case RectPart::BottomLeft:
case RectPart::BottomRight: _variables.floatPlayerCorner = uncheckedCorner; break;
}
_variables.groupStickersSectionHidden = std::move(groupStickersSectionHidden);
_variables.thirdSectionInfoEnabled = thirdSectionInfoEnabled;
_variables.smallDialogsList = smallDialogsList;
_variables.dialogsWidthRatio = dialogsWidthRatio;
_variables.thirdColumnWidth = thirdColumnWidth;
_variables.thirdSectionExtendedBy = thirdSectionExtendedBy;
if (_variables.thirdSectionInfoEnabled) {
_variables.tabbedSelectorSectionEnabled = false;
}
auto uncheckedSendFilesWay = static_cast<SendFilesWay>(sendFilesWay);
switch (uncheckedSendFilesWay) {
case SendFilesWay::Album:
case SendFilesWay::Photos:
case SendFilesWay::Files: _variables.sendFilesWay = uncheckedSendFilesWay; break;
}
auto uncheckedSendSubmitWay = static_cast<Ui::InputSubmitSettings>(
sendSubmitWay);
switch (uncheckedSendSubmitWay) {
case Ui::InputSubmitSettings::Enter:
case Ui::InputSubmitSettings::CtrlEnter: _variables.sendSubmitWay = uncheckedSendSubmitWay; break;
}
auto uncheckedSupportSwitch = static_cast<Support::SwitchSettings>(
supportSwitch);
switch (uncheckedSupportSwitch) {
case Support::SwitchSettings::None:
case Support::SwitchSettings::Next:
case Support::SwitchSettings::Previous: _variables.supportSwitch = uncheckedSupportSwitch; break;
}
_variables.supportFixChatsOrder = (supportFixChatsOrder == 1);
_variables.supportTemplatesAutocomplete = (supportTemplatesAutocomplete == 1);
_variables.supportChatsTimeSlice = supportChatsTimeSlice;
_variables.hadLegacyCallsPeerToPeerNobody = (legacyCallsPeerToPeer == kLegacyCallsPeerToPeerNobody);
_variables.includeMutedCounter = (includeMutedCounter == 1);
_variables.countUnreadMessages = (countUnreadMessages == 1);
_variables.exeLaunchWarning = (exeLaunchWarning == 1);
_variables.supportAllSearchResults = (supportAllSearchResults == 1);
_variables.archiveCollapsed = (archiveCollapsed == 1);
_variables.notifyAboutPinned = (notifyAboutPinned == 1);
_variables.archiveInMainMenu = (archiveInMainMenu == 1);
_variables.skipArchiveInSearch = (skipArchiveInSearch == 1);
_variables.autoplayGifs = (autoplayGifs == 1);
_variables.loopAnimatedStickers = (loopAnimatedStickers == 1);
_variables.largeEmoji = (largeEmoji == 1);
_variables.replaceEmoji = (replaceEmoji == 1);
_variables.suggestEmoji = (suggestEmoji == 1);
_variables.suggestStickersByEmoji = (suggestStickersByEmoji == 1);
}
void Settings::setSupportChatsTimeSlice(int slice) {
_variables.supportChatsTimeSlice = slice;
}
int Settings::supportChatsTimeSlice() const {
return _variables.supportChatsTimeSlice.current();
}
rpl::producer<int> Settings::supportChatsTimeSliceValue() const {
return _variables.supportChatsTimeSlice.value();
}
void Settings::setSupportAllSearchResults(bool all) {
_variables.supportAllSearchResults = all;
}
bool Settings::supportAllSearchResults() const {
return _variables.supportAllSearchResults.current();
}
rpl::producer<bool> Settings::supportAllSearchResultsValue() const {
return _variables.supportAllSearchResults.value();
}
void Settings::setTabbedSelectorSectionEnabled(bool enabled) {
_variables.tabbedSelectorSectionEnabled = enabled;
if (enabled) {
setThirdSectionInfoEnabled(false);
}
setTabbedReplacedWithInfo(false);
}
rpl::producer<bool> Settings::tabbedReplacedWithInfoValue() const {
return _tabbedReplacedWithInfoValue.events_starting_with(
tabbedReplacedWithInfo());
}
void Settings::setThirdSectionInfoEnabled(bool enabled) {
if (_variables.thirdSectionInfoEnabled != enabled) {
_variables.thirdSectionInfoEnabled = enabled;
if (enabled) {
setTabbedSelectorSectionEnabled(false);
}
setTabbedReplacedWithInfo(false);
_thirdSectionInfoEnabledValue.fire_copy(enabled);
}
}
rpl::producer<bool> Settings::thirdSectionInfoEnabledValue() const {
return _thirdSectionInfoEnabledValue.events_starting_with(
thirdSectionInfoEnabled());
}
void Settings::setTabbedReplacedWithInfo(bool enabled) {
if (_tabbedReplacedWithInfo != enabled) {
_tabbedReplacedWithInfo = enabled;
_tabbedReplacedWithInfoValue.fire_copy(enabled);
}
}
QString Settings::getSoundPath(const QString &key) const {
auto it = _variables.soundOverrides.constFind(key);
if (it != _variables.soundOverrides.end()) {
return it.value();
}
return qsl(":/sounds/") + key + qsl(".mp3");
}
void Settings::setDialogsWidthRatio(float64 ratio) {
_variables.dialogsWidthRatio = ratio;
}
float64 Settings::dialogsWidthRatio() const {
return _variables.dialogsWidthRatio.current();
}
rpl::producer<float64> Settings::dialogsWidthRatioChanges() const {
return _variables.dialogsWidthRatio.changes();
}
void Settings::setThirdColumnWidth(int width) {
_variables.thirdColumnWidth = width;
}
int Settings::thirdColumnWidth() const {
return _variables.thirdColumnWidth.current();
}
rpl::producer<int> Settings::thirdColumnWidthChanges() const {
return _variables.thirdColumnWidth.changes();
}
void Settings::setArchiveCollapsed(bool collapsed) {
_variables.archiveCollapsed = collapsed;
}
bool Settings::archiveCollapsed() const {
return _variables.archiveCollapsed.current();
}
rpl::producer<bool> Settings::archiveCollapsedChanges() const {
return _variables.archiveCollapsed.changes();
}
void Settings::setArchiveInMainMenu(bool inMainMenu) {
_variables.archiveInMainMenu = inMainMenu;
}
bool Settings::archiveInMainMenu() const {
return _variables.archiveInMainMenu.current();
}
rpl::producer<bool> Settings::archiveInMainMenuChanges() const {
return _variables.archiveInMainMenu.changes();
}
void Settings::setNotifyAboutPinned(bool notify) {
_variables.notifyAboutPinned = notify;
}
bool Settings::notifyAboutPinned() const {
return _variables.notifyAboutPinned.current();
}
rpl::producer<bool> Settings::notifyAboutPinnedChanges() const {
return _variables.notifyAboutPinned.changes();
}
void Settings::setSkipArchiveInSearch(bool skip) {
_variables.skipArchiveInSearch = skip;
}
bool Settings::skipArchiveInSearch() const {
return _variables.skipArchiveInSearch.current();
}
rpl::producer<bool> Settings::skipArchiveInSearchChanges() const {
return _variables.skipArchiveInSearch.changes();
}
void Settings::setLargeEmoji(bool value) {
_variables.largeEmoji = value;
}
bool Settings::largeEmoji() const {
return _variables.largeEmoji.current();
}
rpl::producer<bool> Settings::largeEmojiValue() const {
return _variables.largeEmoji.value();
}
rpl::producer<bool> Settings::largeEmojiChanges() const {
return _variables.largeEmoji.changes();
}
void Settings::setReplaceEmoji(bool value) {
_variables.replaceEmoji = value;
}
bool Settings::replaceEmoji() const {
return _variables.replaceEmoji.current();
}
rpl::producer<bool> Settings::replaceEmojiValue() const {
return _variables.replaceEmoji.value();
}
rpl::producer<bool> Settings::replaceEmojiChanges() const {
return _variables.replaceEmoji.changes();
}
Session::Session(
not_null<Main::Account*> account,
const MTPUser &user)
: _account(account)
, _saveSettingsTimer([=] { Local::writeUserSettings(); })
, _autoLockTimer([=] { checkAutoLock(); })
, _api(std::make_unique<ApiWrap>(this))
, _appConfig(std::make_unique<AppConfig>(this))
@ -522,9 +52,6 @@ Session::Session(
, _emojiStickersPack(std::make_unique<Stickers::EmojiPack>(this))
, _changelogs(Core::Changelogs::Create(this))
, _supportHelper(Support::Helper::Create(this)) {
_saveDataTimer.setCallback([=] {
Local::writeUserSettings();
});
Core::App().passcodeLockChanges(
) | rpl::start_with_next([=] {
_shouldLockAt = 0;
@ -614,7 +141,7 @@ void Session::moveSettingsFrom(Settings &&other) {
void Session::saveSettingsDelayed(crl::time delay) {
Expects(this == &Auth());
_saveDataTimer.callOnce(delay);
_saveSettingsTimer.callOnce(delay);
}
not_null<MTP::Instance*> Session::mtp() {

View File

@ -10,18 +10,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <rpl/event_stream.h>
#include <rpl/filter.h>
#include <rpl/variable.h>
#include "main/main_settings.h"
#include "base/timer.h"
#include "data/data_auto_download.h"
class ApiWrap;
enum class SendFilesWay;
namespace Ui {
enum class InputSubmitSettings;
} // namespace Ui
namespace Support {
enum class SwitchSettings;
class Helper;
class Templates;
} // namespace Support
@ -40,17 +34,12 @@ namespace Window {
namespace Notifications {
class System;
} // namespace Notifications
enum class Column;
} // namespace Window
namespace Calls {
class Instance;
} // namespace Calls
namespace ChatHelpers {
enum class SelectorTab;
} // namespace ChatHelpers
namespace Stickers {
class EmojiPack;
} // namespace Stickers;
@ -64,269 +53,6 @@ namespace Main {
class Account;
class AppConfig;
class Settings final {
public:
void moveFrom(Settings &&other) {
_variables = std::move(other._variables);
}
[[nodiscard]] QByteArray serialize() const;
void constructFromSerialized(const QByteArray &serialized);
void setLastSeenWarningSeen(bool lastSeenWarningSeen) {
_variables.lastSeenWarningSeen = lastSeenWarningSeen;
}
[[nodiscard]] bool lastSeenWarningSeen() const {
return _variables.lastSeenWarningSeen;
}
void setSendFilesWay(SendFilesWay way) {
_variables.sendFilesWay = way;
}
[[nodiscard]] SendFilesWay sendFilesWay() const {
return _variables.sendFilesWay;
}
void setSendSubmitWay(Ui::InputSubmitSettings value) {
_variables.sendSubmitWay = value;
}
[[nodiscard]] Ui::InputSubmitSettings sendSubmitWay() const {
return _variables.sendSubmitWay;
}
void setSupportSwitch(Support::SwitchSettings value) {
_variables.supportSwitch = value;
}
[[nodiscard]] Support::SwitchSettings supportSwitch() const {
return _variables.supportSwitch;
}
void setSupportFixChatsOrder(bool fix) {
_variables.supportFixChatsOrder = fix;
}
[[nodiscard]] bool supportFixChatsOrder() const {
return _variables.supportFixChatsOrder;
}
void setSupportTemplatesAutocomplete(bool enabled) {
_variables.supportTemplatesAutocomplete = enabled;
}
[[nodiscard]] bool supportTemplatesAutocomplete() const {
return _variables.supportTemplatesAutocomplete;
}
void setSupportChatsTimeSlice(int slice);
[[nodiscard]] int supportChatsTimeSlice() const;
[[nodiscard]] rpl::producer<int> supportChatsTimeSliceValue() const;
void setSupportAllSearchResults(bool all);
[[nodiscard]] bool supportAllSearchResults() const;
[[nodiscard]] rpl::producer<bool> supportAllSearchResultsValue() const;
[[nodiscard]] ChatHelpers::SelectorTab selectorTab() const {
return _variables.selectorTab;
}
void setSelectorTab(ChatHelpers::SelectorTab tab) {
_variables.selectorTab = tab;
}
[[nodiscard]] bool tabbedSelectorSectionEnabled() const {
return _variables.tabbedSelectorSectionEnabled;
}
void setTabbedSelectorSectionEnabled(bool enabled);
[[nodiscard]] bool thirdSectionInfoEnabled() const {
return _variables.thirdSectionInfoEnabled;
}
void setThirdSectionInfoEnabled(bool enabled);
[[nodiscard]] rpl::producer<bool> thirdSectionInfoEnabledValue() const;
[[nodiscard]] int thirdSectionExtendedBy() const {
return _variables.thirdSectionExtendedBy;
}
void setThirdSectionExtendedBy(int savedValue) {
_variables.thirdSectionExtendedBy = savedValue;
}
[[nodiscard]] bool tabbedReplacedWithInfo() const {
return _tabbedReplacedWithInfo;
}
void setTabbedReplacedWithInfo(bool enabled);
[[nodiscard]] rpl::producer<bool> tabbedReplacedWithInfoValue() const;
void setSmallDialogsList(bool enabled) {
_variables.smallDialogsList = enabled;
}
[[nodiscard]] bool smallDialogsList() const {
return _variables.smallDialogsList;
}
void setSoundOverride(const QString &key, const QString &path) {
_variables.soundOverrides.insert(key, path);
}
void clearSoundOverrides() {
_variables.soundOverrides.clear();
}
[[nodiscard]] QString getSoundPath(const QString &key) const;
void setTabbedSelectorSectionTooltipShown(int shown) {
_variables.tabbedSelectorSectionTooltipShown = shown;
}
[[nodiscard]] int tabbedSelectorSectionTooltipShown() const {
return _variables.tabbedSelectorSectionTooltipShown;
}
void setFloatPlayerColumn(Window::Column column) {
_variables.floatPlayerColumn = column;
}
[[nodiscard]] Window::Column floatPlayerColumn() const {
return _variables.floatPlayerColumn;
}
void setFloatPlayerCorner(RectPart corner) {
_variables.floatPlayerCorner = corner;
}
[[nodiscard]] RectPart floatPlayerCorner() const {
return _variables.floatPlayerCorner;
}
void setDialogsWidthRatio(float64 ratio);
[[nodiscard]] float64 dialogsWidthRatio() const;
[[nodiscard]] rpl::producer<float64> dialogsWidthRatioChanges() const;
void setThirdColumnWidth(int width);
[[nodiscard]] int thirdColumnWidth() const;
[[nodiscard]] rpl::producer<int> thirdColumnWidthChanges() const;
void setGroupStickersSectionHidden(PeerId peerId) {
_variables.groupStickersSectionHidden.insert(peerId);
}
[[nodiscard]] bool isGroupStickersSectionHidden(PeerId peerId) const {
return _variables.groupStickersSectionHidden.contains(peerId);
}
void removeGroupStickersSectionHidden(PeerId peerId) {
_variables.groupStickersSectionHidden.remove(peerId);
}
[[nodiscard]] Data::AutoDownload::Full &autoDownload() {
return _variables.autoDownload;
}
[[nodiscard]] const Data::AutoDownload::Full &autoDownload() const {
return _variables.autoDownload;
}
void setArchiveCollapsed(bool collapsed);
[[nodiscard]] bool archiveCollapsed() const;
[[nodiscard]] rpl::producer<bool> archiveCollapsedChanges() const;
void setArchiveInMainMenu(bool inMainMenu);
[[nodiscard]] bool archiveInMainMenu() const;
[[nodiscard]] rpl::producer<bool> archiveInMainMenuChanges() const;
void setNotifyAboutPinned(bool notify);
[[nodiscard]] bool notifyAboutPinned() const;
[[nodiscard]] rpl::producer<bool> notifyAboutPinnedChanges() const;
void setSkipArchiveInSearch(bool skip);
[[nodiscard]] bool skipArchiveInSearch() const;
[[nodiscard]] rpl::producer<bool> skipArchiveInSearchChanges() const;
[[nodiscard]] bool hadLegacyCallsPeerToPeerNobody() const {
return _variables.hadLegacyCallsPeerToPeerNobody;
}
[[nodiscard]] bool includeMutedCounter() const {
return _variables.includeMutedCounter;
}
void setIncludeMutedCounter(bool value) {
_variables.includeMutedCounter = value;
}
[[nodiscard]] bool countUnreadMessages() const {
return _variables.countUnreadMessages;
}
void setCountUnreadMessages(bool value) {
_variables.countUnreadMessages = value;
}
[[nodiscard]] bool exeLaunchWarning() const {
return _variables.exeLaunchWarning;
}
void setExeLaunchWarning(bool warning) {
_variables.exeLaunchWarning = warning;
}
[[nodiscard]] bool autoplayGifs() const {
return _variables.autoplayGifs;
}
void setAutoplayGifs(bool value) {
_variables.autoplayGifs = value;
}
[[nodiscard]] bool loopAnimatedStickers() const {
return _variables.loopAnimatedStickers;
}
void setLoopAnimatedStickers(bool value) {
_variables.loopAnimatedStickers = value;
}
void setLargeEmoji(bool value);
[[nodiscard]] bool largeEmoji() const;
[[nodiscard]] rpl::producer<bool> largeEmojiValue() const;
[[nodiscard]] rpl::producer<bool> largeEmojiChanges() const;
void setReplaceEmoji(bool value);
[[nodiscard]] bool replaceEmoji() const;
[[nodiscard]] rpl::producer<bool> replaceEmojiValue() const;
[[nodiscard]] rpl::producer<bool> replaceEmojiChanges() const;
[[nodiscard]] bool suggestEmoji() const {
return _variables.suggestEmoji;
}
void setSuggestEmoji(bool value) {
_variables.suggestEmoji = value;
}
[[nodiscard]] bool suggestStickersByEmoji() const {
return _variables.suggestStickersByEmoji;
}
void setSuggestStickersByEmoji(bool value) {
_variables.suggestStickersByEmoji = value;
}
private:
struct Variables {
Variables();
static constexpr auto kDefaultDialogsWidthRatio = 5. / 14;
static constexpr auto kDefaultThirdColumnWidth = 0;
bool lastSeenWarningSeen = false;
SendFilesWay sendFilesWay;
ChatHelpers::SelectorTab selectorTab; // per-window
bool tabbedSelectorSectionEnabled = false; // per-window
int tabbedSelectorSectionTooltipShown = 0;
QMap<QString, QString> soundOverrides;
Window::Column floatPlayerColumn; // per-window
RectPart floatPlayerCorner; // per-window
base::flat_set<PeerId> groupStickersSectionHidden;
bool thirdSectionInfoEnabled = true; // per-window
bool smallDialogsList = false; // per-window
int thirdSectionExtendedBy = -1; // per-window
rpl::variable<float64> dialogsWidthRatio
= kDefaultDialogsWidthRatio; // per-window
rpl::variable<int> thirdColumnWidth
= kDefaultThirdColumnWidth; // per-window
Ui::InputSubmitSettings sendSubmitWay;
bool hadLegacyCallsPeerToPeerNobody = false;
bool includeMutedCounter = true;
bool countUnreadMessages = true;
bool exeLaunchWarning = true;
Data::AutoDownload::Full autoDownload;
rpl::variable<bool> archiveCollapsed = false;
rpl::variable<bool> archiveInMainMenu = false;
rpl::variable<bool> notifyAboutPinned = true;
rpl::variable<bool> skipArchiveInSearch = false;
bool autoplayGifs = true;
bool loopAnimatedStickers = true;
rpl::variable<bool> largeEmoji = true;
rpl::variable<bool> replaceEmoji = true;
bool suggestEmoji = true;
bool suggestStickersByEmoji = true;
static constexpr auto kDefaultSupportChatsLimitSlice
= 7 * 24 * 60 * 60;
Support::SwitchSettings supportSwitch;
bool supportFixChatsOrder = true;
bool supportTemplatesAutocomplete = true;
rpl::variable<int> supportChatsTimeSlice
= kDefaultSupportChatsLimitSlice;
rpl::variable<bool> supportAllSearchResults = false;
};
rpl::event_stream<bool> _thirdSectionInfoEnabledValue;
bool _tabbedReplacedWithInfo = false;
rpl::event_stream<bool> _tabbedReplacedWithInfoValue;
Variables _variables;
};
class Session final
: public base::has_weak_ptr
, private base::Subscriber {
@ -337,54 +63,54 @@ public:
Session(const Session &other) = delete;
Session &operator=(const Session &other) = delete;
static bool Exists();
[[nodiscard]] static bool Exists();
Main::Account &account() const;
[[nodiscard]] Main::Account &account() const;
UserId userId() const;
PeerId userPeerId() const;
not_null<UserData*> user() const {
[[nodiscard]] UserId userId() const;
[[nodiscard]] PeerId userPeerId() const;
[[nodiscard]] not_null<UserData*> user() const {
return _user;
}
bool validateSelf(const MTPUser &user);
Storage::Downloader &downloader() {
[[nodiscard]] Storage::Downloader &downloader() {
return *_downloader;
}
Storage::Uploader &uploader() {
[[nodiscard]] Storage::Uploader &uploader() {
return *_uploader;
}
Storage::Facade &storage() {
[[nodiscard]] Storage::Facade &storage() {
return *_storage;
}
Stickers::EmojiPack &emojiStickersPack() {
[[nodiscard]] Stickers::EmojiPack &emojiStickersPack() {
return *_emojiStickersPack;
}
AppConfig &appConfig() {
[[nodiscard]] AppConfig &appConfig() {
return *_appConfig;
}
base::Observable<void> &downloaderTaskFinished();
[[nodiscard]] base::Observable<void> &downloaderTaskFinished();
Window::Notifications::System &notifications() {
[[nodiscard]] Window::Notifications::System &notifications() {
return *_notifications;
}
Data::Session &data() {
[[nodiscard]] Data::Session &data() {
return *_data;
}
Settings &settings() {
[[nodiscard]] Settings &settings() {
return _settings;
}
void moveSettingsFrom(Settings &&other);
void saveSettingsDelayed(crl::time delay = kDefaultSaveDelay);
not_null<MTP::Instance*> mtp();
ApiWrap &api() {
[[nodiscard]] not_null<MTP::Instance*> mtp();
[[nodiscard]] ApiWrap &api() {
return *_api;
}
Calls::Instance &calls() {
[[nodiscard]] Calls::Instance &calls() {
return *_calls;
}
@ -393,7 +119,7 @@ public:
void localPasscodeChanged();
void termsDeleteNow();
rpl::lifetime &lifetime() {
[[nodiscard]] rpl::lifetime &lifetime() {
return _lifetime;
}
@ -410,7 +136,7 @@ private:
const not_null<Main::Account*> _account;
Settings _settings;
base::Timer _saveDataTimer;
base::Timer _saveSettingsTimer;
crl::time _shouldLockAt = 0;
base::Timer _autoLockTimer;

View File

@ -0,0 +1,490 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "main/main_settings.h"
#include "chat_helpers/tabbed_selector.h"
#include "window/section_widget.h"
#include "ui/widgets/input_fields.h"
#include "support/support_common.h"
#include "storage/serialize_common.h"
#include "boxes/send_files_box.h"
namespace Main {
namespace {
constexpr auto kAutoLockTimeoutLateMs = crl::time(3000);
constexpr auto kLegacyCallsPeerToPeerNobody = 4;
} // namespace
Settings::Variables::Variables()
: sendFilesWay(SendFilesWay::Album)
, selectorTab(ChatHelpers::SelectorTab::Emoji)
, floatPlayerColumn(Window::Column::Second)
, floatPlayerCorner(RectPart::TopRight)
, sendSubmitWay(Ui::InputSubmitSettings::Enter)
, supportSwitch(Support::SwitchSettings::Next) {
}
QByteArray Settings::serialize() const {
const auto autoDownload = _variables.autoDownload.serialize();
auto size = sizeof(qint32) * 30;
for (auto i = _variables.soundOverrides.cbegin(), e = _variables.soundOverrides.cend(); i != e; ++i) {
size += Serialize::stringSize(i.key()) + Serialize::stringSize(i.value());
}
size += _variables.groupStickersSectionHidden.size() * sizeof(quint64);
size += Serialize::bytearraySize(autoDownload);
auto result = QByteArray();
result.reserve(size);
{
QDataStream stream(&result, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_5_1);
stream << static_cast<qint32>(_variables.selectorTab);
stream << qint32(_variables.lastSeenWarningSeen ? 1 : 0);
stream << qint32(_variables.tabbedSelectorSectionEnabled ? 1 : 0);
stream << qint32(_variables.soundOverrides.size());
for (auto i = _variables.soundOverrides.cbegin(), e = _variables.soundOverrides.cend(); i != e; ++i) {
stream << i.key() << i.value();
}
stream << qint32(_variables.tabbedSelectorSectionTooltipShown);
stream << qint32(_variables.floatPlayerColumn);
stream << qint32(_variables.floatPlayerCorner);
stream << qint32(_variables.groupStickersSectionHidden.size());
for (auto peerId : _variables.groupStickersSectionHidden) {
stream << quint64(peerId);
}
stream << qint32(_variables.thirdSectionInfoEnabled ? 1 : 0);
stream << qint32(_variables.smallDialogsList ? 1 : 0);
stream << qint32(snap(
qRound(_variables.dialogsWidthRatio.current() * 1000000),
0,
1000000));
stream << qint32(_variables.thirdColumnWidth.current());
stream << qint32(_variables.thirdSectionExtendedBy);
stream << qint32(_variables.sendFilesWay);
stream << qint32(0);// LEGACY _variables.callsPeerToPeer.current());
stream << qint32(_variables.sendSubmitWay);
stream << qint32(_variables.supportSwitch);
stream << qint32(_variables.supportFixChatsOrder ? 1 : 0);
stream << qint32(_variables.supportTemplatesAutocomplete ? 1 : 0);
stream << qint32(_variables.supportChatsTimeSlice.current());
stream << qint32(_variables.includeMutedCounter ? 1 : 0);
stream << qint32(_variables.countUnreadMessages ? 1 : 0);
stream << qint32(_variables.exeLaunchWarning ? 1 : 0);
stream << autoDownload;
stream << qint32(_variables.supportAllSearchResults.current() ? 1 : 0);
stream << qint32(_variables.archiveCollapsed.current() ? 1 : 0);
stream << qint32(_variables.notifyAboutPinned.current() ? 1 : 0);
stream << qint32(_variables.archiveInMainMenu.current() ? 1 : 0);
stream << qint32(_variables.skipArchiveInSearch.current() ? 1 : 0);
stream << qint32(_variables.autoplayGifs ? 1 : 0);
stream << qint32(_variables.loopAnimatedStickers ? 1 : 0);
stream << qint32(_variables.largeEmoji.current() ? 1 : 0);
stream << qint32(_variables.replaceEmoji.current() ? 1 : 0);
stream << qint32(_variables.suggestEmoji ? 1 : 0);
stream << qint32(_variables.suggestStickersByEmoji ? 1 : 0);
}
return result;
}
void Settings::constructFromSerialized(const QByteArray &serialized) {
if (serialized.isEmpty()) {
return;
}
QDataStream stream(serialized);
stream.setVersion(QDataStream::Qt_5_1);
qint32 selectorTab = static_cast<qint32>(ChatHelpers::SelectorTab::Emoji);
qint32 lastSeenWarningSeen = 0;
qint32 tabbedSelectorSectionEnabled = 1;
qint32 tabbedSelectorSectionTooltipShown = 0;
qint32 floatPlayerColumn = static_cast<qint32>(Window::Column::Second);
qint32 floatPlayerCorner = static_cast<qint32>(RectPart::TopRight);
QMap<QString, QString> soundOverrides;
base::flat_set<PeerId> groupStickersSectionHidden;
qint32 thirdSectionInfoEnabled = 0;
qint32 smallDialogsList = 0;
float64 dialogsWidthRatio = _variables.dialogsWidthRatio.current();
int thirdColumnWidth = _variables.thirdColumnWidth.current();
int thirdSectionExtendedBy = _variables.thirdSectionExtendedBy;
qint32 sendFilesWay = static_cast<qint32>(_variables.sendFilesWay);
qint32 legacyCallsPeerToPeer = qint32(0);
qint32 sendSubmitWay = static_cast<qint32>(_variables.sendSubmitWay);
qint32 supportSwitch = static_cast<qint32>(_variables.supportSwitch);
qint32 supportFixChatsOrder = _variables.supportFixChatsOrder ? 1 : 0;
qint32 supportTemplatesAutocomplete = _variables.supportTemplatesAutocomplete ? 1 : 0;
qint32 supportChatsTimeSlice = _variables.supportChatsTimeSlice.current();
qint32 includeMutedCounter = _variables.includeMutedCounter ? 1 : 0;
qint32 countUnreadMessages = _variables.countUnreadMessages ? 1 : 0;
qint32 exeLaunchWarning = _variables.exeLaunchWarning ? 1 : 0;
QByteArray autoDownload;
qint32 supportAllSearchResults = _variables.supportAllSearchResults.current() ? 1 : 0;
qint32 archiveCollapsed = _variables.archiveCollapsed.current() ? 1 : 0;
qint32 notifyAboutPinned = _variables.notifyAboutPinned.current() ? 1 : 0;
qint32 archiveInMainMenu = _variables.archiveInMainMenu.current() ? 1 : 0;
qint32 skipArchiveInSearch = _variables.skipArchiveInSearch.current() ? 1 : 0;
qint32 autoplayGifs = _variables.autoplayGifs ? 1 : 0;
qint32 loopAnimatedStickers = _variables.loopAnimatedStickers ? 1 : 0;
qint32 largeEmoji = _variables.largeEmoji.current() ? 1 : 0;
qint32 replaceEmoji = _variables.replaceEmoji.current() ? 1 : 0;
qint32 suggestEmoji = _variables.suggestEmoji ? 1 : 0;
qint32 suggestStickersByEmoji = _variables.suggestStickersByEmoji ? 1 : 0;
stream >> selectorTab;
stream >> lastSeenWarningSeen;
if (!stream.atEnd()) {
stream >> tabbedSelectorSectionEnabled;
}
if (!stream.atEnd()) {
auto count = qint32(0);
stream >> count;
if (stream.status() == QDataStream::Ok) {
for (auto i = 0; i != count; ++i) {
QString key, value;
stream >> key >> value;
soundOverrides[key] = value;
}
}
}
if (!stream.atEnd()) {
stream >> tabbedSelectorSectionTooltipShown;
}
if (!stream.atEnd()) {
stream >> floatPlayerColumn >> floatPlayerCorner;
}
if (!stream.atEnd()) {
auto count = qint32(0);
stream >> count;
if (stream.status() == QDataStream::Ok) {
for (auto i = 0; i != count; ++i) {
quint64 peerId;
stream >> peerId;
groupStickersSectionHidden.insert(peerId);
}
}
}
if (!stream.atEnd()) {
stream >> thirdSectionInfoEnabled;
stream >> smallDialogsList;
}
if (!stream.atEnd()) {
qint32 value = 0;
stream >> value;
dialogsWidthRatio = snap(value / 1000000., 0., 1.);
stream >> value;
thirdColumnWidth = value;
stream >> value;
thirdSectionExtendedBy = value;
}
if (!stream.atEnd()) {
stream >> sendFilesWay;
}
if (!stream.atEnd()) {
stream >> legacyCallsPeerToPeer;
}
if (!stream.atEnd()) {
stream >> sendSubmitWay;
stream >> supportSwitch;
stream >> supportFixChatsOrder;
}
if (!stream.atEnd()) {
stream >> supportTemplatesAutocomplete;
}
if (!stream.atEnd()) {
stream >> supportChatsTimeSlice;
}
if (!stream.atEnd()) {
stream >> includeMutedCounter;
stream >> countUnreadMessages;
}
if (!stream.atEnd()) {
stream >> exeLaunchWarning;
}
if (!stream.atEnd()) {
stream >> autoDownload;
}
if (!stream.atEnd()) {
stream >> supportAllSearchResults;
}
if (!stream.atEnd()) {
stream >> archiveCollapsed;
}
if (!stream.atEnd()) {
stream >> notifyAboutPinned;
}
if (!stream.atEnd()) {
stream >> archiveInMainMenu;
}
if (!stream.atEnd()) {
stream >> skipArchiveInSearch;
}
if (!stream.atEnd()) {
stream >> autoplayGifs;
stream >> loopAnimatedStickers;
stream >> largeEmoji;
stream >> replaceEmoji;
stream >> suggestEmoji;
stream >> suggestStickersByEmoji;
}
if (stream.status() != QDataStream::Ok) {
LOG(("App Error: "
"Bad data for Main::Settings::constructFromSerialized()"));
return;
}
if (!autoDownload.isEmpty()
&& !_variables.autoDownload.setFromSerialized(autoDownload)) {
return;
}
auto uncheckedTab = static_cast<ChatHelpers::SelectorTab>(selectorTab);
switch (uncheckedTab) {
case ChatHelpers::SelectorTab::Emoji:
case ChatHelpers::SelectorTab::Stickers:
case ChatHelpers::SelectorTab::Gifs: _variables.selectorTab = uncheckedTab; break;
}
_variables.lastSeenWarningSeen = (lastSeenWarningSeen == 1);
_variables.tabbedSelectorSectionEnabled = (tabbedSelectorSectionEnabled == 1);
_variables.soundOverrides = std::move(soundOverrides);
_variables.tabbedSelectorSectionTooltipShown = tabbedSelectorSectionTooltipShown;
auto uncheckedColumn = static_cast<Window::Column>(floatPlayerColumn);
switch (uncheckedColumn) {
case Window::Column::First:
case Window::Column::Second:
case Window::Column::Third: _variables.floatPlayerColumn = uncheckedColumn; break;
}
auto uncheckedCorner = static_cast<RectPart>(floatPlayerCorner);
switch (uncheckedCorner) {
case RectPart::TopLeft:
case RectPart::TopRight:
case RectPart::BottomLeft:
case RectPart::BottomRight: _variables.floatPlayerCorner = uncheckedCorner; break;
}
_variables.groupStickersSectionHidden = std::move(groupStickersSectionHidden);
_variables.thirdSectionInfoEnabled = thirdSectionInfoEnabled;
_variables.smallDialogsList = smallDialogsList;
_variables.dialogsWidthRatio = dialogsWidthRatio;
_variables.thirdColumnWidth = thirdColumnWidth;
_variables.thirdSectionExtendedBy = thirdSectionExtendedBy;
if (_variables.thirdSectionInfoEnabled) {
_variables.tabbedSelectorSectionEnabled = false;
}
auto uncheckedSendFilesWay = static_cast<SendFilesWay>(sendFilesWay);
switch (uncheckedSendFilesWay) {
case SendFilesWay::Album:
case SendFilesWay::Photos:
case SendFilesWay::Files: _variables.sendFilesWay = uncheckedSendFilesWay; break;
}
auto uncheckedSendSubmitWay = static_cast<Ui::InputSubmitSettings>(
sendSubmitWay);
switch (uncheckedSendSubmitWay) {
case Ui::InputSubmitSettings::Enter:
case Ui::InputSubmitSettings::CtrlEnter: _variables.sendSubmitWay = uncheckedSendSubmitWay; break;
}
auto uncheckedSupportSwitch = static_cast<Support::SwitchSettings>(
supportSwitch);
switch (uncheckedSupportSwitch) {
case Support::SwitchSettings::None:
case Support::SwitchSettings::Next:
case Support::SwitchSettings::Previous: _variables.supportSwitch = uncheckedSupportSwitch; break;
}
_variables.supportFixChatsOrder = (supportFixChatsOrder == 1);
_variables.supportTemplatesAutocomplete = (supportTemplatesAutocomplete == 1);
_variables.supportChatsTimeSlice = supportChatsTimeSlice;
_variables.hadLegacyCallsPeerToPeerNobody = (legacyCallsPeerToPeer == kLegacyCallsPeerToPeerNobody);
_variables.includeMutedCounter = (includeMutedCounter == 1);
_variables.countUnreadMessages = (countUnreadMessages == 1);
_variables.exeLaunchWarning = (exeLaunchWarning == 1);
_variables.supportAllSearchResults = (supportAllSearchResults == 1);
_variables.archiveCollapsed = (archiveCollapsed == 1);
_variables.notifyAboutPinned = (notifyAboutPinned == 1);
_variables.archiveInMainMenu = (archiveInMainMenu == 1);
_variables.skipArchiveInSearch = (skipArchiveInSearch == 1);
_variables.autoplayGifs = (autoplayGifs == 1);
_variables.loopAnimatedStickers = (loopAnimatedStickers == 1);
_variables.largeEmoji = (largeEmoji == 1);
_variables.replaceEmoji = (replaceEmoji == 1);
_variables.suggestEmoji = (suggestEmoji == 1);
_variables.suggestStickersByEmoji = (suggestStickersByEmoji == 1);
}
void Settings::setSupportChatsTimeSlice(int slice) {
_variables.supportChatsTimeSlice = slice;
}
int Settings::supportChatsTimeSlice() const {
return _variables.supportChatsTimeSlice.current();
}
rpl::producer<int> Settings::supportChatsTimeSliceValue() const {
return _variables.supportChatsTimeSlice.value();
}
void Settings::setSupportAllSearchResults(bool all) {
_variables.supportAllSearchResults = all;
}
bool Settings::supportAllSearchResults() const {
return _variables.supportAllSearchResults.current();
}
rpl::producer<bool> Settings::supportAllSearchResultsValue() const {
return _variables.supportAllSearchResults.value();
}
void Settings::setTabbedSelectorSectionEnabled(bool enabled) {
_variables.tabbedSelectorSectionEnabled = enabled;
if (enabled) {
setThirdSectionInfoEnabled(false);
}
setTabbedReplacedWithInfo(false);
}
rpl::producer<bool> Settings::tabbedReplacedWithInfoValue() const {
return _tabbedReplacedWithInfoValue.events_starting_with(
tabbedReplacedWithInfo());
}
void Settings::setThirdSectionInfoEnabled(bool enabled) {
if (_variables.thirdSectionInfoEnabled != enabled) {
_variables.thirdSectionInfoEnabled = enabled;
if (enabled) {
setTabbedSelectorSectionEnabled(false);
}
setTabbedReplacedWithInfo(false);
_thirdSectionInfoEnabledValue.fire_copy(enabled);
}
}
rpl::producer<bool> Settings::thirdSectionInfoEnabledValue() const {
return _thirdSectionInfoEnabledValue.events_starting_with(
thirdSectionInfoEnabled());
}
void Settings::setTabbedReplacedWithInfo(bool enabled) {
if (_tabbedReplacedWithInfo != enabled) {
_tabbedReplacedWithInfo = enabled;
_tabbedReplacedWithInfoValue.fire_copy(enabled);
}
}
QString Settings::getSoundPath(const QString &key) const {
auto it = _variables.soundOverrides.constFind(key);
if (it != _variables.soundOverrides.end()) {
return it.value();
}
return qsl(":/sounds/") + key + qsl(".mp3");
}
void Settings::setDialogsWidthRatio(float64 ratio) {
_variables.dialogsWidthRatio = ratio;
}
float64 Settings::dialogsWidthRatio() const {
return _variables.dialogsWidthRatio.current();
}
rpl::producer<float64> Settings::dialogsWidthRatioChanges() const {
return _variables.dialogsWidthRatio.changes();
}
void Settings::setThirdColumnWidth(int width) {
_variables.thirdColumnWidth = width;
}
int Settings::thirdColumnWidth() const {
return _variables.thirdColumnWidth.current();
}
rpl::producer<int> Settings::thirdColumnWidthChanges() const {
return _variables.thirdColumnWidth.changes();
}
void Settings::setArchiveCollapsed(bool collapsed) {
_variables.archiveCollapsed = collapsed;
}
bool Settings::archiveCollapsed() const {
return _variables.archiveCollapsed.current();
}
rpl::producer<bool> Settings::archiveCollapsedChanges() const {
return _variables.archiveCollapsed.changes();
}
void Settings::setArchiveInMainMenu(bool inMainMenu) {
_variables.archiveInMainMenu = inMainMenu;
}
bool Settings::archiveInMainMenu() const {
return _variables.archiveInMainMenu.current();
}
rpl::producer<bool> Settings::archiveInMainMenuChanges() const {
return _variables.archiveInMainMenu.changes();
}
void Settings::setNotifyAboutPinned(bool notify) {
_variables.notifyAboutPinned = notify;
}
bool Settings::notifyAboutPinned() const {
return _variables.notifyAboutPinned.current();
}
rpl::producer<bool> Settings::notifyAboutPinnedChanges() const {
return _variables.notifyAboutPinned.changes();
}
void Settings::setSkipArchiveInSearch(bool skip) {
_variables.skipArchiveInSearch = skip;
}
bool Settings::skipArchiveInSearch() const {
return _variables.skipArchiveInSearch.current();
}
rpl::producer<bool> Settings::skipArchiveInSearchChanges() const {
return _variables.skipArchiveInSearch.changes();
}
void Settings::setLargeEmoji(bool value) {
_variables.largeEmoji = value;
}
bool Settings::largeEmoji() const {
return _variables.largeEmoji.current();
}
rpl::producer<bool> Settings::largeEmojiValue() const {
return _variables.largeEmoji.value();
}
rpl::producer<bool> Settings::largeEmojiChanges() const {
return _variables.largeEmoji.changes();
}
void Settings::setReplaceEmoji(bool value) {
_variables.replaceEmoji = value;
}
bool Settings::replaceEmoji() const {
return _variables.replaceEmoji.current();
}
rpl::producer<bool> Settings::replaceEmojiValue() const {
return _variables.replaceEmoji.value();
}
rpl::producer<bool> Settings::replaceEmojiChanges() const {
return _variables.replaceEmoji.changes();
}
} // namespace Main

View File

@ -0,0 +1,295 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "data/data_auto_download.h"
enum class SendFilesWay;
namespace Ui {
enum class InputSubmitSettings;
} // namespace Ui
namespace Support {
enum class SwitchSettings;
} // namespace Support
namespace Window {
enum class Column;
} // namespace Window
namespace ChatHelpers {
enum class SelectorTab;
} // namespace ChatHelpers
namespace Main {
class Settings final {
public:
void moveFrom(Settings &&other) {
_variables = std::move(other._variables);
}
[[nodiscard]] QByteArray serialize() const;
void constructFromSerialized(const QByteArray &serialized);
void setLastSeenWarningSeen(bool lastSeenWarningSeen) {
_variables.lastSeenWarningSeen = lastSeenWarningSeen;
}
[[nodiscard]] bool lastSeenWarningSeen() const {
return _variables.lastSeenWarningSeen;
}
void setSendFilesWay(SendFilesWay way) {
_variables.sendFilesWay = way;
}
[[nodiscard]] SendFilesWay sendFilesWay() const {
return _variables.sendFilesWay;
}
void setSendSubmitWay(Ui::InputSubmitSettings value) {
_variables.sendSubmitWay = value;
}
[[nodiscard]] Ui::InputSubmitSettings sendSubmitWay() const {
return _variables.sendSubmitWay;
}
void setSupportSwitch(Support::SwitchSettings value) {
_variables.supportSwitch = value;
}
[[nodiscard]] Support::SwitchSettings supportSwitch() const {
return _variables.supportSwitch;
}
void setSupportFixChatsOrder(bool fix) {
_variables.supportFixChatsOrder = fix;
}
[[nodiscard]] bool supportFixChatsOrder() const {
return _variables.supportFixChatsOrder;
}
void setSupportTemplatesAutocomplete(bool enabled) {
_variables.supportTemplatesAutocomplete = enabled;
}
[[nodiscard]] bool supportTemplatesAutocomplete() const {
return _variables.supportTemplatesAutocomplete;
}
void setSupportChatsTimeSlice(int slice);
[[nodiscard]] int supportChatsTimeSlice() const;
[[nodiscard]] rpl::producer<int> supportChatsTimeSliceValue() const;
void setSupportAllSearchResults(bool all);
[[nodiscard]] bool supportAllSearchResults() const;
[[nodiscard]] rpl::producer<bool> supportAllSearchResultsValue() const;
[[nodiscard]] ChatHelpers::SelectorTab selectorTab() const {
return _variables.selectorTab;
}
void setSelectorTab(ChatHelpers::SelectorTab tab) {
_variables.selectorTab = tab;
}
[[nodiscard]] bool tabbedSelectorSectionEnabled() const {
return _variables.tabbedSelectorSectionEnabled;
}
void setTabbedSelectorSectionEnabled(bool enabled);
[[nodiscard]] bool thirdSectionInfoEnabled() const {
return _variables.thirdSectionInfoEnabled;
}
void setThirdSectionInfoEnabled(bool enabled);
[[nodiscard]] rpl::producer<bool> thirdSectionInfoEnabledValue() const;
[[nodiscard]] int thirdSectionExtendedBy() const {
return _variables.thirdSectionExtendedBy;
}
void setThirdSectionExtendedBy(int savedValue) {
_variables.thirdSectionExtendedBy = savedValue;
}
[[nodiscard]] bool tabbedReplacedWithInfo() const {
return _tabbedReplacedWithInfo;
}
void setTabbedReplacedWithInfo(bool enabled);
[[nodiscard]] rpl::producer<bool> tabbedReplacedWithInfoValue() const;
void setSmallDialogsList(bool enabled) {
_variables.smallDialogsList = enabled;
}
[[nodiscard]] bool smallDialogsList() const {
return _variables.smallDialogsList;
}
void setSoundOverride(const QString &key, const QString &path) {
_variables.soundOverrides.insert(key, path);
}
void clearSoundOverrides() {
_variables.soundOverrides.clear();
}
[[nodiscard]] QString getSoundPath(const QString &key) const;
void setTabbedSelectorSectionTooltipShown(int shown) {
_variables.tabbedSelectorSectionTooltipShown = shown;
}
[[nodiscard]] int tabbedSelectorSectionTooltipShown() const {
return _variables.tabbedSelectorSectionTooltipShown;
}
void setFloatPlayerColumn(Window::Column column) {
_variables.floatPlayerColumn = column;
}
[[nodiscard]] Window::Column floatPlayerColumn() const {
return _variables.floatPlayerColumn;
}
void setFloatPlayerCorner(RectPart corner) {
_variables.floatPlayerCorner = corner;
}
[[nodiscard]] RectPart floatPlayerCorner() const {
return _variables.floatPlayerCorner;
}
void setDialogsWidthRatio(float64 ratio);
[[nodiscard]] float64 dialogsWidthRatio() const;
[[nodiscard]] rpl::producer<float64> dialogsWidthRatioChanges() const;
void setThirdColumnWidth(int width);
[[nodiscard]] int thirdColumnWidth() const;
[[nodiscard]] rpl::producer<int> thirdColumnWidthChanges() const;
void setGroupStickersSectionHidden(PeerId peerId) {
_variables.groupStickersSectionHidden.insert(peerId);
}
[[nodiscard]] bool isGroupStickersSectionHidden(PeerId peerId) const {
return _variables.groupStickersSectionHidden.contains(peerId);
}
void removeGroupStickersSectionHidden(PeerId peerId) {
_variables.groupStickersSectionHidden.remove(peerId);
}
[[nodiscard]] Data::AutoDownload::Full &autoDownload() {
return _variables.autoDownload;
}
[[nodiscard]] const Data::AutoDownload::Full &autoDownload() const {
return _variables.autoDownload;
}
void setArchiveCollapsed(bool collapsed);
[[nodiscard]] bool archiveCollapsed() const;
[[nodiscard]] rpl::producer<bool> archiveCollapsedChanges() const;
void setArchiveInMainMenu(bool inMainMenu);
[[nodiscard]] bool archiveInMainMenu() const;
[[nodiscard]] rpl::producer<bool> archiveInMainMenuChanges() const;
void setNotifyAboutPinned(bool notify);
[[nodiscard]] bool notifyAboutPinned() const;
[[nodiscard]] rpl::producer<bool> notifyAboutPinnedChanges() const;
void setSkipArchiveInSearch(bool skip);
[[nodiscard]] bool skipArchiveInSearch() const;
[[nodiscard]] rpl::producer<bool> skipArchiveInSearchChanges() const;
[[nodiscard]] bool hadLegacyCallsPeerToPeerNobody() const {
return _variables.hadLegacyCallsPeerToPeerNobody;
}
[[nodiscard]] bool includeMutedCounter() const {
return _variables.includeMutedCounter;
}
void setIncludeMutedCounter(bool value) {
_variables.includeMutedCounter = value;
}
[[nodiscard]] bool countUnreadMessages() const {
return _variables.countUnreadMessages;
}
void setCountUnreadMessages(bool value) {
_variables.countUnreadMessages = value;
}
[[nodiscard]] bool exeLaunchWarning() const {
return _variables.exeLaunchWarning;
}
void setExeLaunchWarning(bool warning) {
_variables.exeLaunchWarning = warning;
}
[[nodiscard]] bool autoplayGifs() const {
return _variables.autoplayGifs;
}
void setAutoplayGifs(bool value) {
_variables.autoplayGifs = value;
}
[[nodiscard]] bool loopAnimatedStickers() const {
return _variables.loopAnimatedStickers;
}
void setLoopAnimatedStickers(bool value) {
_variables.loopAnimatedStickers = value;
}
void setLargeEmoji(bool value);
[[nodiscard]] bool largeEmoji() const;
[[nodiscard]] rpl::producer<bool> largeEmojiValue() const;
[[nodiscard]] rpl::producer<bool> largeEmojiChanges() const;
void setReplaceEmoji(bool value);
[[nodiscard]] bool replaceEmoji() const;
[[nodiscard]] rpl::producer<bool> replaceEmojiValue() const;
[[nodiscard]] rpl::producer<bool> replaceEmojiChanges() const;
[[nodiscard]] bool suggestEmoji() const {
return _variables.suggestEmoji;
}
void setSuggestEmoji(bool value) {
_variables.suggestEmoji = value;
}
[[nodiscard]] bool suggestStickersByEmoji() const {
return _variables.suggestStickersByEmoji;
}
void setSuggestStickersByEmoji(bool value) {
_variables.suggestStickersByEmoji = value;
}
private:
struct Variables {
Variables();
static constexpr auto kDefaultDialogsWidthRatio = 5. / 14;
static constexpr auto kDefaultThirdColumnWidth = 0;
bool lastSeenWarningSeen = false;
SendFilesWay sendFilesWay;
ChatHelpers::SelectorTab selectorTab; // per-window
bool tabbedSelectorSectionEnabled = false; // per-window
int tabbedSelectorSectionTooltipShown = 0;
QMap<QString, QString> soundOverrides;
Window::Column floatPlayerColumn; // per-window
RectPart floatPlayerCorner; // per-window
base::flat_set<PeerId> groupStickersSectionHidden;
bool thirdSectionInfoEnabled = true; // per-window
bool smallDialogsList = false; // per-window
int thirdSectionExtendedBy = -1; // per-window
rpl::variable<float64> dialogsWidthRatio
= kDefaultDialogsWidthRatio; // per-window
rpl::variable<int> thirdColumnWidth
= kDefaultThirdColumnWidth; // per-window
Ui::InputSubmitSettings sendSubmitWay;
bool hadLegacyCallsPeerToPeerNobody = false;
bool includeMutedCounter = true;
bool countUnreadMessages = true;
bool exeLaunchWarning = true;
Data::AutoDownload::Full autoDownload;
rpl::variable<bool> archiveCollapsed = false;
rpl::variable<bool> archiveInMainMenu = false;
rpl::variable<bool> notifyAboutPinned = true;
rpl::variable<bool> skipArchiveInSearch = false;
bool autoplayGifs = true;
bool loopAnimatedStickers = true;
rpl::variable<bool> largeEmoji = true;
rpl::variable<bool> replaceEmoji = true;
bool suggestEmoji = true;
bool suggestStickersByEmoji = true;
static constexpr auto kDefaultSupportChatsLimitSlice
= 7 * 24 * 60 * 60;
Support::SwitchSettings supportSwitch;
bool supportFixChatsOrder = true;
bool supportTemplatesAutocomplete = true;
rpl::variable<int> supportChatsTimeSlice
= kDefaultSupportChatsLimitSlice;
rpl::variable<bool> supportAllSearchResults = false;
};
rpl::event_stream<bool> _thirdSectionInfoEnabledValue;
bool _tabbedReplacedWithInfo = false;
rpl::event_stream<bool> _tabbedReplacedWithInfoValue;
Variables _variables;
};
} // namespace Main

View File

@ -28,10 +28,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h"
#include "window/themes/window_theme_editor.h"
#include "window/themes/window_theme.h"
#include "window/themes/window_themes_embedded.h"
#include "window/window_session_controller.h"
#include "info/profile/info_profile_button.h"
#include "storage/localstorage.h"
#include "core/file_utilities.h"
#include "core/application.h"
#include "data/data_session.h"
#include "chat_helpers/emoji_sets_manager.h"
#include "platform/platform_info.h"
@ -43,58 +45,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_boxes.h"
namespace Settings {
namespace {
const auto kColorizeIgnoredKeys = base::flat_set<QLatin1String>{ {
qstr("boxTextFgGood"),
qstr("boxTextFgError"),
qstr("historyPeer1NameFg"),
qstr("historyPeer1NameFgSelected"),
qstr("historyPeer1UserpicBg"),
qstr("historyPeer2NameFg"),
qstr("historyPeer2NameFgSelected"),
qstr("historyPeer2UserpicBg"),
qstr("historyPeer3NameFg"),
qstr("historyPeer3NameFgSelected"),
qstr("historyPeer3UserpicBg"),
qstr("historyPeer4NameFg"),
qstr("historyPeer4NameFgSelected"),
qstr("historyPeer4UserpicBg"),
qstr("historyPeer5NameFg"),
qstr("historyPeer5NameFgSelected"),
qstr("historyPeer5UserpicBg"),
qstr("historyPeer6NameFg"),
qstr("historyPeer6NameFgSelected"),
qstr("historyPeer6UserpicBg"),
qstr("historyPeer7NameFg"),
qstr("historyPeer7NameFgSelected"),
qstr("historyPeer7UserpicBg"),
qstr("historyPeer8NameFg"),
qstr("historyPeer8NameFgSelected"),
qstr("historyPeer8UserpicBg"),
qstr("msgFile1Bg"),
qstr("msgFile1BgDark"),
qstr("msgFile1BgOver"),
qstr("msgFile1BgSelected"),
qstr("msgFile2Bg"),
qstr("msgFile2BgDark"),
qstr("msgFile2BgOver"),
qstr("msgFile2BgSelected"),
qstr("msgFile3Bg"),
qstr("msgFile3BgDark"),
qstr("msgFile3BgOver"),
qstr("msgFile3BgSelected"),
qstr("msgFile4Bg"),
qstr("msgFile4BgDark"),
qstr("msgFile4BgOver"),
qstr("msgFile4BgSelected"),
qstr("mediaviewFileRedCornerFg"),
qstr("mediaviewFileYellowCornerFg"),
qstr("mediaviewFileGreenCornerFg"),
qstr("mediaviewFileBlueCornerFg"),
} };
} // namespace
class BackgroundRow : public Ui::RpWidget {
public:
@ -127,23 +77,9 @@ private:
class DefaultTheme final : public Ui::AbstractCheckView {
public:
enum class Type {
DayBlue,
Default,
Night,
NightGreen,
};
struct Scheme {
Type type = Type();
QColor background;
QColor sent;
QColor received;
QColor radiobuttonInactive;
QColor radiobuttonActive;
tr::phrase<> name;
QString path;
QColor accentColor;
};
using Type = Window::Theme::EmbeddedType;
using Scheme = Window::Theme::EmbeddedScheme;
DefaultTheme(Scheme scheme, bool checked);
QSize getSize() const override;
@ -155,10 +91,13 @@ public:
QImage prepareRippleMask() const override;
bool checkRippleStartPosition(QPoint position) const override;
void setColorizer(const Window::Theme::Colorizer *colorizer);
private:
void checkedChangedHook(anim::type animated) override;
Scheme _scheme;
Scheme _colorized;
Ui::RadioView _radio;
};
@ -369,8 +308,17 @@ DefaultTheme::DefaultTheme(Scheme scheme, bool checked)
: AbstractCheckView(st::defaultRadio.duration, checked, nullptr)
, _scheme(scheme)
, _radio(st::defaultRadio, checked, [=] { update(); }) {
_radio.setToggledOverride(_scheme.radiobuttonActive);
_radio.setUntoggledOverride(_scheme.radiobuttonInactive);
setColorizer(nullptr);
}
void DefaultTheme::setColorizer(const Window::Theme::Colorizer *colorizer) {
_colorized = _scheme;
if (colorizer) {
Window::Theme::Colorize(_colorized, colorizer);
}
_radio.setToggledOverride(_colorized.radiobuttonActive);
_radio.setUntoggledOverride(_colorized.radiobuttonInactive);
update();
}
QSize DefaultTheme::getSize() const {
@ -394,13 +342,13 @@ void DefaultTheme::paint(
p.fillRect(
QRect(QPoint(), st::settingsThemePreviewSize),
_scheme.background);
_colorized.background);
PainterHighQualityEnabler hq(p);
p.setPen(Qt::NoPen);
p.setBrush(_scheme.received);
p.setBrush(_colorized.received);
p.drawRoundedRect(rtlrect(received, outerWidth), radius, radius);
p.setBrush(_scheme.sent);
p.setBrush(_colorized.sent);
p.drawRoundedRect(rtlrect(sent, outerWidth), radius, radius);
const auto radio = _radio.getSize();
@ -824,79 +772,13 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
using Scheme = DefaultTheme::Scheme;
const auto block = container->add(object_ptr<Ui::FixedHeightWidget>(
container));
const auto scheme = DefaultTheme::Scheme();
const auto color = [](str_const hex) {
Expects(hex.size() == 6);
const auto component = [](char a, char b) {
const auto convert = [](char ch) {
Expects((ch >= '0' && ch <= '9')
|| (ch >= 'A' && ch <= 'F')
|| (ch >= 'a' && ch <= 'f'));
return (ch >= '0' && ch <= '9')
? int(ch - '0')
: int(ch - ((ch >= 'A' && ch <= 'F') ? 'A' : 'a') + 10);
};
return convert(a) * 16 + convert(b);
};
return QColor(
component(hex[0], hex[1]),
component(hex[2], hex[3]),
component(hex[4], hex[5]));
};
static const auto schemes = {
Scheme{
Type::DayBlue,
color("7ec4ea"),
color("d7f0ff"),
color("ffffff"),
color("d7f0ff"),
color("ffffff"),
tr::lng_settings_theme_blue,
":/gui/day-blue.tdesktop-theme",
color("40a7e3")
},
Scheme{
Type::Default,
color("90ce89"),
color("eaffdc"),
color("ffffff"),
color("eaffdc"),
color("ffffff"),
tr::lng_settings_theme_classic,
QString()
},
Scheme{
Type::Night,
color("485761"),
color("5ca7d4"),
color("6b808d"),
color("6b808d"),
color("5ca7d4"),
tr::lng_settings_theme_midnight,
":/gui/night.tdesktop-theme",
color("5288c1")
},
Scheme{
Type::NightGreen,
color("485761"),
color("74bf93"),
color("6b808d"),
color("6b808d"),
color("74bf93"),
tr::lng_settings_theme_matrix,
":/gui/night-green.tdesktop-theme",
color("3fc1b0")
},
};
const auto chosen = [&] {
static const auto SchemesList = Window::Theme::EmbeddedThemes();
const auto chosen = [] {
if (Window::Theme::IsNonDefaultBackground()) {
return Type(-1);
}
const auto path = Window::Theme::Background()->themeAbsolutePath();
for (const auto &scheme : schemes) {
for (const auto &scheme : SchemesList) {
if (path == scheme.path) {
return scheme.type;
}
@ -922,23 +804,26 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
Window::Theme::KeepApplied();
}
};
const auto applyWithColor = [=](
const Scheme &scheme,
const QColor &color) {
const auto colorizer = Window::Theme::ColorizerFrom(
scheme,
color);
apply(scheme, &colorizer);
};
const auto applyWithColorize = [=](const Scheme &scheme) {
const auto &colors = Core::App().settings().themesAccentColors();
const auto color = colors.get(scheme.type);
const auto box = Ui::show(Box<EditColorBox>(
"Choose accent color",
scheme.accentColor));
color.value_or(scheme.accentColor)));
box->setSaveCallback([=](QColor result) {
auto colorizer = Window::Theme::Colorizer();
colorizer.ignoreKeys = kColorizeIgnoredKeys;
colorizer.hueThreshold = 10;
scheme.accentColor.getHsv(
&colorizer.wasHue,
&colorizer.wasSaturation,
&colorizer.wasValue);
result.getHsv(
&colorizer.nowHue,
&colorizer.nowSaturation,
&colorizer.nowValue);
apply(scheme, &colorizer);
Core::App().settings().themesAccentColors().set(
scheme.type,
result);
Core::App().saveSettingsDelayed();
applyWithColor(scheme, result);
});
};
const auto schemeClicked = [=](
@ -947,12 +832,18 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
if (scheme.accentColor.hue() && (modifiers & Qt::ControlModifier)) {
applyWithColorize(scheme);
} else {
apply(scheme);
const auto &colors = Core::App().settings().themesAccentColors();
if (const auto color = colors.get(scheme.type)) {
applyWithColor(scheme, *color);
} else {
apply(scheme);
}
}
};
auto checks = base::flat_map<Type,not_null<DefaultTheme*>>();
auto buttons = ranges::view::all(
schemes
SchemesList
) | ranges::view::transform([&](const Scheme &scheme) {
auto check = std::make_unique<DefaultTheme>(scheme, false);
const auto weak = check.get();
@ -967,9 +858,30 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
schemeClicked(scheme, result->clickModifiers());
});
weak->setUpdateCallback([=] { result->update(); });
checks.emplace(scheme.type, weak);
return result;
}) | ranges::to_vector;
const auto refreshColorizer = [=](Type type) {
const auto &colors = Core::App().settings().themesAccentColors();
const auto i = checks.find(type);
const auto scheme = ranges::find(SchemesList, type, &Scheme::type);
if (i != end(checks) && scheme != end(SchemesList)) {
if (const auto color = colors.get(type)) {
const auto colorizer = Window::Theme::ColorizerFrom(
*scheme,
*color);
i->second->setColorizer(&colorizer);
} else {
i->second->setColorizer(nullptr);
}
}
};
for (const auto &scheme : SchemesList) {
refreshColorizer(scheme.type);
}
using Update = const Window::Theme::BackgroundUpdate;
base::ObservableViewer(
*Window::Theme::Background()
@ -979,6 +891,7 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
}) | rpl::map([=] {
return chosen();
}) | rpl::start_with_next([=](Type type) {
refreshColorizer(type);
group->setValue(type);
}, container->lifetime());
@ -1025,6 +938,12 @@ void SetupDefaultThemes(not_null<Ui::VerticalLayout*> container) {
}
}, block->lifetime());
const auto colors = container->add(
object_ptr<Ui::SlideWrap<>>(
container,
object_ptr<Ui::FixedHeightWidget>(
container)));
AddSkip(container);
}

View File

@ -616,6 +616,7 @@ enum {
dbiCallSettings = 0x5b,
dbiCacheSettings = 0x5c,
dbiTxtDomainString = 0x5d,
dbiApplicationSettings = 0x5e,
dbiEncryptedWithSalt = 333,
dbiEncrypted = 444,
@ -927,6 +928,14 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
context.dcOptions.constructFromSerialized(serialized);
} break;
case dbiApplicationSettings: {
auto serialized = QByteArray();
stream >> serialized;
if (!_checkStreamStatus(stream)) return false;
Core::App().settings().constructFromSerialized(serialized);
} break;
case dbiChatSizeMax: {
qint32 maxSize;
stream >> maxSize;
@ -2618,10 +2627,12 @@ void writeSettings() {
}
settings.writeData(_settingsSalt);
auto dcOptionsSerialized = Core::App().dcOptions()->serialize();
const auto dcOptionsSerialized = Core::App().dcOptions()->serialize();
const auto applicationSettings = Core::App().settings().serialize();
quint32 size = 12 * (sizeof(quint32) + sizeof(qint32));
size += sizeof(quint32) + Serialize::bytearraySize(dcOptionsSerialized);
size += sizeof(quint32) + Serialize::bytearraySize(applicationSettings);
size += sizeof(quint32) + Serialize::stringSize(cLoggedPhoneNumber());
size += sizeof(quint32) + Serialize::stringSize(Global::TxtDomainString());
@ -2660,6 +2671,7 @@ void writeSettings() {
data.stream << quint32(dbiLastUpdateCheck) << qint32(cLastUpdateCheck());
data.stream << quint32(dbiScalePercent) << qint32(cConfigScale());
data.stream << quint32(dbiDcOptions) << dcOptionsSerialized;
data.stream << quint32(dbiApplicationSettings) << applicationSettings;
data.stream << quint32(dbiLoggedPhoneNumber) << cLoggedPhoneNumber();
data.stream << quint32(dbiTxtDomainString) << Global::TxtDomainString();
data.stream << quint32(dbiAnimationsDisabled) << qint32(anim::Disabled() ? 1 : 0);

View File

@ -21,6 +21,23 @@ constexpr auto kModernImageLocationTag = std::numeric_limits<qint32>::min();
} // namespace
void writeColor(QDataStream &stream, const QColor &color) {
stream << (quint32(uchar(color.red()))
| (quint32(uchar(color.green())) << 8)
| (quint32(uchar(color.blue())) << 16)
| (quint32(uchar(color.alpha())) << 24));
}
QColor readColor(QDataStream &stream) {
auto value = quint32();
stream >> value;
return QColor(
int(value & 0xFFU),
int((value >> 8) & 0xFFU),
int((value >> 16) & 0xFFU),
int((value >> 24) & 0xFFU));
}
std::optional<StorageImageLocation> readLegacyStorageImageLocationOrTag(
int streamAppVersion,
QDataStream &stream) {

View File

@ -23,6 +23,13 @@ inline int bytesSize(bytes::const_span bytes) {
return sizeof(quint32) + bytes.size();
}
inline int colorSize() {
return sizeof(quint32);
}
void writeColor(QDataStream &stream, const QColor &color);
QColor readColor(QDataStream &stream);
struct ReadBytesVectorWrap {
bytes::vector &bytes;
};

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/themes/window_theme.h"
#include "window/themes/window_theme_preview.h"
#include "window/themes/window_themes_embedded.h"
#include "mainwidget.h"
#include "main/main_session.h"
#include "apiwrap.h"
@ -33,6 +34,7 @@ constexpr auto kThemeBackgroundSizeLimit = 4 * 1024 * 1024;
constexpr auto kBackgroundSizeLimit = 25 * 1024 * 1024;
constexpr auto kThemeSchemeSizeLimit = 1024 * 1024;
constexpr auto kNightThemeFile = str_const(":/gui/night.tdesktop-theme");
constexpr auto kMinimumTiledSize = 512;
struct Applying {
QString pathRelative;
@ -143,75 +145,6 @@ bool readNameAndValue(const char *&from, const char *end, QLatin1String *outName
return true;
}
void Colorize(
uchar &r,
uchar &g,
uchar &b,
not_null<const Colorizer*> colorizer) {
auto color = QColor(int(r), int(g), int(b));
auto hue = 0;
auto saturation = 0;
auto value = 0;
color.getHsv(&hue, &saturation, &value);
const auto changeColor = std::abs(hue - colorizer->wasHue)
<= colorizer->hueThreshold;
const auto nowHue = hue + (colorizer->nowHue - colorizer->wasHue);
const auto nowSaturation = ((saturation > colorizer->wasSaturation)
&& (colorizer->nowSaturation > colorizer->wasSaturation))
? (((colorizer->nowSaturation * (255 - colorizer->wasSaturation))
+ ((saturation - colorizer->wasSaturation)
* (255 - colorizer->nowSaturation)))
/ (255 - colorizer->wasSaturation))
: ((saturation != colorizer->wasSaturation)
&& (colorizer->wasSaturation != 0))
? ((saturation * colorizer->nowSaturation)
/ colorizer->wasSaturation)
: colorizer->nowSaturation;
const auto nowValue = (value > colorizer->wasValue)
? (((colorizer->nowValue * (255 - colorizer->wasValue))
+ ((value - colorizer->wasValue)
* (255 - colorizer->nowValue)))
/ (255 - colorizer->wasValue))
: (value < colorizer->wasValue)
? ((value * colorizer->nowValue)
/ colorizer->wasValue)
: colorizer->nowValue;
auto nowR = 0;
auto nowG = 0;
auto nowB = 0;
QColor::fromHsv(
changeColor ? ((nowHue + 360) % 360) : hue,
changeColor ? nowSaturation : saturation,
nowValue
).getRgb(&nowR, &nowG, &nowB);
r = uchar(nowR);
g = uchar(nowG);
b = uchar(nowB);
}
void Colorize(uint32 &pixel, not_null<const Colorizer*> colorizer) {
const auto chars = reinterpret_cast<uchar*>(&pixel);
Colorize(
chars[2],
chars[1],
chars[0],
colorizer);
}
void Colorize(QImage &image, not_null<const Colorizer*> colorizer) {
image = std::move(image).convertToFormat(QImage::Format_ARGB32);
const auto bytes = image.bits();
const auto bytesPerLine = image.bytesPerLine();
for (auto line = 0; line != image.height(); ++line) {
const auto ints = reinterpret_cast<uint32*>(
bytes + line * bytesPerLine);
const auto end = ints + image.width();
for (auto p = ints; p != end; ++p) {
Colorize(*p, colorizer);
}
}
}
enum class SetResult {
Ok,
Bad,

View File

@ -16,7 +16,7 @@ class Session;
namespace Window {
namespace Theme {
constexpr auto kMinimumTiledSize = 512;
struct Colorizer;
struct Cached {
QByteArray colors;
@ -49,17 +49,6 @@ struct Preview {
QImage preview;
};
struct Colorizer {
int wasHue = 0;
int wasSaturation = 0;
int wasValue = 0;
int nowHue = 0;
int nowSaturation = 0;
int nowValue = 0;
int hueThreshold = 0;
base::flat_set<QLatin1String> ignoreKeys;
};
bool Apply(const QString &filepath);
bool Apply(std::unique_ptr<Preview> preview);
void ApplyDefaultWithPath(

View File

@ -0,0 +1,365 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "window/themes/window_themes_embedded.h"
#include "window/themes/window_theme.h"
#include "storage/serialize_common.h"
namespace Window {
namespace Theme {
namespace {
constexpr auto kMaxAccentColors = 3;
const auto kColorizeIgnoredKeys = base::flat_set<QLatin1String>{ {
qstr("boxTextFgGood"),
qstr("boxTextFgError"),
qstr("historyPeer1NameFg"),
qstr("historyPeer1NameFgSelected"),
qstr("historyPeer1UserpicBg"),
qstr("historyPeer2NameFg"),
qstr("historyPeer2NameFgSelected"),
qstr("historyPeer2UserpicBg"),
qstr("historyPeer3NameFg"),
qstr("historyPeer3NameFgSelected"),
qstr("historyPeer3UserpicBg"),
qstr("historyPeer4NameFg"),
qstr("historyPeer4NameFgSelected"),
qstr("historyPeer4UserpicBg"),
qstr("historyPeer5NameFg"),
qstr("historyPeer5NameFgSelected"),
qstr("historyPeer5UserpicBg"),
qstr("historyPeer6NameFg"),
qstr("historyPeer6NameFgSelected"),
qstr("historyPeer6UserpicBg"),
qstr("historyPeer7NameFg"),
qstr("historyPeer7NameFgSelected"),
qstr("historyPeer7UserpicBg"),
qstr("historyPeer8NameFg"),
qstr("historyPeer8NameFgSelected"),
qstr("historyPeer8UserpicBg"),
qstr("msgFile1Bg"),
qstr("msgFile1BgDark"),
qstr("msgFile1BgOver"),
qstr("msgFile1BgSelected"),
qstr("msgFile2Bg"),
qstr("msgFile2BgDark"),
qstr("msgFile2BgOver"),
qstr("msgFile2BgSelected"),
qstr("msgFile3Bg"),
qstr("msgFile3BgDark"),
qstr("msgFile3BgOver"),
qstr("msgFile3BgSelected"),
qstr("msgFile4Bg"),
qstr("msgFile4BgDark"),
qstr("msgFile4BgOver"),
qstr("msgFile4BgSelected"),
qstr("mediaviewFileRedCornerFg"),
qstr("mediaviewFileYellowCornerFg"),
qstr("mediaviewFileGreenCornerFg"),
qstr("mediaviewFileBlueCornerFg"),
} };
QColor Color(str_const hex) {
Expects(hex.size() == 6);
const auto component = [](char a, char b) {
const auto convert = [](char ch) {
Expects((ch >= '0' && ch <= '9')
|| (ch >= 'A' && ch <= 'F')
|| (ch >= 'a' && ch <= 'f'));
return (ch >= '0' && ch <= '9')
? int(ch - '0')
: int(ch - ((ch >= 'A' && ch <= 'F') ? 'A' : 'a') + 10);
};
return convert(a) * 16 + convert(b);
};
return QColor(
component(hex[0], hex[1]),
component(hex[2], hex[3]),
component(hex[4], hex[5]));
};
} // namespace
Colorizer ColorizerFrom(const EmbeddedScheme &scheme, const QColor &color) {
auto result = Colorizer();
result.ignoreKeys = kColorizeIgnoredKeys;
result.hueThreshold = 10;
scheme.accentColor.getHsv(
&result.wasHue,
&result.wasSaturation,
&result.wasValue);
color.getHsv(
&result.nowHue,
&result.nowSaturation,
&result.nowValue);
return result;
}
void Colorize(
uchar &r,
uchar &g,
uchar &b,
not_null<const Colorizer*> colorizer) {
auto color = QColor(int(r), int(g), int(b));
auto hue = 0;
auto saturation = 0;
auto value = 0;
color.getHsv(&hue, &saturation, &value);
const auto changeColor = std::abs(hue - colorizer->wasHue)
<= colorizer->hueThreshold;
const auto nowHue = hue + (colorizer->nowHue - colorizer->wasHue);
const auto nowSaturation = ((saturation > colorizer->wasSaturation)
&& (colorizer->nowSaturation > colorizer->wasSaturation))
? (((colorizer->nowSaturation * (255 - colorizer->wasSaturation))
+ ((saturation - colorizer->wasSaturation)
* (255 - colorizer->nowSaturation)))
/ (255 - colorizer->wasSaturation))
: ((saturation != colorizer->wasSaturation)
&& (colorizer->wasSaturation != 0))
? ((saturation * colorizer->nowSaturation)
/ colorizer->wasSaturation)
: colorizer->nowSaturation;
const auto nowValue = (value > colorizer->wasValue)
? (((colorizer->nowValue * (255 - colorizer->wasValue))
+ ((value - colorizer->wasValue)
* (255 - colorizer->nowValue)))
/ (255 - colorizer->wasValue))
: (value < colorizer->wasValue)
? ((value * colorizer->nowValue)
/ colorizer->wasValue)
: colorizer->nowValue;
auto nowR = 0;
auto nowG = 0;
auto nowB = 0;
QColor::fromHsv(
changeColor ? ((nowHue + 360) % 360) : hue,
changeColor ? nowSaturation : saturation,
nowValue
).getRgb(&nowR, &nowG, &nowB);
r = uchar(nowR);
g = uchar(nowG);
b = uchar(nowB);
}
void Colorize(uint32 &pixel, not_null<const Colorizer*> colorizer) {
const auto chars = reinterpret_cast<uchar*>(&pixel);
Colorize(
chars[2],
chars[1],
chars[0],
colorizer);
}
void Colorize(QColor &color, not_null<const Colorizer*> colorizer) {
auto r = uchar(color.red());
auto g = uchar(color.green());
auto b = uchar(color.blue());
Colorize(r, g, b, colorizer);
color = QColor(r, g, b, color.alpha());
}
void Colorize(QImage &image, not_null<const Colorizer*> colorizer) {
image = std::move(image).convertToFormat(QImage::Format_ARGB32);
const auto bytes = image.bits();
const auto bytesPerLine = image.bytesPerLine();
for (auto line = 0; line != image.height(); ++line) {
const auto ints = reinterpret_cast<uint32*>(
bytes + line * bytesPerLine);
const auto end = ints + image.width();
for (auto p = ints; p != end; ++p) {
Colorize(*p, colorizer);
}
}
}
void Colorize(EmbeddedScheme &scheme, not_null<const Colorizer*> colorizer) {
const auto colors = {
&EmbeddedScheme::background,
&EmbeddedScheme::sent,
&EmbeddedScheme::received,
&EmbeddedScheme::radiobuttonActive,
&EmbeddedScheme::radiobuttonInactive
};
for (const auto color : colors) {
Colorize(scheme.*color, colorizer);
}
}
std::vector<EmbeddedScheme> EmbeddedThemes() {
return {
EmbeddedScheme{
EmbeddedType::DayBlue,
Color("7ec4ea"),
Color("d7f0ff"),
Color("ffffff"),
Color("d7f0ff"),
Color("ffffff"),
tr::lng_settings_theme_blue,
":/gui/day-blue.tdesktop-theme",
Color("40a7e3")
},
EmbeddedScheme{
EmbeddedType::Default,
Color("90ce89"),
Color("eaffdc"),
Color("ffffff"),
Color("eaffdc"),
Color("ffffff"),
tr::lng_settings_theme_classic,
QString()
},
EmbeddedScheme{
EmbeddedType::Night,
Color("485761"),
Color("5ca7d4"),
Color("6b808d"),
Color("6b808d"),
Color("5ca7d4"),
tr::lng_settings_theme_midnight,
":/gui/night.tdesktop-theme",
Color("5288c1")
},
EmbeddedScheme{
EmbeddedType::NightGreen,
Color("485761"),
Color("75bfab"),
Color("6b808d"),
Color("6b808d"),
Color("75bfab"),
tr::lng_settings_theme_matrix,
":/gui/night-green.tdesktop-theme",
Color("3fc1b0")
},
};
}
std::vector<QColor> AccentColors(EmbeddedType type) {
switch (type) {
case EmbeddedType::DayBlue:
return {
//Color("3478f5"),
Color("58bfe8"),
Color("58b040"),
Color("da73a2"),
Color("e28830"),
Color("9073e7"),
Color("9073e7"),
Color("e3b63e"),
Color("71829c")
};
case EmbeddedType::Default:
return {};
case EmbeddedType::Night:
return {
//Color("3478f5"),
Color("58bfe8"),
Color("58b040"),
Color("da73a2"),
Color("e28830"),
Color("9073e7"),
Color("9073e7"),
Color("e3b63e"),
Color("71829c")
};
case EmbeddedType::NightGreen:
return {
Color("3478f5"),
//Color("58bfe8"),
Color("58b040"),
Color("da73a2"),
Color("e28830"),
Color("9073e7"),
Color("9073e7"),
Color("e3b63e"),
Color("71829c")
};
}
Unexpected("Type in Window::Theme::AccentColors.");
}
QByteArray AccentColors::serialize() const {
auto result = QByteArray();
if (_data.empty()) {
return result;
}
const auto count = _data.size();
auto size = sizeof(qint32) * (count + 1)
+ Serialize::colorSize() * count;
result.reserve(size);
auto stream = QDataStream(&result, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_5_1);
stream << qint32(_data.size());
for (const auto &[type, color] : _data) {
stream << static_cast<qint32>(type);
Serialize::writeColor(stream, color);
}
stream.device()->close();
return result;
}
bool AccentColors::setFromSerialized(const QByteArray &serialized) {
if (serialized.isEmpty()) {
_data.clear();
return true;
}
auto copy = QByteArray(serialized);
auto stream = QDataStream(&copy, QIODevice::ReadOnly);
stream.setVersion(QDataStream::Qt_5_1);
auto count = qint32();
stream >> count;
if (stream.status() != QDataStream::Ok) {
return false;
} else if (count <= 0 || count > kMaxAccentColors) {
return false;
}
auto data = base::flat_map<EmbeddedType, QColor>();
for (auto i = 0; i != count; ++i) {
auto type = qint32();
stream >> type;
const auto color = Serialize::readColor(stream);
const auto uncheckedType = static_cast<EmbeddedType>(type);
switch (uncheckedType) {
case EmbeddedType::DayBlue:
case EmbeddedType::Night:
case EmbeddedType::NightGreen:
data.emplace(uncheckedType, color);
break;
default:
return false;
}
}
if (stream.status() != QDataStream::Ok) {
return false;
}
_data = std::move(data);
return true;
}
void AccentColors::set(EmbeddedType type, const QColor &value) {
_data.emplace_or_assign(type, value);
}
void AccentColors::clear(EmbeddedType type) {
_data.remove(type);
}
std::optional<QColor> AccentColors::get(EmbeddedType type) const {
const auto i = _data.find(type);
return (i != end(_data)) ? std::make_optional(i->second) : std::nullopt;
}
} // namespace Theme
} // namespace Window

View File

@ -0,0 +1,77 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "lang/lang_keys.h"
class QImage;
namespace Window {
namespace Theme {
enum class EmbeddedType {
DayBlue,
Default,
Night,
NightGreen,
};
struct EmbeddedScheme {
EmbeddedType type = EmbeddedType();
QColor background;
QColor sent;
QColor received;
QColor radiobuttonInactive;
QColor radiobuttonActive;
tr::phrase<> name;
QString path;
QColor accentColor;
};
class AccentColors final {
public:
[[nodiscard]] QByteArray serialize() const;
bool setFromSerialized(const QByteArray &serialized);
void set(EmbeddedType type, const QColor &value);
void clear(EmbeddedType type);
[[nodiscard]] std::optional<QColor> get(EmbeddedType type) const;
private:
base::flat_map<EmbeddedType, QColor> _data;
};
struct Colorizer {
int wasHue = 0;
int wasSaturation = 0;
int wasValue = 0;
int nowHue = 0;
int nowSaturation = 0;
int nowValue = 0;
int hueThreshold = 0;
base::flat_set<QLatin1String> ignoreKeys;
};
[[nodiscard]] Colorizer ColorizerFrom(
const EmbeddedScheme &scheme,
const QColor &color);
void Colorize(
uchar &r,
uchar &g,
uchar &b,
not_null<const Colorizer*> colorizer);
void Colorize(QImage &image, not_null<const Colorizer*> colorizer);
void Colorize(EmbeddedScheme &scheme, not_null<const Colorizer*> colorizer);
[[nodiscard]] std::vector<EmbeddedScheme> EmbeddedThemes();
[[nodiscard]] std::vector<QColor> DefaultAccentColors(EmbeddedType type);
} // namespace Theme
} // namespace Window

View File

@ -145,6 +145,8 @@
<(src_loc)/core/click_handler_types.h
<(src_loc)/core/core_cloud_password.cpp
<(src_loc)/core/core_cloud_password.h
<(src_loc)/core/core_settings.cpp
<(src_loc)/core/core_settings.h
<(src_loc)/core/crash_report_window.cpp
<(src_loc)/core/crash_report_window.h
<(src_loc)/core/crash_reports.cpp
@ -467,6 +469,8 @@
<(src_loc)/main/main_app_config.h
<(src_loc)/main/main_session.cpp
<(src_loc)/main/main_session.h
<(src_loc)/main/main_settings.cpp
<(src_loc)/main/main_settings.h
<(src_loc)/media/audio/media_audio.cpp
<(src_loc)/media/audio/media_audio.h
<(src_loc)/media/audio/media_audio_capture.cpp
@ -893,6 +897,8 @@
<(src_loc)/window/themes/window_theme_preview.h
<(src_loc)/window/themes/window_theme_warning.cpp
<(src_loc)/window/themes/window_theme_warning.h
<(src_loc)/window/themes/window_themes_embedded.cpp
<(src_loc)/window/themes/window_themes_embedded.h
<(src_loc)/apiwrap.cpp
<(src_loc)/apiwrap.h
<(src_loc)/app.cpp