Move session data localstorage -> storage_account.

This commit is contained in:
John Preston 2020-06-09 20:57:05 +04:00
parent 739a3ebe97
commit ad4afe9293
64 changed files with 5190 additions and 4652 deletions

View File

@ -155,6 +155,7 @@ PRIVATE
api/api_chat_filters.cpp
api/api_chat_filters.h
api/api_common.h
api/api_hash.cpp
api/api_hash.h
api/api_self_destruct.cpp
api/api_self_destruct.h
@ -883,6 +884,10 @@ PRIVATE
settings/settings_privacy_controllers.h
settings/settings_privacy_security.cpp
settings/settings_privacy_security.h
storage/details/storage_file_utilities.cpp
storage/details/storage_file_utilities.h
storage/details/storage_settings_scheme.cpp
storage/details/storage_settings_scheme.h
storage/download_manager_mtproto.cpp
storage/download_manager_mtproto.h
storage/file_download.cpp
@ -901,6 +906,8 @@ PRIVATE
storage/serialize_common.h
storage/serialize_document.cpp
storage/serialize_document.h
storage/storage_account.cpp
storage/storage_account.h
storage/storage_cloud_blob.cpp
storage/storage_cloud_blob.h
storage/storage_facade.cpp

View File

@ -0,0 +1,94 @@
/*
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 "api/api_hash.h"
#include "data/data_document.h"
#include "data/data_session.h"
#include "data/stickers/data_stickers.h"
#include "main/main_session.h"
namespace Api {
namespace {
[[nodiscard]] int32 CountDocumentVectorHash(
const QVector<DocumentData*> vector) {
auto result = HashInit();
for (const auto document : vector) {
HashUpdate(result, document->id);
}
return HashFinalize(result);
}
[[nodiscard]] int32 CountSpecialStickerSetHash(
not_null<Main::Session*> session,
uint64 setId) {
const auto &sets = session->data().stickers().sets();
const auto it = sets.find(setId);
if (it != sets.cend()) {
return CountDocumentVectorHash(it->second->stickers);
}
return 0;
}
} // namespace
int32 CountStickersHash(
not_null<Main::Session*> session,
bool checkOutdatedInfo) {
auto result = HashInit();
bool foundOutdated = false;
const auto &sets = session->data().stickers().sets();
const auto &order = session->data().stickers().setsOrder();
for (auto i = order.cbegin(), e = order.cend(); i != e; ++i) {
auto it = sets.find(*i);
if (it != sets.cend()) {
const auto set = it->second.get();
if (set->id == Data::Stickers::DefaultSetId) {
foundOutdated = true;
} else if (!(set->flags & MTPDstickerSet_ClientFlag::f_special)
&& !(set->flags & MTPDstickerSet::Flag::f_archived)) {
HashUpdate(result, set->hash);
}
}
}
return (!checkOutdatedInfo || !foundOutdated)
? HashFinalize(result)
: 0;
}
int32 CountRecentStickersHash(not_null<Main::Session*> session) {
return CountSpecialStickerSetHash(
session,
Data::Stickers::CloudRecentSetId);
}
int32 CountFavedStickersHash(not_null<Main::Session*> session) {
return CountSpecialStickerSetHash(session, Data::Stickers::FavedSetId);
}
int32 CountFeaturedStickersHash(not_null<Main::Session*> session) {
auto result = HashInit();
const auto &sets = session->data().stickers().sets();
const auto &featured = session->data().stickers().featuredSetsOrder();
for (const auto setId : featured) {
HashUpdate(result, setId);
const auto it = sets.find(setId);
if (it != sets.cend()
&& (it->second->flags & MTPDstickerSet_ClientFlag::f_unread)) {
HashUpdate(result, 1);
}
}
return HashFinalize(result);
}
int32 CountSavedGifsHash(not_null<Main::Session*> session) {
return CountDocumentVectorHash(session->data().stickers().savedGifs());
}
} // namespace Api

View File

@ -7,8 +7,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
namespace Main {
class Session;
} // namespace Main
namespace Api {
[[nodiscard]] int32 CountStickersHash(
not_null<Main::Session*> session,
bool checkOutdatedInfo = false);
[[nodiscard]] int32 CountRecentStickersHash(
not_null<Main::Session*> session);
[[nodiscard]] int32 CountFavedStickersHash(not_null<Main::Session*> session);
[[nodiscard]] int32 CountFeaturedStickersHash(
not_null<Main::Session*> session);
[[nodiscard]] int32 CountSavedGifsHash(not_null<Main::Session*> session);
[[nodiscard]] inline uint32 HashInit() {
return 0;
}

View File

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "apiwrap.h"
#include "api/api_hash.h"
#include "api/api_sending.h"
#include "api/api_text_entities.h"
#include "api/api_self_destruct.h"
@ -45,7 +46,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_message.h"
#include "history/history_item_components.h"
//#include "history/feed/history_feed_section.h" // #feed
#include "storage/localstorage.h"
#include "main/main_session.h"
#include "main/main_account.h"
#include "boxes/confirm_box.h"
@ -67,6 +67,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/storage_shared_media.h"
#include "storage/storage_user_photos.h"
#include "storage/storage_media_prepare.h"
#include "storage/storage_account.h"
#include "facades.h"
#include "app.h"
//#include "storage/storage_feed_messages.h" // #feed
@ -267,6 +268,10 @@ Main::Session &ApiWrap::session() const {
return *_session;
}
Storage::Account &ApiWrap::local() const {
return _session->local();
}
void ApiWrap::setupSupportMode() {
if (!_session->supportMode()) {
return;
@ -1980,11 +1985,12 @@ void ApiWrap::saveStickerSets(
}
}
if (writeInstalled) Local::writeInstalledStickers();
if (writeRecent) Local::writeUserSettings();
if (writeArchived) Local::writeArchivedStickers();
if (writeCloudRecent) Local::writeRecentStickers();
if (writeFaved) Local::writeFavedStickers();
auto &storage = local();
if (writeInstalled) storage.writeInstalledStickers();
if (writeRecent) storage.writeSettings();
if (writeArchived) storage.writeArchivedStickers();
if (writeCloudRecent) storage.writeRecentStickers();
if (writeFaved) storage.writeFavedStickers();
_session->data().stickers().notifyUpdated();
if (_stickerSetDisenableRequests.empty()) {
@ -2927,25 +2933,25 @@ void ApiWrap::refreshFileReference(
request(MTPmessages_GetRecentStickers(
MTP_flags(0),
MTP_int(0)),
[] { crl::on_main([] { Local::writeRecentStickers(); }); });
[=] { crl::on_main(&session(), [=] { local().writeRecentStickers(); }); });
} else if (data.setId == Data::Stickers::FavedSetId) {
request(MTPmessages_GetFavedStickers(MTP_int(0)),
[] { crl::on_main([] { Local::writeFavedStickers(); }); });
[=] { crl::on_main(&session(), [=] { local().writeFavedStickers(); }); });
} else {
request(MTPmessages_GetStickerSet(
MTP_inputStickerSetID(
MTP_long(data.setId),
MTP_long(data.accessHash))),
[] { crl::on_main([] {
Local::writeInstalledStickers();
Local::writeRecentStickers();
Local::writeFavedStickers();
[=] { crl::on_main(&session(), [=] {
local().writeInstalledStickers();
local().writeRecentStickers();
local().writeFavedStickers();
}); });
}
}, [&](Data::FileOriginSavedGifs data) {
request(
MTPmessages_GetSavedGifs(MTP_int(0)),
[] { crl::on_main([] { Local::writeSavedGifs(); }); });
[=] { crl::on_main(&session(), [=] { local().writeSavedGifs(); }); });
}, [&](Data::FileOriginWallpaper data) {
request(MTPaccount_GetWallPaper(
MTP_inputWallPaper(
@ -3165,7 +3171,7 @@ void ApiWrap::requestStickers(TimeId now) {
}
};
_stickersUpdateRequest = request(MTPmessages_GetAllStickers(
MTP_int(Local::countStickersHash(true))
MTP_int(Api::CountStickersHash(&session(), true))
)).done(onDone).fail([=](const RPCError &error) {
LOG(("App Fail: Failed to get stickers!"));
onDone(MTP_messages_allStickersNotModified());
@ -3176,7 +3182,8 @@ void ApiWrap::requestRecentStickers(TimeId now) {
if (!_session->data().stickers().recentUpdateNeeded(now)) {
return;
}
requestRecentStickersWithHash(Local::countRecentStickersHash());
requestRecentStickersWithHash(
Api::CountRecentStickersHash(&session()));
}
void ApiWrap::requestRecentStickersWithHash(int32 hash) {
@ -3218,7 +3225,7 @@ void ApiWrap::requestFavedStickers(TimeId now) {
return;
}
_favedStickersUpdateRequest = request(MTPmessages_GetFavedStickers(
MTP_int(Local::countFavedStickersHash())
MTP_int(Api::CountFavedStickersHash(&session()))
)).done([=](const MTPmessages_FavedStickers &result) {
_session->data().stickers().setLastFavedUpdate(crl::now());
_favedStickersUpdateRequest = 0;
@ -3250,7 +3257,7 @@ void ApiWrap::requestFeaturedStickers(TimeId now) {
return;
}
_featuredStickersUpdateRequest = request(MTPmessages_GetFeaturedStickers(
MTP_int(Local::countFeaturedStickersHash())
MTP_int(Api::CountFeaturedStickersHash(&session()))
)).done([=](const MTPmessages_FeaturedStickers &result) {
_session->data().stickers().setLastFeaturedUpdate(crl::now());
_featuredStickersUpdateRequest = 0;
@ -3280,7 +3287,7 @@ void ApiWrap::requestSavedGifs(TimeId now) {
return;
}
_savedGifsUpdateRequest = request(MTPmessages_GetSavedGifs(
MTP_int(Local::countSavedGifsHash())
MTP_int(Api::CountSavedGifsHash(&session()))
)).done([=](const MTPmessages_SavedGifs &result) {
_session->data().stickers().setLastSavedGifsUpdate(crl::now());
_savedGifsUpdateRequest = 0;
@ -3331,7 +3338,7 @@ void ApiWrap::readFeaturedSets() {
auto requestData = MTPmessages_ReadFeaturedStickers(
MTP_vector<MTPlong>(wrappedIds));
request(std::move(requestData)).done([=](const MTPBool &result) {
Local::writeFeaturedStickers();
local().writeFeaturedStickers();
_session->data().stickers().notifyUpdated();
}).send();
@ -4786,7 +4793,7 @@ void ApiWrap::sendMessage(MessageToSend &&message) {
if (!peer->canWrite() || Api::SendDice(message)) {
return;
}
Local::saveRecentSentHashtags(textWithTags.text);
local().saveRecentSentHashtags(textWithTags.text);
auto sending = TextWithEntities();
auto left = TextWithEntities {

View File

@ -38,6 +38,7 @@ namespace Storage {
enum class SharedMediaType : signed char;
struct PreparedList;
class DownloadMtprotoTask;
class Account;
} // namespace Storage
namespace Dialogs {
@ -136,7 +137,8 @@ public:
explicit ApiWrap(not_null<Main::Session*> session);
~ApiWrap();
Main::Session &session() const;
[[nodiscard]] Main::Session &session() const;
[[nodiscard]] Storage::Account &local() const;
void applyUpdates(
const MTPUpdates &updates,

View File

@ -210,7 +210,7 @@ void AutoDownloadBox::setupContent() {
}
}
if (changed || hiddenChanged) {
Local::writeUserSettings();
_session->saveSettingsDelayed();
}
if (allowMoreTypes.contains(Type::Photo)) {
_session->data().photoLoadSettingsChanged();

View File

@ -43,7 +43,7 @@ void AutoLockBox::prepare() {
void AutoLockBox::durationChanged(int seconds) {
Global::SetAutoLock(seconds);
Local::writeUserSettings();
_session->saveSettingsDelayed();
Global::RefLocalPasscodeChanged().notify();
Core::App().checkAutoLock();

View File

@ -8,17 +8,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/download_path_box.h"
#include "lang/lang_keys.h"
#include "storage/localstorage.h"
#include "core/file_utilities.h"
#include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h"
#include "platform/platform_specific.h"
#include "facades.h"
#include "window/window_session_controller.h"
#include "main/main_session.h"
#include "storage/storage_account.h"
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
DownloadPathBox::DownloadPathBox(QWidget *parent)
: _path(Global::DownloadPath())
DownloadPathBox::DownloadPathBox(
QWidget *parent,
not_null<Window::SessionController*> controller)
: _controller(controller)
, _path(Global::DownloadPath())
, _pathBookmark(Global::DownloadPathBookmark())
, _group(std::make_shared<Ui::RadioenumGroup<Directory>>(typeFromPath(_path)))
, _default(this, _group, Directory::Downloads, tr::lng_download_path_default_radio(tr::now), st::defaultBoxCheckbox)
@ -119,7 +124,7 @@ void DownloadPathBox::save() {
};
Global::SetDownloadPath(computePath());
Global::SetDownloadPathBookmark((value == Directory::Custom) ? _pathBookmark : QByteArray());
Local::writeUserSettings();
_controller->session().local().writeSettings();
Global::RefDownloadPathChanged().notify();
closeBox();
#endif // OS_WIN_STORE

View File

@ -18,9 +18,15 @@ class Radioenum;
class LinkButton;
} // namespace Ui
namespace Window {
class SessionController;
} // namespace Window
class DownloadPathBox : public Ui::BoxContent {
public:
DownloadPathBox(QWidget *parent);
DownloadPathBox(
QWidget *parent,
not_null<Window::SessionController*> controller);
protected:
void prepare() override;
@ -48,6 +54,7 @@ private:
void setPathText(const QString &text);
void editPath();
const not_null<Window::SessionController*> _controller;
QString _path;
QByteArray _pathBookmark;

View File

@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/continuous_sliders.h"
#include "ui/effects/radial_animation.h"
#include "ui/emoji_config.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "storage/cache/storage_cache_database.h"
#include "data/data_session.h"
#include "lang/lang_keys.h"
@ -271,8 +271,8 @@ LocalStorageBox::LocalStorageBox(
: _session(session)
, _db(&session->data().cache())
, _dbBig(&session->data().cacheBigFile()) {
const auto &settings = Local::cacheSettings();
const auto &settingsBig = Local::cacheBigFileSettings();
const auto &settings = session->local().cacheSettings();
const auto &settingsBig = session->local().cacheBigFileSettings();
_totalSizeLimit = settings.totalSizeLimit + settingsBig.totalSizeLimit;
_mediaSizeLimit = settingsBig.totalSizeLimit;
_timeLimit = settings.totalTimeLimit;
@ -560,8 +560,8 @@ void LocalStorageBox::setupLimits(not_null<Ui::VerticalLayout*> container) {
}
void LocalStorageBox::limitsChanged() {
const auto &settings = Local::cacheSettings();
const auto &settingsBig = Local::cacheBigFileSettings();
const auto &settings = _session->local().cacheSettings();
const auto &settingsBig = _session->local().cacheBigFileSettings();
const auto sizeLimit = _totalSizeLimit - _mediaSizeLimit;
const auto changed = (settings.totalSizeLimit != sizeLimit)
|| (settingsBig.totalSizeLimit != _mediaSizeLimit)
@ -590,7 +590,7 @@ void LocalStorageBox::save() {
auto updateBig = Storage::Cache::Database::SettingsUpdate();
updateBig.totalSizeLimit = _mediaSizeLimit;
updateBig.totalTimeLimit = _timeLimit;
Local::updateCacheSettings(update, updateBig);
_session->local().updateCacheSettings(update, updateBig);
_session->data().cache().updateSettings(update);
closeBox();
}

View File

@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "main/main_session.h"
#include "core/application.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h"
#include "ui/widgets/labels.h"
@ -451,7 +451,7 @@ void PasscodeBox::save(bool force) {
return;
}
if (Local::checkPasscode(old.toUtf8())) {
if (_session->local().checkPasscode(old.toUtf8())) {
cSetPasscodeBadTries(0);
if (_turningOff) pwd = conf = QString();
} else {
@ -519,7 +519,7 @@ void PasscodeBox::save(bool force) {
closeReplacedBy();
const auto weak = Ui::MakeWeak(this);
cSetPasscodeBadTries(0);
Local::setPasscode(pwd.toUtf8());
_session->local().setPasscode(pwd.toUtf8());
Core::App().localPasscodeChanged();
if (weak) {
closeBox();

View File

@ -13,7 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwindow.h"
#include "mainwidget.h"
#include "base/qthelp_url.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "boxes/confirm_box.h"
#include "apiwrap.h"
#include "ui/toast/toast.h"
@ -1101,7 +1101,7 @@ QString AppendShareGameScoreUrl(
*reinterpret_cast<uint64*>(shareHashEncrypted.data()) ^= *reinterpret_cast<uint64*>(channelAccessHashInts);
// Encrypt data.
if (!Local::encrypt(shareHashData.constData(), shareHashEncrypted.data() + key128Size, shareHashData.size(), shareHashEncrypted.constData())) {
if (!session->local().encrypt(shareHashData.constData(), shareHashEncrypted.data() + key128Size, shareHashData.size(), shareHashEncrypted.constData())) {
return url;
}
@ -1137,7 +1137,7 @@ void ShareGameScoreByHash(
// Decrypt data.
auto hashData = QByteArray(hashEncrypted.size() - key128Size, Qt::Uninitialized);
if (!Local::decrypt(hashEncrypted.constData() + key128Size, hashData.data(), hashEncrypted.size() - key128Size, hashEncrypted.constData())) {
if (!session->local().decrypt(hashEncrypted.constData() + key128Size, hashData.data(), hashEncrypted.size() - key128Size, hashEncrypted.constData())) {
return;
}

View File

@ -16,7 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/confirm_box.h"
#include "core/application.h"
#include "mtproto/sender.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "dialogs/dialogs_layout.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/scroll_area.h"
@ -417,9 +417,9 @@ void StickerSetBox::Inner::installDone(
result.c_messages_stickerSetInstallResultArchive());
} else {
if (wasArchived) {
Local::writeArchivedStickers();
_controller->session().local().writeArchivedStickers();
}
Local::writeInstalledStickers();
_controller->session().local().writeInstalledStickers();
_controller->session().data().stickers().notifyUpdated();
}
_setInstalled.fire_copy(_setId);

View File

@ -20,7 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/confirm_box.h"
#include "boxes/sticker_set_box.h"
#include "apiwrap.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "dialogs/dialogs_layout.h"
#include "lottie/lottie_single_player.h"
#include "chat_helpers/stickers_lottie.h"
@ -498,7 +498,7 @@ void StickersBox::getArchivedDone(
void StickersBox::prepare() {
if (_section == Section::Installed) {
if (_tabs) {
Local::readArchivedStickers();
_session->local().readArchivedStickers();
} else {
setTitle(tr::lng_stickers_group_set());
}
@ -866,7 +866,7 @@ void StickersBox::saveChanges() {
rebuildList(&_installed);
if (_someArchivedLoaded) {
Local::writeArchivedStickers();
_session->local().writeArchivedStickers();
}
_session->api().saveStickerSets(_installed.widget()->getOrder(), _installed.widget()->getRemovedSets());
}

View File

@ -19,7 +19,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/stickers_lottie.h"
#include "mainwindow.h"
#include "apiwrap.h"
#include "storage/localstorage.h"
#include "main/main_session.h"
#include "storage/storage_account.h"
#include "lottie/lottie_single_player.h"
#include "ui/widgets/scroll_area.h"
#include "ui/image/image.h"
@ -931,7 +932,7 @@ void FieldAutocompleteInner::mousePressEvent(QMouseEvent *e) {
}
}
if (removed) {
Local::writeRecentHashtagsAndBots();
_controller->session().local().writeRecentHashtagsAndBots();
}
_parent->updateFiltered();

View File

@ -23,7 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lottie/lottie_animation.h"
#include "boxes/stickers_box.h"
#include "inline_bots/inline_bot_result.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "lang/lang_keys.h"
#include "mainwindow.h"
#include "dialogs/dialogs_layout.h"
@ -2127,7 +2127,7 @@ void StickersListWidget::removeRecentSticker(int section, int index) {
for (int32 i = 0, l = recent.size(); i < l; ++i) {
if (recent.at(i).first == document) {
recent.removeAt(i);
Local::writeUserSettings();
session().local().writeSettings();
refresh = true;
break;
}
@ -2142,7 +2142,7 @@ void StickersListWidget::removeRecentSticker(int section, int index) {
if (set->stickers.isEmpty()) {
sets.erase(it);
}
Local::writeInstalledStickers();
session().local().writeInstalledStickers();
refresh = true;
break;
}
@ -2573,7 +2573,7 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
auto removeHiddenForGroup = [this, &hidden] {
if (hidden) {
session().settings().removeGroupStickersSectionHidden(_megagroupSet->id);
Local::writeUserSettings();
session().local().writeSettings();
hidden = false;
}
};
@ -2984,7 +2984,7 @@ void StickersListWidget::sendInstallRequest(
void StickersListWidget::removeMegagroupSet(bool locally) {
if (locally) {
session().settings().setGroupStickersSectionHidden(_megagroupSet->id);
Local::writeUserSettings();
session().local().writeSettings();
refreshStickers();
return;
}
@ -3044,8 +3044,8 @@ void StickersListWidget::removeSet(uint64 setId) {
int removeIndex = session().data().stickers().setsOrder().indexOf(_removingSetId);
if (removeIndex >= 0) session().data().stickers().setsOrderRef().removeAt(removeIndex);
refreshStickers();
Local::writeInstalledStickers();
if (writeRecent) Local::writeUserSettings();
session().local().writeInstalledStickers();
if (writeRecent) session().local().writeSettings();
}
_removingSetId = 0;
_checkForHide.fire({});

View File

@ -56,6 +56,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/emoji_config.h"
#include "ui/effects/animations.h"
#include "storage/serialize_common.h"
#include "storage/storage_account.h"
#include "window/window_session_controller.h"
#include "window/window_controller.h"
#include "base/qthelp_regex.h"
@ -124,6 +125,11 @@ Application::Application(not_null<Launcher*> launcher)
) | rpl::filter([=](MTP::Instance *instance) {
return instance != nullptr;
}) | rpl::start_with_next([=](not_null<MTP::Instance*> mtp) {
if (_window) {
// This should be called when user settings are read.
// Right now after they are read the startMtp() is called.
_window->widget()->updateTrayMenu();
}
if (!UpdaterDisabled()) {
UpdateChecker().setMtproto(mtp.get());
}
@ -232,8 +238,8 @@ void Application::run() {
startShortcuts();
App::initMedia();
Local::ReadMapState state = Local::readMap(QByteArray());
if (state == Local::ReadMapPassNeeded) {
const auto state = activeAccount().local().start(QByteArray());
if (state == Storage::StartResult::IncorrectPasscode) {
Global::SetLocalPasscode(true);
Global::RefLocalPasscodeChanged().notify();
lockByPasscode();

View File

@ -7,8 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "core/changelogs.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "data/data_session.h"
#include "mainwindow.h"
#include "apiwrap.h"
@ -79,7 +80,7 @@ Changelogs::Changelogs(not_null<Main::Session*> session, int oldVersion)
std::unique_ptr<Changelogs> Changelogs::Create(
not_null<Main::Session*> session) {
const auto oldVersion = Local::oldMapVersion();
const auto oldVersion = session->local().oldMapVersion();
return (oldVersion > 0 && oldVersion < AppVersion)
? std::make_unique<Changelogs>(session, oldVersion)
: nullptr;

View File

@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
#include "boxes/confirm_box.h"
#include "base/qthelp_regex.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "history/view/history_view_element.h"
#include "history/history_item.h"
#include "data/data_user.h"
@ -83,12 +83,14 @@ void BotGameUrlClickHandler::onClick(ClickContext context) const {
};
if (url.startsWith(qstr("tg://"), Qt::CaseInsensitive)) {
open();
} else if (!_bot || _bot->isVerified() || Local::isBotTrusted(_bot)) {
} else if (!_bot
|| _bot->isVerified()
|| _bot->session().local().isBotTrusted(_bot)) {
open();
} else {
const auto callback = [=, bot = _bot] {
Ui::hideLayer();
Local::makeBotTrusted(bot);
bot->session().local().markBotTrusted(bot);
open();
};
Ui::show(Box<ConfirmBox>(

View File

@ -345,7 +345,7 @@ bool GetDefault(
QString path = files.isEmpty() ? QString() : QFileInfo(files.back()).absoluteDir().absolutePath();
if (!path.isEmpty() && path != cDialogLastPath()) {
cSetDialogLastPath(path);
Local::writeUserSettings();
Local::writeSettings();
}
return !files.isEmpty();
} else if (type == Type::ReadFolder) {
@ -366,7 +366,7 @@ bool GetDefault(
auto path = QFileInfo(file).absoluteDir().absolutePath();
if (!path.isEmpty() && path != cDialogLastPath()) {
cSetDialogLastPath(path);
Local::writeUserSettings();
Local::writeSettings();
}
}
files = QStringList(file);

View File

@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "media/streaming/media_streaming_loader_mtproto.h"
#include "media/streaming/media_streaming_loader_local.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "storage/streamed_file_downloader.h"
#include "storage/file_download_mtproto.h"
#include "storage/file_download_web.h"
@ -138,7 +139,7 @@ QString FileNameUnsafe(
QString path = dir.absolutePath();
if (path != cDialogLastPath()) {
cSetDialogLastPath(path);
Local::writeUserSettings();
Local::writeSettings();
}
}
@ -901,11 +902,11 @@ void DocumentData::setLoadedInMediaCache(bool loaded) {
_flags = flags;
if (filepath().isEmpty()) {
if (loadedInMediaCache()) {
Local::writeFileLocation(
session().local().writeFileLocation(
mediaKey(),
FileLocation::InMediaCacheLocation());
} else {
Local::removeFileLocation(mediaKey());
session().local().removeFileLocation(mediaKey());
}
owner().requestDocumentViewRepaint(this);
}
@ -941,7 +942,9 @@ void DocumentData::save(
f.close();
setLocation(FileLocation(toFile));
Local::writeFileLocation(mediaKey(), FileLocation(toFile));
session().local().writeFileLocation(
mediaKey(),
FileLocation(toFile));
} else if (l.accessEnable()) {
const auto &alreadyName = l.name();
if (alreadyName != toFile) {
@ -1136,7 +1139,7 @@ QByteArray documentWaveformEncode5bit(const VoiceWaveform &waveform) {
const FileLocation &DocumentData::location(bool check) const {
if (check && !_location.check()) {
const auto location = Local::readFileLocation(mediaKey());
const auto location = session().local().readFileLocation(mediaKey());
const auto that = const_cast<DocumentData*>(this);
if (location.inMediaCache()) {
that->setLoadedInMediaCacheLocation();
@ -1190,7 +1193,7 @@ bool DocumentData::saveFromDataChecked() {
}
file.close();
_location = FileLocation(path);
Local::writeFileLocation(mediaKey(), _location);
session().local().writeFileLocation(mediaKey(), _location);
return true;
}
@ -1543,13 +1546,13 @@ void DocumentData::setRemoteLocation(
_access = access;
if (!isNull()) {
if (_location.check()) {
Local::writeFileLocation(mediaKey(), _location);
session().local().writeFileLocation(mediaKey(), _location);
} else {
_location = Local::readFileLocation(mediaKey());
_location = session().local().readFileLocation(mediaKey());
if (_location.inMediaCache()) {
setLoadedInMediaCacheLocation();
} else if (_location.isEmpty() && loadedInMediaCache()) {
Local::writeFileLocation(
session().local().writeFileLocation(
mediaKey(),
FileLocation::InMediaCacheLocation());
}
@ -1579,7 +1582,7 @@ void DocumentData::collectLocalData(not_null<DocumentData*> local) {
}
if (!local->_location.inMediaCache() && !local->_location.isEmpty()) {
_location = local->_location;
Local::writeFileLocation(mediaKey(), _location);
session().local().writeFileLocation(mediaKey(), _location);
}
}

View File

@ -25,7 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/view/media/history_view_media.h"
#include "history/view/history_view_element.h"
#include "inline_bots/inline_bot_layout_item.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "storage/storage_encrypted_file.h"
#include "main/main_account.h"
#include "media/player/media_player_instance.h" // instance()->play()
@ -203,11 +203,11 @@ std::vector<UnavailableReason> ExtractUnavailableReasons(
Session::Session(not_null<Main::Session*> session)
: _session(session)
, _cache(Core::App().databases().get(
Local::cachePath(),
Local::cacheSettings()))
_session->local().cachePath(),
_session->local().cacheSettings()))
, _bigFileCache(Core::App().databases().get(
Local::cacheBigFilePath(),
Local::cacheBigFileSettings()))
_session->local().cacheBigFilePath(),
_session->local().cacheBigFileSettings()))
, _chatsList(FilterId(), PinnedDialogsCountMaxValue(session))
, _contactsList(Dialogs::SortMode::Name)
, _contactsNoChatsList(Dialogs::SortMode::Name)
@ -225,11 +225,11 @@ Session::Session(not_null<Main::Session*> session)
, _mediaRotation(std::make_unique<MediaRotation>())
, _histories(std::make_unique<Histories>(this))
, _stickers(std::make_unique<Stickers>(this)) {
_cache->open(Local::cacheKey());
_bigFileCache->open(Local::cacheBigFileKey());
_cache->open(_session->local().cacheKey());
_bigFileCache->open(_session->local().cacheBigFileKey());
if constexpr (Platform::IsLinux()) {
const auto wasVersion = Local::oldMapVersion();
const auto wasVersion = _session->local().oldMapVersion();
if (wasVersion >= 1007011 && wasVersion < 1007015) {
_bigFileCache->clear();
_cache->clearByTag(Data::kImageCacheTag);
@ -446,7 +446,7 @@ not_null<UserData*> Session::processUser(const MTPUser &data) {
&& (result->id != _session->userPeerId());
}
// see also Local::readPeer
// see also Serialize::readPeer
const auto pname = (showPhoneChanged || phoneChanged || nameChanged)
? ((showPhone && !phone.isEmpty())
@ -2433,7 +2433,7 @@ void Session::documentConvert(
cache().moveIfEmpty(oldCacheKey, original->cacheKey());
cache().moveIfEmpty(oldGoodKey, original->goodThumbnailCacheKey());
if (stickers().savedGifs().indexOf(original) >= 0) {
Local::writeSavedGifs();
_session->local().writeSavedGifs();
}
}
}

View File

@ -71,7 +71,7 @@ void UserData::setIsContact(bool is) {
}
}
// see Local::readPeer as well
// see Serialize::readPeer as well
void UserData::setPhoto(const MTPUserProfilePhoto &photo) {
photo.match([&](const MTPDuserProfilePhoto &data) {
updateUserpic(

View File

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "data/stickers/data_stickers.h"
#include "api/api_hash.h"
#include "data/data_document.h"
#include "data/data_session.h"
#include "data/data_user.h"
@ -16,7 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_item.h"
#include "history/history_item_components.h"
#include "apiwrap.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "main/main_session.h"
#include "ui/toast/toast.h"
#include "ui/image/image_location_factory.h"
@ -73,7 +74,7 @@ void Stickers::addSavedGif(not_null<DocumentData*> document) {
if (_savedGifs.size() > Global::SavedGifsLimit()) {
_savedGifs.pop_back();
}
Local::writeSavedGifs();
session().local().writeSavedGifs();
notifySavedGifsUpdated();
setLastSavedGifsUpdate(0);
@ -136,8 +137,8 @@ void Stickers::applyArchivedResult(
}
session().api().requestStickerSets();
}
Local::writeInstalledStickers();
Local::writeArchivedStickers();
session().local().writeInstalledStickers();
session().local().writeArchivedStickers();
Ui::Toast::Show(Ui::Toast::Config{
.text = { tr::lng_stickers_packs_archived(tr::now) },
@ -219,15 +220,15 @@ void Stickers::installLocally(uint64 setId) {
sets.erase(customIt);
}
}
Local::writeInstalledStickers();
session().local().writeInstalledStickers();
if (changedFlags & MTPDstickerSet_ClientFlag::f_unread) {
Local::writeFeaturedStickers();
session().local().writeFeaturedStickers();
}
if (changedFlags & MTPDstickerSet::Flag::f_archived) {
auto index = archivedSetsOrderRef().indexOf(setId);
if (index >= 0) {
archivedSetsOrderRef().removeAt(index);
Local::writeArchivedStickers();
session().local().writeArchivedStickers();
}
}
notifyUpdated();
@ -250,7 +251,7 @@ void Stickers::undoInstallLocally(uint64 setId) {
order.removeAt(currentIndex);
}
Local::writeInstalledStickers();
session().local().writeInstalledStickers();
notifyUpdated();
Ui::show(
@ -353,7 +354,7 @@ void Stickers::setIsFaved(
requestSetToPushFaved(document);
return;
}
Local::writeFavedStickers();
session().local().writeFavedStickers();
notifyUpdated();
session().api().stickerSetInstalled(FavedSetId);
}
@ -423,7 +424,7 @@ void Stickers::setIsNotFaved(not_null<DocumentData*> document) {
if (set->stickers.empty()) {
sets.erase(it);
}
Local::writeFavedStickers();
session().local().writeFavedStickers();
notifyUpdated();
}
@ -492,11 +493,14 @@ void Stickers::setsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
api.requestStickerSets();
}
Local::writeInstalledStickers();
if (writeRecent) Local::writeUserSettings();
session().local().writeInstalledStickers();
if (writeRecent) session().local().writeSettings();
if (Local::countStickersHash() != hash) {
LOG(("API Error: received stickers hash %1 while counted hash is %2").arg(hash).arg(Local::countStickersHash()));
const auto counted = Api::CountStickersHash(&session());
if (counted != hash) {
LOG(("API Error: received stickers hash %1 while counted hash is %2"
).arg(hash
).arg(counted));
}
notifyUpdated();
@ -613,22 +617,30 @@ void Stickers::specialSetReceived(
}
if (writeRecent) {
Local::writeUserSettings();
session().local().writeSettings();
}
}
switch (setId) {
case CloudRecentSetId: {
if (Local::countRecentStickersHash() != hash) {
LOG(("API Error: received recent stickers hash %1 while counted hash is %2").arg(hash).arg(Local::countRecentStickersHash()));
const auto counted = Api::CountRecentStickersHash(&session());
if (counted != hash) {
LOG(("API Error: "
"received recent stickers hash %1 while counted hash is %2"
).arg(hash
).arg(counted));
}
Local::writeRecentStickers();
session().local().writeRecentStickers();
} break;
case FavedSetId: {
if (Local::countFavedStickersHash() != hash) {
LOG(("API Error: received faved stickers hash %1 while counted hash is %2").arg(hash).arg(Local::countFavedStickersHash()));
const auto counted = Api::CountFavedStickersHash(&session());
if (counted != hash) {
LOG(("API Error: "
"received faved stickers hash %1 while counted hash is %2"
).arg(hash
).arg(counted));
}
Local::writeFavedStickers();
session().local().writeFavedStickers();
} break;
default: Unexpected("setId in SpecialSetReceived()");
}
@ -735,8 +747,12 @@ void Stickers::featuredSetsReceived(
}
setFeaturedSetsUnreadCount(unreadCount);
if (Local::countFeaturedStickersHash() != hash) {
LOG(("API Error: received featured stickers hash %1 while counted hash is %2").arg(hash).arg(Local::countFeaturedStickersHash()));
const auto counted = Api::CountFeaturedStickersHash(&session());
if (counted != hash) {
LOG(("API Error: "
"received featured stickers hash %1 while counted hash is %2"
).arg(hash
).arg(counted));
}
if (!setsToRequest.empty()) {
@ -747,7 +763,7 @@ void Stickers::featuredSetsReceived(
api.requestStickerSets();
}
Local::writeFeaturedStickers();
session().local().writeFeaturedStickers();
notifyUpdated();
}
@ -767,11 +783,15 @@ void Stickers::gifsReceived(const QVector<MTPDocument> &items, int32 hash) {
saved.push_back(document);
}
if (Local::countSavedGifsHash() != hash) {
LOG(("API Error: received saved gifs hash %1 while counted hash is %2").arg(hash).arg(Local::countSavedGifsHash()));
const auto counted = Api::CountSavedGifsHash(&session());
if (counted != hash) {
LOG(("API Error: "
"received saved gifs hash %1 while counted hash is %2"
).arg(hash
).arg(counted));
}
Local::writeSavedGifs();
session().local().writeSavedGifs();
notifySavedGifsUpdated();
}
@ -1118,21 +1138,21 @@ StickersSet *Stickers::feedSetFull(const MTPmessages_StickerSet &data) {
}
if (writeRecent) {
Local::writeUserSettings();
session().local().writeSettings();
}
if (set) {
const auto isArchived = !!(set->flags & MTPDstickerSet::Flag::f_archived);
if (set->flags & MTPDstickerSet::Flag::f_installed_date) {
if (!isArchived) {
Local::writeInstalledStickers();
session().local().writeInstalledStickers();
}
}
if (set->flags & MTPDstickerSet_ClientFlag::f_featured) {
Local::writeFeaturedStickers();
session().local().writeFeaturedStickers();
}
if (wasArchived != isArchived) {
Local::writeArchivedStickers();
session().local().writeArchivedStickers();
}
}
@ -1176,7 +1196,7 @@ QString Stickers::getSetTitle(const MTPDstickerSet &s) {
return title;
}
RecentStickerPack &Stickers::getRecentPack() {
RecentStickerPack &Stickers::getRecentPack() const {
if (cRecentStickers().isEmpty() && !cRecentStickersPreload().isEmpty()) {
const auto p = cRecentStickersPreload();
cSetRecentStickersPreload(RecentStickerPreload());

View File

@ -165,7 +165,7 @@ public:
QString getSetTitle(const MTPDstickerSet &s);
RecentStickerPack &getRecentPack();
RecentStickerPack &getRecentPack() const;
private:
bool updateNeeded(crl::time lastUpdate, crl::time now) const {

View File

@ -35,7 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h"
#include "mainwindow.h"
#include "mainwidget.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "apiwrap.h"
#include "window/themes/window_theme.h"
#include "observer_peer.h"
@ -1902,7 +1902,7 @@ void InnerWidget::onHashtagFilterUpdate(QStringRef newFilter) {
}
_hashtagFilter = newFilter.toString();
if (cRecentSearchHashtags().isEmpty() && cRecentWriteHashtags().isEmpty()) {
Local::readRecentHashtagsAndBots();
session().local().readRecentHashtagsAndBots();
}
auto &recent = cRecentSearchHashtags();
_hashtagResults.clear();
@ -2665,11 +2665,11 @@ bool InnerWidget::chooseHashtag() {
}
}
cSetRecentSearchHashtags(recent);
Local::writeRecentHashtagsAndBots();
session().local().writeRecentHashtagsAndBots();
emit refreshHashtags();
selectByMouse(QCursor::pos());
} else {
Local::saveRecentSearchHashtags('#' + hashtag->tag);
session().local().saveRecentSearchHashtags('#' + hashtag->tag);
emit completeHashtag(hashtag->tag);
}
return true;
@ -2723,7 +2723,7 @@ bool InnerWidget::chooseRow() {
const auto chosen = computeChosenRow();
if (chosen.key) {
if (IsServerMsgId(chosen.message.fullId.msg)) {
Local::saveRecentSearchHashtags(_filter);
session().local().saveRecentSearchHashtags(_filter);
}
_chosenRow.fire_copy(chosen);
return true;

View File

@ -32,7 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_slide_animation.h"
#include "window/window_connecting_widget.h"
#include "storage/storage_media_prepare.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "data/data_session.h"
#include "data/data_channel.h"
#include "data/data_chat.h"
@ -942,7 +942,7 @@ void Widget::searchMessages(
_searchTimer.stop();
onSearchMessages();
Local::saveRecentSearchHashtags(query);
session().local().saveRecentSearchHashtags(query);
}
}

View File

@ -14,7 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/wrap/padding_wrap.h"
#include "boxes/confirm_box.h"
#include "lang/lang_keys.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "core/file_utilities.h"
#include "main/main_session.h"
#include "data/data_session.h"
@ -51,7 +51,8 @@ void SuggestBox::prepare() {
addButton(tr::lng_box_ok(), [=] {
closeBox();
_session->data().startExport(Local::ReadExportSettings().singlePeer);
_session->data().startExport(
_session->local().readExportSettings().singlePeer);
});
addButton(tr::lng_export_suggest_cancel(), [=] { closeBox(); });
setCloseByOutsideClick(false);
@ -99,10 +100,10 @@ QPointer<Ui::BoxContent> SuggestStart(not_null<Main::Session*> session) {
void ClearSuggestStart(not_null<Main::Session*> session) {
session->data().clearExportSuggestion();
auto settings = Local::ReadExportSettings();
auto settings = session->local().readExportSettings();
if (settings.availableAt) {
settings.availableAt = 0;
Local::WriteExportSettings(settings);
session->local().writeExportSettings(settings);
}
}
@ -133,7 +134,8 @@ PanelController::PanelController(
not_null<Controller*> process)
: _session(session)
, _process(process)
, _settings(std::make_unique<Settings>(Local::ReadExportSettings()))
, _settings(
std::make_unique<Settings>(_session->local().readExportSettings()))
, _saveSettingsTimer([=] { saveSettings(); }) {
ResolveSettings(session, *_settings);
@ -401,7 +403,7 @@ void PanelController::saveSettings() const {
if (check(settings.path) == check(File::DefaultDownloadPath(_session))) {
settings.path = QString();
}
Local::WriteExportSettings(settings);
_session->local().writeExportSettings(settings);
}
} // namespace View

View File

@ -68,7 +68,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwidget.h"
#include "mainwindow.h"
#include "storage/localimageloader.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "storage/file_upload.h"
#include "storage/storage_media_prepare.h"
#include "media/audio/media_audio.h"
@ -1180,7 +1180,7 @@ void HistoryWidget::onDraftSaveDelayed() {
if (!_field->textCursor().position()
&& !_field->textCursor().anchor()
&& !_field->scrollTop().current()) {
if (!Local::hasDraftCursors(_peer->id)) {
if (!session().local().hasDraftCursors(_peer->id)) {
return;
}
}
@ -1231,24 +1231,40 @@ void HistoryWidget::writeDrafts(Data::Draft **localDraft, Data::Draft **editDraf
_saveDraftTimer.stop();
if (_saveDraftText) {
if (save) {
Local::MessageDraft storedLocalDraft, storedEditDraft;
Storage::MessageDraft storedLocalDraft, storedEditDraft;
if (localDraft) {
if (*localDraft) {
storedLocalDraft = Local::MessageDraft((*localDraft)->msgId, (*localDraft)->textWithTags, (*localDraft)->previewCancelled);
storedLocalDraft = Storage::MessageDraft{
(*localDraft)->msgId,
(*localDraft)->textWithTags,
(*localDraft)->previewCancelled
};
}
} else {
storedLocalDraft = Local::MessageDraft(_replyToId, _field->getTextWithTags(), _previewCancelled);
storedLocalDraft = Storage::MessageDraft{
_replyToId,
_field->getTextWithTags(),
_previewCancelled
};
}
if (editDraft) {
if (*editDraft) {
storedEditDraft = Local::MessageDraft((*editDraft)->msgId, (*editDraft)->textWithTags, (*editDraft)->previewCancelled);
storedEditDraft = Storage::MessageDraft{
(*editDraft)->msgId,
(*editDraft)->textWithTags,
(*editDraft)->previewCancelled
};
}
} else if (_editMsgId) {
storedEditDraft = Local::MessageDraft(_editMsgId, _field->getTextWithTags(), _previewCancelled);
storedEditDraft = Storage::MessageDraft{
_editMsgId,
_field->getTextWithTags(),
_previewCancelled
};
}
Local::writeDrafts(_peer->id, storedLocalDraft, storedEditDraft);
session().local().writeDrafts(_peer->id, storedLocalDraft, storedEditDraft);
if (_migrated) {
Local::writeDrafts(_migrated->peer->id, Local::MessageDraft(), Local::MessageDraft());
session().local().writeDrafts(_migrated->peer->id, {}, {});
}
}
_saveDraftText = false;
@ -1269,9 +1285,9 @@ void HistoryWidget::writeDrafts(Data::Draft **localDraft, Data::Draft **editDraf
} else if (_editMsgId) {
editCursor = MessageCursor(_field);
}
Local::writeDraftCursors(_peer->id, localCursor, editCursor);
session().local().writeDraftCursors(_peer->id, localCursor, editCursor);
if (_migrated) {
Local::writeDraftCursors(_migrated->peer->id, MessageCursor(), MessageCursor());
session().local().writeDraftCursors(_migrated->peer->id, {}, {});
}
}
@ -1869,9 +1885,9 @@ void HistoryWidget::showHistory(
handlePeerUpdate();
Local::readDraftsWithCursors(_history);
session().local().readDraftsWithCursors(_history);
if (_migrated) {
Local::readDraftsWithCursors(_migrated);
session().local().readDraftsWithCursors(_migrated);
_migrated->clearEditDraft();
_history->takeLocalDraft(_migrated);
}
@ -4283,10 +4299,10 @@ void HistoryWidget::onCheckFieldAutocomplete() {
if (autocomplete.query[0] == '#'
&& cRecentWriteHashtags().isEmpty()
&& cRecentSearchHashtags().isEmpty()) {
Local::readRecentHashtagsAndBots();
session().local().readRecentHashtagsAndBots();
} else if (autocomplete.query[0] == '@'
&& cRecentInlineBots().isEmpty()) {
Local::readRecentHashtagsAndBots();
session().local().readRecentHashtagsAndBots();
} else if (autocomplete.query[0] == '/'
&& _peer->isUser()
&& !_peer->asUser()->isBot()) {
@ -5764,7 +5780,7 @@ void HistoryWidget::sendInlineResult(
bots.resize(RecentInlineBotsLimit - 1);
}
bots.push_front(bot);
Local::writeRecentHashtagsAndBots();
session().local().writeRecentHashtagsAndBots();
}
hideSelectorControlsAnimated();
@ -5823,7 +5839,7 @@ bool HistoryWidget::pinnedMsgVisibilityUpdated() {
pinnedId = 0;
} else {
Global::RefHiddenPinnedMessages().remove(_peer->id);
Local::writeUserSettings();
session().local().writeSettings();
}
}
}
@ -6151,7 +6167,7 @@ void HistoryWidget::hidePinnedMessage() {
pinnedId));
} else {
Global::RefHiddenPinnedMessages().insert(_peer->id, pinnedId);
Local::writeUserSettings();
session().local().writeSettings();
if (pinnedMsgVisibilityUpdated()) {
updateControlsGeometry();
update();

View File

@ -32,9 +32,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/file_utilities.h"
#include "main/main_session.h"
#include "data/data_session.h"
#include "data/data_user.h"
#include "data/data_scheduled_messages.h"
#include "storage/storage_media_prepare.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "inline_bots/inline_bot_result.h"
#include "platform/platform_specific.h"
#include "lang/lang_keys.h"
@ -605,7 +606,7 @@ void ScheduledWidget::sendInlineResult(
bots.resize(RecentInlineBotsLimit - 1);
}
bots.push_front(bot);
Local::writeRecentHashtagsAndBots();
bot->session().local().writeRecentHashtagsAndBots();
}
_composeControls->hidePanelsAnimated();

View File

@ -22,7 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "media/player/media_player_instance.h"
#include "history/history_location_manager.h"
#include "history/view/history_view_cursor_state.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "ui/image/image.h"
#include "main/main_session.h"
#include "apiwrap.h"
@ -134,7 +134,7 @@ void DeleteSavedGifClickHandler::onClickImpl() const {
const auto index = _data->owner().stickers().savedGifs().indexOf(_data);
if (index >= 0) {
_data->owner().stickers().savedGifsRef().remove(index);
Local::writeSavedGifs();
_data->session().local().writeSavedGifs();
}
_data->owner().stickers().notifySavedGifsUpdated();
}

View File

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "intro/intro_widget.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "lang/lang_keys.h"
#include "lang/lang_cloud_manager.h"
#include "main/main_account.h"
@ -42,7 +43,7 @@ void PrepareSupportMode(not_null<Main::Session*> session) {
Global::SetSoundNotify(false);
Global::SetFlashBounceNotify(false);
session->settings().autoDownload() = Full::FullDisabled();
Local::writeUserSettings();
session->local().writeSettings();
}
} // namespace
@ -141,7 +142,9 @@ void Step::finish(const MTPUser &user, QImage &&photo) {
const auto account = _account;
const auto weak = base::make_weak(account.get());
account->createSession(user);
Local::writeMtpData();
if (weak) {
account->local().writeMtpData();
}
App::wnd()->controller().setupMain();
// "this" is already deleted here by creating the main widget.

View File

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h"
#include "core/launcher.h"
#include "core/shortcuts.h"
#include "storage/storage_account.h"
#include "storage/serialize_common.h"
#include "storage/localstorage.h"
#include "data/data_session.h"
@ -25,10 +26,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Main {
Account::Account(const QString &dataName) {
Account::Account(const QString &dataName)
: _local(std::make_unique<Storage::Account>(this, dataName))
, _appConfig(std::make_unique<AppConfig>(this)) {
watchProxyChanges();
watchSessionChanges();
_appConfig = std::make_unique<AppConfig>(this);
}
Account::~Account() = default;
@ -128,7 +130,7 @@ void Account::createSession(
if (!serialized.isEmpty()) {
// For now it depends on Auth() which depends on _sessionValue.
Local::readSelf(serialized, streamVersion);
local().readSelf(serialized, streamVersion);
}
}
@ -337,6 +339,10 @@ void Account::startMtp() {
MTP::Instance::Mode::Normal,
std::move(config));
_mtp->setUserPhone(cLoggedPhoneNumber());
_mtp->writeKeysRequests(
) | rpl::start_with_next([=] {
local().writeMtpData();
}, _mtp->lifetime());
_mtpConfig.mainDcId = _mtp->mainDcId();
_mtp->setUpdatesHandler(::rpcDone([=](
@ -376,7 +382,7 @@ void Account::startMtp() {
_storedSettings = nullptr;
if (sessionExists()) {
// Skip all pending self updates so that we won't Local::writeSelf.
// Skip all pending self updates so that we won't local().writeSelf.
Notify::peerUpdatedSendDelayed();
}
@ -439,6 +445,7 @@ void Account::loggedOut() {
session().data().clearLocalStorage();
}
destroySession();
local().reset();
Local::reset();
cSetOtherOnline(0);
@ -450,7 +457,7 @@ void Account::destroyMtpKeys(MTP::AuthKeysList &&keys) {
}
if (_mtpForKeysDestroy) {
_mtpForKeysDestroy->addKeysForDestroy(std::move(keys));
Local::writeMtpData();
local().writeMtpData();
return;
}
auto destroyConfig = MTP::Instance::Config();
@ -462,14 +469,18 @@ void Account::destroyMtpKeys(MTP::AuthKeysList &&keys) {
Core::App().dcOptions(),
MTP::Instance::Mode::KeysDestroyer,
std::move(destroyConfig));
_mtpForKeysDestroy->writeKeysRequests(
) | rpl::start_with_next([=] {
local().writeMtpData();
}, _mtpForKeysDestroy->lifetime());
_mtpForKeysDestroy->allKeysDestroyed(
) | rpl::start_with_next([=] {
LOG(("MTP Info: all keys scheduled for destroy are destroyed."));
crl::on_main(this, [=] {
_mtpForKeysDestroy = nullptr;
Local::writeMtpData();
local().writeMtpData();
});
}, _lifetime);
}, _mtpForKeysDestroy->lifetime());
}
void Account::suggestMainDcId(MTP::DcId mainDcId) {
@ -508,7 +519,7 @@ void Account::resetAuthorizationKeys() {
_mtpValue = nullptr;
_mtp = nullptr;
startMtp();
Local::writeMtpData();
local().writeMtpData();
}
void Account::clearMtp() {

View File

@ -11,6 +11,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mtproto/mtp_instance.h"
#include "base/weak_ptr.h"
namespace Storage {
class Account;
} // namespace Storage
namespace Main {
class Session;
@ -36,9 +40,12 @@ public:
void logOut();
void forcedLogOut();
[[nodiscard]] AppConfig &appConfig() {
[[nodiscard]] AppConfig &appConfig() const {
return *_appConfig;
}
[[nodiscard]] Storage::Account &local() const {
return *_local;
}
[[nodiscard]] bool sessionExists() const;
[[nodiscard]] Session &session();
@ -91,6 +98,8 @@ private:
void loggedOut();
const std::unique_ptr<Storage::Account> _local;
std::unique_ptr<MTP::Instance> _mtp;
rpl::variable<MTP::Instance*> _mtpValue;
std::unique_ptr<MTP::Instance> _mtpForKeysDestroy;

View File

@ -16,8 +16,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/file_download.h"
#include "storage/download_manager_mtproto.h"
#include "storage/file_upload.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "storage/storage_facade.h"
#include "storage/storage_account.h"
#include "data/data_session.h"
#include "data/data_user.h"
#include "window/notifications_manager.h"
@ -45,7 +46,7 @@ Session::Session(
Settings &&settings)
: _account(account)
, _settings(std::move(settings))
, _saveSettingsTimer([=] { Local::writeUserSettings(); })
, _saveSettingsTimer([=] { local().writeSettings(); })
, _api(std::make_unique<ApiWrap>(this))
, _calls(std::make_unique<Calls::Instance>(this))
, _downloader(std::make_unique<Storage::DownloadManagerMtproto>(_api.get()))
@ -82,7 +83,7 @@ Session::Session(
events,
[=](const Notify::PeerUpdate &update) {
if (update.peer == _user) {
Local::writeSelf();
local().writeSelf();
}
}));
@ -112,6 +113,10 @@ Main::Account &Session::account() const {
return *_account;
}
Storage::Account &Session::local() const {
return _account->local();
}
bool Session::Exists() {
return Core::IsAppLaunched()
&& Core::App().activeAccount().sessionExists();
@ -174,7 +179,7 @@ Support::Templates& Session::supportTemplates() const {
void Session::saveSettingsNowIfNeeded() {
if (_saveSettingsTimer.isActive()) {
_saveSettingsTimer.cancel();
Local::writeUserSettings();
local().writeSettings();
}
}

View File

@ -32,6 +32,7 @@ namespace Storage {
class DownloadManagerMtproto;
class Uploader;
class Facade;
class Account;
} // namespace Storage
namespace Window {
@ -73,6 +74,7 @@ public:
[[nodiscard]] static bool Exists();
[[nodiscard]] Main::Account &account() const;
[[nodiscard]] Storage::Account &local() const;
[[nodiscard]] UserId userId() const;
[[nodiscard]] PeerId userPeerId() const;

View File

@ -68,7 +68,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peer_list_controllers.h"
#include "boxes/download_path_box.h"
#include "boxes/connection_box.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "media/audio/media_audio.h"
#include "media/player/media_player_panel.h"
#include "media/player/media_player_widget.h"
@ -1089,7 +1089,9 @@ void MainWidget::closeBothPlayers() {
void MainWidget::createPlayer() {
if (!_player) {
_player.create(this, object_ptr<Media::Player::Widget>(this));
_player.create(
this,
object_ptr<Media::Player::Widget>(this, &session()));
rpl::merge(
_player->heightValue() | rpl::map([] { return true; }),
_player->shownValue()
@ -2507,7 +2509,7 @@ void MainWidget::ensureFirstColumnResizeAreaCreated() {
session().settings().setDialogsWidthRatio(
float64(_dialogsWidth) / width());
}
Local::writeUserSettings();
session().local().writeSettings();
};
createResizeArea(
_firstColumnResizeArea,
@ -2531,7 +2533,7 @@ void MainWidget::ensureThirdColumnResizeAreaCreated() {
session().settings().thirdColumnWidth(),
st::columnMinimalWidthThird,
st::columnMaximalWidthThird));
Local::writeUserSettings();
session().local().writeSettings();
};
createResizeArea(
_thirdColumnResizeArea,
@ -3193,9 +3195,10 @@ void MainWidget::sendPing() {
}
void MainWidget::start() {
session().api().requestNotifySettings(MTP_inputNotifyUsers());
session().api().requestNotifySettings(MTP_inputNotifyChats());
session().api().requestNotifySettings(MTP_inputNotifyBroadcasts());
auto &api = session().api();
api.requestNotifySettings(MTP_inputNotifyUsers());
api.requestNotifySettings(MTP_inputNotifyChats());
api.requestNotifySettings(MTP_inputNotifyBroadcasts());
cSetOtherOnline(0);
session().user()->loadUserpic();
@ -3204,16 +3207,19 @@ void MainWidget::start() {
update();
_started = true;
Local::readInstalledStickers();
Local::readFeaturedStickers();
Local::readRecentStickers();
Local::readFavedStickers();
Local::readSavedGifs();
if (const auto availableAt = Local::ReadExportSettings().availableAt) {
session().data().suggestStartExport(availableAt);
auto &local = session().local();
local.readInstalledStickers();
local.readFeaturedStickers();
local.readRecentStickers();
local.readFavedStickers();
local.readSavedGifs();
auto &data = session().data();
if (const auto availableAt = local.readExportSettings().availableAt) {
data.suggestStartExport(availableAt);
}
session().data().stickers().notifyUpdated();
session().data().stickers().notifySavedGifsUpdated();
auto &stickers = data.stickers();
stickers.notifyUpdated();
stickers.notifySavedGifsUpdated();
_history->start();
@ -3441,7 +3447,7 @@ void MainWidget::incrementSticker(DocumentData *sticker) {
}
if (writeOldRecent) {
Local::writeUserSettings();
session().local().writeSettings();
}
// Remove that sticker from custom stickers, now it is in cloud recent stickers.
@ -3460,10 +3466,10 @@ void MainWidget::incrementSticker(DocumentData *sticker) {
}
if (writeInstalledStickers) {
Local::writeInstalledStickers();
session().local().writeInstalledStickers();
}
if (writeRecentStickers) {
Local::writeRecentStickers();
session().local().writeRecentStickers();
}
_controller->tabbedSelector()->refreshStickers();
}
@ -3623,30 +3629,32 @@ void MainWidget::applyCloudDraft(History *history) {
}
void MainWidget::writeDrafts(History *history) {
Local::MessageDraft storedLocalDraft, storedEditDraft;
Storage::MessageDraft storedLocalDraft, storedEditDraft;
MessageCursor localCursor, editCursor;
if (const auto localDraft = history->localDraft()) {
if (session().supportMode()
|| !Data::draftsAreEqual(localDraft, history->cloudDraft())) {
storedLocalDraft = Local::MessageDraft(
storedLocalDraft = Storage::MessageDraft{
localDraft->msgId,
localDraft->textWithTags,
localDraft->previewCancelled);
localDraft->previewCancelled
};
localCursor = localDraft->cursor;
}
}
if (const auto editDraft = history->editDraft()) {
storedEditDraft = Local::MessageDraft(
storedEditDraft = Storage::MessageDraft{
editDraft->msgId,
editDraft->textWithTags,
editDraft->previewCancelled);
editDraft->previewCancelled
};
editCursor = editDraft->cursor;
}
Local::writeDrafts(
session().local().writeDrafts(
history->peer->id,
storedLocalDraft,
storedEditDraft);
Local::writeDraftCursors(history->peer->id, localCursor, editCursor);
session().local().writeDraftCursors(history->peer->id, localCursor, editCursor);
}
void MainWidget::checkIdleFinish() {
@ -4543,7 +4551,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
session().api().updateStickers();
} else {
session().data().stickers().setsOrderRef() = std::move(result);
Local::writeInstalledStickers();
session().local().writeInstalledStickers();
session().data().stickers().notifyUpdated();
}
}

View File

@ -33,6 +33,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/add_contact_box.h"
#include "boxes/connection_box.h"
#include "observer_peer.h"
#include "storage/storage_account.h"
#include "storage/localstorage.h"
#include "apiwrap.h"
#include "settings/settings_intro.h"
@ -791,7 +792,7 @@ void MainWindow::toggleDisplayNotifyFromTray() {
Global::SetRestoreFlashBounceNotifyFromTray(false);
}
}
Local::writeUserSettings();
account().local().writeSettings();
using Change = Window::Notifications::ChangeType;
auto &changes = account().session().notifications().settingsChanged();
changes.notify(Change::DesktopEnabled);
@ -850,13 +851,6 @@ MainWindow::TempDirState MainWindow::tempDirState() {
return QDir(cTempDir()).exists() ? TempDirExists : TempDirEmpty;
}
MainWindow::TempDirState MainWindow::localStorageState() {
if (_clearManager && _clearManager->hasTask(Local::ClearManagerStorage)) {
return TempDirRemoving;
}
return TempDirEmpty;
}
void MainWindow::tempDirDelete(int task) {
if (_clearManager) {
if (_clearManager->addTask(task)) {

View File

@ -79,7 +79,6 @@ public:
TempDirEmpty,
};
TempDirState tempDirState();
TempDirState localStorageState();
void tempDirDelete(int task);
void sendPaths();

View File

@ -25,7 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_media_player.h"
#include "styles/style_media_view.h"
#include "history/history_item.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "layout.h"
#include "main/main_session.h"
#include "facades.h"
@ -80,7 +80,9 @@ QPoint Widget::PlayButton::prepareRippleStartPosition() const {
return QPoint(mapFromGlobal(QCursor::pos()) - st::mediaPlayerButton.rippleAreaPosition);
}
Widget::Widget(QWidget *parent) : RpWidget(parent)
Widget::Widget(QWidget *parent, not_null<Main::Session*> session)
: RpWidget(parent)
, _session(session)
, _nameLabel(this, st::mediaPlayerName)
, _timeLabel(this, st::mediaPlayerTime)
, _playPause(this)
@ -141,7 +143,7 @@ Widget::Widget(QWidget *parent) : RpWidget(parent)
Global::SetVoiceMsgPlaybackDoubled(doubled);
instance()->updateVoicePlaybackSpeed();
updatePlaybackSpeedIcon();
Local::writeUserSettings();
_session->local().writeSettings();
});
subscribe(instance()->repeatChangedNotifier(), [this](AudioMsgId::Type type) {

View File

@ -26,6 +26,10 @@ class PlaybackProgress;
} // namespace Clip
} // namespace Media
namespace Main {
class Session;
} // namespace Main
namespace Media {
namespace Player {
@ -35,7 +39,7 @@ struct TrackState;
class Widget : public Ui::RpWidget, private base::Subscriber {
public:
Widget(QWidget *parent);
Widget(QWidget *parent, not_null<Main::Session*> session);
void setCloseCallback(Fn<void()> callback);
void stopAndClose();
@ -85,6 +89,8 @@ private:
void updateTimeText(const TrackState &state);
void updateTimeLabel();
const not_null<Main::Session*> _session;
crl::time _seekPositionMs = -1;
crl::time _lastDurationMs = 0;
QString _time;

View File

@ -64,6 +64,8 @@ public:
void setMainDcId(DcId mainDcId);
[[nodiscard]] DcId mainDcId() const;
[[nodiscard]] rpl::producer<> writeKeysRequests() const;
void dcPersistentKeyChanged(DcId dcId, const AuthKeyPtr &persistentKey);
void dcTemporaryKeyChanged(DcId dcId);
[[nodiscard]] rpl::producer<DcId> dcTemporaryKeyChanged() const;
@ -159,6 +161,8 @@ public:
void prepareToDestroy();
[[nodiscard]] rpl::lifetime &lifetime();
private:
bool hasAuthorization();
void importDone(const MTPauth_Authorization &result, mtpRequestId requestId);
@ -224,6 +228,7 @@ private:
base::flat_map<DcId, AuthKeyPtr> _keysForWrite;
base::flat_map<ShiftedDcId, mtpRequestId> _logoutGuestRequestIds;
rpl::event_stream<> _writeKeysRequests;
rpl::event_stream<> _allKeysDestroyed;
// holds dcWithShift for request to this dc or -dc for request to main dc
@ -253,6 +258,8 @@ private:
base::Timer _checkDelayedTimer;
rpl::lifetime _lifetime;
};
Instance::Private::Private(
@ -404,7 +411,7 @@ void Instance::Private::setMainDcId(DcId mainDcId) {
if (oldMainDcId != _mainDcId) {
killSession(oldMainDcId);
}
Local::writeMtpData();
_writeKeysRequests.fire({});
}
DcId Instance::Private::mainDcId() const {
@ -724,8 +731,9 @@ void Instance::Private::dcPersistentKeyChanged(
} else {
_keysForWrite.emplace(dcId, persistentKey);
}
DEBUG_LOG(("AuthKey Info: writing auth keys, called by dc %1").arg(dcId));
Local::writeMtpData();
DEBUG_LOG(("AuthKey Info: writing auth keys, called by dc %1"
).arg(dcId));
_writeKeysRequests.fire({});
}
void Instance::Private::dcTemporaryKeyChanged(DcId dcId) {
@ -769,6 +777,10 @@ rpl::producer<> Instance::Private::allKeysDestroyed() const {
return _allKeysDestroyed.events();
}
rpl::producer<> Instance::Private::writeKeysRequests() const {
return _writeKeysRequests.events();
}
not_null<DcOptions*> Instance::Private::dcOptions() {
return _dcOptions;
}
@ -1419,6 +1431,10 @@ not_null<Session*> Instance::Private::getSession(
return startSession(shiftedDcId);
}
rpl::lifetime &Instance::Private::lifetime() {
return _lifetime;
}
Session *Instance::Private::findSession(ShiftedDcId shiftedDcId) {
const auto i = _sessions.find(shiftedDcId);
return (i != _sessions.end()) ? i->second.get() : nullptr;
@ -1666,6 +1682,10 @@ QString Instance::langPackName() const {
return Lang::Current().langPackName();
}
rpl::producer<> Instance::writeKeysRequests() const {
return _private->writeKeysRequests();
}
rpl::producer<> Instance::allKeysDestroyed() const {
return _private->allKeysDestroyed();
}
@ -1862,6 +1882,10 @@ void Instance::sendAnything(ShiftedDcId shiftedDcId, crl::time msCanWait) {
_private->getSession(shiftedDcId)->sendAnything(msCanWait);
}
rpl::lifetime &Instance::lifetime() {
return _private->lifetime();
}
Instance::~Instance() {
_private->prepareToDestroy();
}

View File

@ -60,6 +60,7 @@ public:
[[nodiscard]] QString cloudLangCode() const;
[[nodiscard]] QString langPackName() const;
[[nodiscard]] rpl::producer<> writeKeysRequests() const;
[[nodiscard]] rpl::producer<> allKeysDestroyed() const;
// Thread-safe.
@ -195,6 +196,8 @@ public:
afterRequestId);
}
[[nodiscard]] rpl::lifetime &lifetime();
signals:
void proxyDomainResolved(
QString host,

View File

@ -207,7 +207,7 @@ bool GetNative(
QString path = dialog.directory().absolutePath();
if (path != cDialogLastPath()) {
cSetDialogLastPath(path);
Local::writeUserSettings();
Local::writeSettings();
}
if (res == QDialog::Accepted) {

View File

@ -417,7 +417,7 @@ bool Get(
const auto path = dialog.directory().absolutePath();
if (path != cDialogLastPath()) {
cSetDialogLastPath(path);
Local::writeUserSettings();
Local::writeSettings();
}
}

View File

@ -17,8 +17,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/single_choice_box.h"
#include "boxes/confirm_box.h"
#include "platform/platform_specific.h"
#include "main/main_session.h"
#include "lang/lang_keys.h"
#include "storage/localstorage.h"
#include "layout.h"
#include "styles/style_settings.h"
#include "ui/widgets/continuous_sliders.h"
@ -43,13 +43,14 @@ namespace Settings {
Calls::Calls(
QWidget *parent,
not_null<Window::SessionController*> controller)
: Section(parent) {
setupContent(controller);
: Section(parent)
, _controller(controller) {
setupContent();
}
Calls::~Calls() {
if (_needWriteSettings) {
Local::writeUserSettings();
_controller->session().saveSettingsDelayed();
}
}
@ -60,7 +61,7 @@ void Calls::sectionSaveChanges(FnMut<void()> done) {
done();
}
void Calls::setupContent(not_null<Window::SessionController*> controller) {
void Calls::setupContent() {
using VoIP = tgvoip::VoIPController;
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
@ -129,8 +130,8 @@ void Calls::setupContent(not_null<Window::SessionController*> controller) {
? devices[option - 1].id
: "default";
Global::SetCallOutputDeviceID(QString::fromStdString(deviceId));
Local::writeUserSettings();
if (const auto call = controller->session().calls().currentCall()) {
_controller->session().saveSettingsDelayed();
if (const auto call = _controller->session().calls().currentCall()) {
call->setCurrentAudioDevice(false, deviceId);
}
});
@ -160,7 +161,7 @@ void Calls::setupContent(not_null<Window::SessionController*> controller) {
_needWriteSettings = true;
updateOutputLabel(value);
Global::SetCallOutputVolume(value);
if (const auto call = controller->session().calls().currentCall()) {
if (const auto call = _controller->session().calls().currentCall()) {
call->setAudioVolume(false, value / 100.0f);
}
};
@ -204,11 +205,11 @@ void Calls::setupContent(not_null<Window::SessionController*> controller) {
? devices[option - 1].id
: "default";
Global::SetCallInputDeviceID(QString::fromStdString(deviceId));
Local::writeUserSettings();
_controller->session().saveSettingsDelayed();
if (_micTester) {
stopTestingMicrophone();
}
if (const auto call = controller->session().calls().currentCall()) {
if (const auto call = _controller->session().calls().currentCall()) {
call->setCurrentAudioDevice(true, deviceId);
}
});
@ -238,7 +239,7 @@ void Calls::setupContent(not_null<Window::SessionController*> controller) {
_needWriteSettings = true;
updateInputLabel(value);
Global::SetCallInputVolume(value);
if (const auto call = controller->session().calls().currentCall()) {
if (const auto call = _controller->session().calls().currentCall()) {
call->setAudioVolume(true, value / 100.0f);
}
};
@ -292,8 +293,8 @@ void Calls::setupContent(not_null<Window::SessionController*> controller) {
return (enabled != Global::CallAudioDuckingEnabled());
}) | rpl::start_with_next([=](bool enabled) {
Global::SetCallAudioDuckingEnabled(enabled);
Local::writeUserSettings();
if (const auto call = controller->session().calls().currentCall()) {
_controller->session().saveSettingsDelayed();
if (const auto call = _controller->session().calls().currentCall()) {
call->setAudioDuckingEnabled(enabled);
}
}, content->lifetime());

View File

@ -32,11 +32,12 @@ public:
void sectionSaveChanges(FnMut<void()> done) override;
private:
void setupContent(not_null<Window::SessionController*> controller);
void setupContent();
void requestPermissionAndStartTestingMicrophone();
void startTestingMicrophone();
void stopTestingMicrophone();
const not_null<Window::SessionController*> _controller;
rpl::event_stream<QString> _outputNameStream;
rpl::event_stream<QString> _inputNameStream;
rpl::event_stream<QString> _micTestTextStream;

View File

@ -791,7 +791,7 @@ void SetupMessages(
if (App::main()) {
App::main()->ctrlEnterSubmitUpdated();
}
Local::writeUserSettings();
controller->session().saveSettingsDelayed();
});
AddSkip(inner, st::settingsCheckboxesSkip);
@ -863,8 +863,8 @@ void SetupDataStorage(
std::move(pathtext),
st::settingsButton,
tr::lng_download_path());
path->entity()->addClickHandler([] {
Ui::show(Box<DownloadPathBox>());
path->entity()->addClickHandler([=] {
Ui::show(Box<DownloadPathBox>(controller));
});
path->toggleOn(ask->toggledValue() | rpl::map(!_1));
#endif // OS_WIN_STORE
@ -874,7 +874,7 @@ void SetupDataStorage(
return (checked != Global::AskDownloadPath());
}) | rpl::start_with_next([=](bool checked) {
Global::SetAskDownloadPath(checked);
Local::writeUserSettings();
controller->session().saveSettingsDelayed();
#ifndef OS_WIN_STORE
showpath->fire_copy(!checked);
@ -979,10 +979,10 @@ void SetupChatBackground(
}));
adaptive->entity()->checkedChanges(
) | rpl::start_with_next([](bool checked) {
) | rpl::start_with_next([=](bool checked) {
Global::SetAdaptiveForWide(checked);
Adaptive::Changed().notify();
Local::writeUserSettings();
controller->session().saveSettingsDelayed();
}, adaptive->lifetime());
}
@ -1285,7 +1285,7 @@ void SetupSupportSwitchSettings(
add(SwitchType::Previous, "Send and switch to previous");
group->setChangedCallback([=](SwitchType value) {
controller->session().settings().setSupportSwitch(value);
Local::writeUserSettings();
controller->session().saveSettingsDelayed();
});
}
@ -1325,7 +1325,7 @@ void SetupSupportChatsLimitSlice(
group->setChangedCallback([=](int days) {
controller->session().settings().setSupportChatsTimeSlice(
days * kDayDuration);
Local::writeUserSettings();
controller->session().saveSettingsDelayed();
});
}
@ -1362,7 +1362,7 @@ void SetupSupport(
) | rpl::start_with_next([=](bool checked) {
controller->session().settings().setSupportTemplatesAutocomplete(
checked);
Local::writeUserSettings();
controller->session().saveSettingsDelayed();
}, inner->lifetime());
AddSkip(inner, st::settingsCheckboxesSkip);

View File

@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwidget.h"
#include "mainwindow.h"
#include "data/data_session.h"
#include "storage/localstorage.h"
#include "main/main_session.h"
#include "boxes/confirm_box.h"
#include "lang/lang_cloud_manager.h"
#include "lang/lang_instance.h"
@ -76,10 +76,13 @@ auto GenerateCodes() {
Unexpected("Crashed in Settings!");
});
codes.emplace(qsl("moderate"), [](SessionController *window) {
if (!window) {
return;
}
auto text = Global::ModerateModeEnabled() ? qsl("Disable moderate mode?") : qsl("Enable moderate mode?");
Ui::show(Box<ConfirmBox>(text, [] {
Ui::show(Box<ConfirmBox>(text, [=] {
Global::SetModerateModeEnabled(!Global::ModerateModeEnabled());
Local::writeUserSettings();
window->session().saveSettingsDelayed();
Ui::hideLayer();
}));
});
@ -96,10 +99,13 @@ auto GenerateCodes() {
});
});
codes.emplace(qsl("videoplayer"), [](SessionController *window) {
if (!window) {
return;
}
auto text = cUseExternalVideoPlayer() ? qsl("Use internal video player?") : qsl("Use external video player?");
Ui::show(Box<ConfirmBox>(text, [] {
Ui::show(Box<ConfirmBox>(text, [=] {
cSetUseExternalVideoPlayer(!cUseExternalVideoPlayer());
Local::writeUserSettings();
window->session().saveSettingsDelayed();
Ui::hideLayer();
}));
});
@ -168,7 +174,7 @@ auto GenerateCodes() {
window->session().settings().setSoundOverride(
key,
result.paths.front());
Local::writeUserSettings();
window->session().saveSettingsDelayed();
}
}
}));
@ -177,7 +183,7 @@ auto GenerateCodes() {
codes.emplace(qsl("sounds_reset"), [](SessionController *window) {
if (window) {
window->session().settings().clearSoundOverrides();
Local::writeUserSettings();
window->session().saveSettingsDelayed();
Ui::show(Box<InformBox>("All sound overrides were reset."));
}
});

View File

@ -15,7 +15,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/buttons.h"
#include "ui/widgets/discrete_sliders.h"
#include "lang/lang_keys.h"
#include "storage/localstorage.h"
#include "window/notifications_manager.h"
#include "window/window_session_controller.h"
#include "platform/platform_notifications_manager.h"
@ -187,7 +186,7 @@ void NotificationsCount::setCount(int count) {
Global::SetNotificationsCount(count);
_controller->session().notifications().settingsChanged().notify(
ChangeType::MaxCount);
Local::writeUserSettings();
_controller->session().saveSettingsDelayed();
}
}
@ -414,7 +413,7 @@ void NotificationsCount::mouseReleaseEvent(QMouseEvent *e) {
Global::SetNotificationsCorner(_chosenCorner);
_controller->session().notifications().settingsChanged().notify(
ChangeType::Corner);
Local::writeUserSettings();
_controller->session().saveSettingsDelayed();
}
}
}
@ -679,7 +678,7 @@ void SetupNotificationsContent(
using Change = Window::Notifications::ChangeType;
const auto changed = [=](Change change) {
Local::writeUserSettings();
session->saveSettingsDelayed();
session->notifications().settingsChanged().notify(change);
};
desktop->checkedChanges(
@ -776,8 +775,7 @@ void SetupNotificationsContent(
return (checked != Global::NativeNotifications());
}) | rpl::start_with_next([=](bool checked) {
Global::SetNativeNotifications(checked);
Local::writeUserSettings();
session->saveSettingsDelayed();
session->notifications().createManager();
if (advancedSlide) {

View File

@ -13,7 +13,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "observer_peer.h"
#include "mainwidget.h"
#include "main/main_session.h"
#include "storage/localstorage.h"
#include "data/data_user.h"
#include "data/data_session.h"
#include "history/admin_log/history_admin_log_item.h"
@ -515,7 +514,7 @@ void LastSeenPrivacyController::confirmSave(
}
saveCallback();
session->settings().setLastSeenWarningSeen(true);
Local::writeUserSettings();
session->saveSettingsDelayed();
};
auto box = Box<ConfirmBox>(
tr::lng_edit_privacy_lastseen_warning(tr::now),

View File

@ -0,0 +1,477 @@
/*
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 "storage/details/storage_file_utilities.h"
#include "mtproto/mtproto_auth_key.h"
#include "base/platform/base_platform_file_utilities.h"
#include "base/openssl_help.h"
#include <QtCore/QtEndian>
#include <QtCore/QSaveFile>
namespace Storage {
namespace details {
namespace {
constexpr char TdfMagic[] = { 'T', 'D', 'F', '$' };
constexpr auto TdfMagicLen = int(sizeof(TdfMagic));
} // namespace
QString ToFilePart(FileKey val) {
QString result;
result.reserve(0x10);
for (int32 i = 0; i < 0x10; ++i) {
uchar v = (val & 0x0F);
result.push_back((v < 0x0A) ? ('0' + v) : ('A' + (v - 0x0A)));
val >>= 4;
}
return result;
}
bool KeyAlreadyUsed(QString &name) {
name += '0';
if (QFileInfo(name).exists()) {
return true;
}
name[name.size() - 1] = '1';
if (QFileInfo(name).exists()) {
return true;
}
name[name.size() - 1] = 's';
if (QFileInfo(name).exists()) {
return true;
}
return false;
}
FileKey GenerateKey(const QString &basePath) {
FileKey result;
QString path;
path.reserve(basePath.size() + 0x11);
path += basePath;
do {
result = rand_value<FileKey>();
path.resize(basePath.size());
path += ToFilePart(result);
} while (!result || KeyAlreadyUsed(path));
return result;
}
void ClearKey(const FileKey &key, const QString &basePath) {
QString name;
name.reserve(basePath.size() + 0x11);
name.append(basePath).append(ToFilePart(key)).append('0');
QFile::remove(name);
name[name.size() - 1] = '1';
QFile::remove(name);
name[name.size() - 1] = 's';
QFile::remove(name);
}
bool CheckStreamStatus(QDataStream &stream) {
if (stream.status() != QDataStream::Ok) {
LOG(("Bad data stream status: %1").arg(stream.status()));
return false;
}
return true;
}
MTP::AuthKeyPtr CreateLocalKey(
const QByteArray &passcode,
const QByteArray &salt) {
auto key = MTP::AuthKey::Data{ { gsl::byte{} } };
const auto iterationsCount = passcode.isEmpty()
? LocalEncryptNoPwdIterCount // Don't slow down for no password.
: LocalEncryptIterCount;
PKCS5_PBKDF2_HMAC_SHA1(
passcode.constData(),
passcode.size(),
(uchar*)salt.data(),
salt.size(),
iterationsCount,
key.size(),
(uchar*)key.data());
return std::make_shared<MTP::AuthKey>(key);
}
FileReadDescriptor::~FileReadDescriptor() {
if (version) {
stream.setDevice(nullptr);
if (buffer.isOpen()) {
buffer.close();
}
buffer.setBuffer(nullptr);
}
}
EncryptedDescriptor::EncryptedDescriptor() {
}
EncryptedDescriptor::EncryptedDescriptor(uint32 size) {
uint32 fullSize = sizeof(uint32) + size;
if (fullSize & 0x0F) fullSize += 0x10 - (fullSize & 0x0F);
data.reserve(fullSize);
data.resize(sizeof(uint32));
buffer.setBuffer(&data);
buffer.open(QIODevice::WriteOnly);
buffer.seek(sizeof(uint32));
stream.setDevice(&buffer);
stream.setVersion(QDataStream::Qt_5_1);
}
EncryptedDescriptor::~EncryptedDescriptor() {
finish();
}
void EncryptedDescriptor::finish() {
if (stream.device()) stream.setDevice(nullptr);
if (buffer.isOpen()) buffer.close();
buffer.setBuffer(nullptr);
}
FileWriteDescriptor::FileWriteDescriptor(
const FileKey &key,
const QString &basePath)
: FileWriteDescriptor(ToFilePart(key), basePath) {
}
FileWriteDescriptor::FileWriteDescriptor(
const QString &name,
const QString &basePath)
: _basePath(basePath) {
init(name);
}
FileWriteDescriptor::~FileWriteDescriptor() {
finish();
}
QString FileWriteDescriptor::path(char postfix) const {
return _base + postfix;
}
template <typename File>
bool FileWriteDescriptor::open(File &file, char postfix) {
const auto name = path(postfix);
file.setFileName(name);
if (!writeHeader(file)) {
LOG(("Storage Error: Could not open '%1' for writing.").arg(name));
return false;
}
return true;
}
bool FileWriteDescriptor::writeHeader(QFileDevice &file) {
if (!file.open(QIODevice::WriteOnly)) {
return false;
}
file.write(TdfMagic, TdfMagicLen);
const auto version = qint32(AppVersion);
file.write((const char*)&version, sizeof(version));
return true;
}
void FileWriteDescriptor::writeFooter(QFileDevice &file) {
file.write((const char*)_md5.result(), 0x10);
}
void FileWriteDescriptor::init(const QString &name) {
_base = _basePath + name;
_buffer.setBuffer(&_safeData);
const auto opened = _buffer.open(QIODevice::WriteOnly);
Assert(opened);
_stream.setDevice(&_buffer);
}
void FileWriteDescriptor::writeData(const QByteArray &data) {
if (!_stream.device()) {
return;
}
_stream << data;
quint32 len = data.isNull() ? 0xffffffff : data.size();
if (QSysInfo::ByteOrder != QSysInfo::BigEndian) {
len = qbswap(len);
}
_md5.feed(&len, sizeof(len));
_md5.feed(data.constData(), data.size());
_fullSize += sizeof(len) + data.size();
}
void FileWriteDescriptor::writeEncrypted(
EncryptedDescriptor &data,
const MTP::AuthKeyPtr &key) {
writeData(PrepareEncrypted(data, key));
}
void FileWriteDescriptor::finish() {
if (!_stream.device()) {
return;
}
_stream.setDevice(nullptr);
_md5.feed(&_fullSize, sizeof(_fullSize));
qint32 version = AppVersion;
_md5.feed(&version, sizeof(version));
_md5.feed(TdfMagic, TdfMagicLen);
_buffer.close();
const auto safe = path('s');
const auto simple = path('0');
const auto backup = path('1');
QSaveFile save;
if (open(save, 's')) {
save.write(_safeData);
writeFooter(save);
if (save.commit()) {
QFile::remove(simple);
QFile::remove(backup);
return;
}
LOG(("Storage Error: Could not commit '%1'.").arg(safe));
}
QFile plain;
if (open(plain, '0')) {
plain.write(_safeData);
writeFooter(plain);
base::Platform::FlushFileData(plain);
plain.close();
QFile::remove(backup);
if (base::Platform::RenameWithOverwrite(simple, safe)) {
return;
}
QFile::remove(safe);
LOG(("Storage Error: Could not rename '%1' to '%2', removing."
).arg(simple
).arg(safe));
}
}
[[nodiscard]] QByteArray PrepareEncrypted(
EncryptedDescriptor &data,
const MTP::AuthKeyPtr &key) {
data.finish();
QByteArray &toEncrypt(data.data);
// prepare for encryption
uint32 size = toEncrypt.size(), fullSize = size;
if (fullSize & 0x0F) {
fullSize += 0x10 - (fullSize & 0x0F);
toEncrypt.resize(fullSize);
memset_rand(toEncrypt.data() + size, fullSize - size);
}
*(uint32*)toEncrypt.data() = size;
QByteArray encrypted(0x10 + fullSize, Qt::Uninitialized); // 128bit of sha1 - key128, sizeof(data), data
hashSha1(toEncrypt.constData(), toEncrypt.size(), encrypted.data());
MTP::aesEncryptLocal(toEncrypt.constData(), encrypted.data() + 0x10, fullSize, key, encrypted.constData());
return encrypted;
}
bool ReadFile(
FileReadDescriptor &result,
const QString &name,
const QString &basePath) {
const auto base = basePath + name;
// detect order of read attempts
QString toTry[2];
const auto modern = base + 's';
if (QFileInfo(modern).exists()) {
toTry[0] = modern;
} else {
// Legacy way.
toTry[0] = base + '0';
QFileInfo toTry0(toTry[0]);
if (toTry0.exists()) {
toTry[1] = basePath + name + '1';
QFileInfo toTry1(toTry[1]);
if (toTry1.exists()) {
QDateTime mod0 = toTry0.lastModified();
QDateTime mod1 = toTry1.lastModified();
if (mod0 < mod1) {
qSwap(toTry[0], toTry[1]);
}
} else {
toTry[1] = QString();
}
} else {
toTry[0][toTry[0].size() - 1] = '1';
}
}
for (int32 i = 0; i < 2; ++i) {
QString fname(toTry[i]);
if (fname.isEmpty()) break;
QFile f(fname);
if (!f.open(QIODevice::ReadOnly)) {
DEBUG_LOG(("App Info: failed to open '%1' for reading"
).arg(name));
continue;
}
// check magic
char magic[TdfMagicLen];
if (f.read(magic, TdfMagicLen) != TdfMagicLen) {
DEBUG_LOG(("App Info: failed to read magic from '%1'"
).arg(name));
continue;
}
if (memcmp(magic, TdfMagic, TdfMagicLen)) {
DEBUG_LOG(("App Info: bad magic %1 in '%2'"
).arg(Logs::mb(magic, TdfMagicLen).str()
).arg(name));
continue;
}
// read app version
qint32 version;
if (f.read((char*)&version, sizeof(version)) != sizeof(version)) {
DEBUG_LOG(("App Info: failed to read version from '%1'"
).arg(name));
continue;
}
if (version > AppVersion) {
DEBUG_LOG(("App Info: version too big %1 for '%2', my version %3"
).arg(version
).arg(name
).arg(AppVersion));
continue;
}
// read data
QByteArray bytes = f.read(f.size());
int32 dataSize = bytes.size() - 16;
if (dataSize < 0) {
DEBUG_LOG(("App Info: bad file '%1', could not read sign part"
).arg(name));
continue;
}
// check signature
HashMd5 md5;
md5.feed(bytes.constData(), dataSize);
md5.feed(&dataSize, sizeof(dataSize));
md5.feed(&version, sizeof(version));
md5.feed(magic, TdfMagicLen);
if (memcmp(md5.result(), bytes.constData() + dataSize, 16)) {
DEBUG_LOG(("App Info: bad file '%1', signature did not match"
).arg(name));
continue;
}
bytes.resize(dataSize);
result.data = bytes;
bytes = QByteArray();
result.version = version;
result.buffer.setBuffer(&result.data);
result.buffer.open(QIODevice::ReadOnly);
result.stream.setDevice(&result.buffer);
result.stream.setVersion(QDataStream::Qt_5_1);
if ((i == 0 && !toTry[1].isEmpty()) || i == 1) {
QFile::remove(toTry[1 - i]);
}
return true;
}
return false;
}
bool DecryptLocal(
EncryptedDescriptor &result,
const QByteArray &encrypted,
const MTP::AuthKeyPtr &key) {
if (encrypted.size() <= 16 || (encrypted.size() & 0x0F)) {
LOG(("App Error: bad encrypted part size: %1").arg(encrypted.size()));
return false;
}
uint32 fullLen = encrypted.size() - 16;
QByteArray decrypted;
decrypted.resize(fullLen);
const char *encryptedKey = encrypted.constData(), *encryptedData = encrypted.constData() + 16;
aesDecryptLocal(encryptedData, decrypted.data(), fullLen, key, encryptedKey);
uchar sha1Buffer[20];
if (memcmp(hashSha1(decrypted.constData(), decrypted.size(), sha1Buffer), encryptedKey, 16)) {
LOG(("App Info: bad decrypt key, data not decrypted - incorrect password?"));
return false;
}
uint32 dataLen = *(const uint32*)decrypted.constData();
if (dataLen > uint32(decrypted.size()) || dataLen <= fullLen - 16 || dataLen < sizeof(uint32)) {
LOG(("App Error: bad decrypted part size: %1, fullLen: %2, decrypted size: %3").arg(dataLen).arg(fullLen).arg(decrypted.size()));
return false;
}
decrypted.resize(dataLen);
result.data = decrypted;
decrypted = QByteArray();
result.buffer.setBuffer(&result.data);
result.buffer.open(QIODevice::ReadOnly);
result.buffer.seek(sizeof(uint32)); // skip len
result.stream.setDevice(&result.buffer);
result.stream.setVersion(QDataStream::Qt_5_1);
return true;
}
bool ReadEncryptedFile(
FileReadDescriptor &result,
const QString &name,
const QString &basePath,
const MTP::AuthKeyPtr &key) {
if (!ReadFile(result, name, basePath)) {
return false;
}
QByteArray encrypted;
result.stream >> encrypted;
EncryptedDescriptor data;
if (!DecryptLocal(data, encrypted, key)) {
result.stream.setDevice(nullptr);
if (result.buffer.isOpen()) result.buffer.close();
result.buffer.setBuffer(nullptr);
result.data = QByteArray();
result.version = 0;
return false;
}
result.stream.setDevice(0);
if (result.buffer.isOpen()) {
result.buffer.close();
}
result.buffer.setBuffer(0);
result.data = data.data;
result.buffer.setBuffer(&result.data);
result.buffer.open(QIODevice::ReadOnly);
result.buffer.seek(data.buffer.pos());
result.stream.setDevice(&result.buffer);
result.stream.setVersion(QDataStream::Qt_5_1);
return true;
}
bool ReadEncryptedFile(
FileReadDescriptor &result,
const FileKey &fkey,
const QString &basePath,
const MTP::AuthKeyPtr &key) {
return ReadEncryptedFile(result, ToFilePart(fkey), basePath, key);
}
} // namespace details
} // namespace Storage

View File

@ -0,0 +1,109 @@
/*
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 "storage/storage_account.h"
#include <QtCore/QBuffer>
namespace Storage {
namespace details {
[[nodiscard]] QString ToFilePart(FileKey val);
[[nodiscard]] bool KeyAlreadyUsed(QString &name);
[[nodiscard]] FileKey GenerateKey(const QString &basePath);
void ClearKey(const FileKey &key, const QString &basePath);
[[nodiscard]] bool CheckStreamStatus(QDataStream &stream);
[[nodiscard]] MTP::AuthKeyPtr CreateLocalKey(
const QByteArray &passcode,
const QByteArray &salt);
struct FileReadDescriptor final {
~FileReadDescriptor();
int32 version = 0;
QByteArray data;
QBuffer buffer;
QDataStream stream;
};
struct EncryptedDescriptor final {
EncryptedDescriptor();
explicit EncryptedDescriptor(uint32 size);
~EncryptedDescriptor();
void finish();
QByteArray data;
QBuffer buffer;
QDataStream stream;
};
[[nodiscard]] QByteArray PrepareEncrypted(
EncryptedDescriptor &data,
const MTP::AuthKeyPtr &key);
class FileWriteDescriptor final {
public:
FileWriteDescriptor(
const FileKey &key,
const QString &basePath);
FileWriteDescriptor(
const QString &name,
const QString &basePath);
~FileWriteDescriptor();
void writeData(const QByteArray &data);
void writeEncrypted(
EncryptedDescriptor &data,
const MTP::AuthKeyPtr &key);
private:
void init(const QString &name);
[[nodiscard]] QString path(char postfix) const;
template <typename File>
[[nodiscard]] bool open(File &file, char postfix);
[[nodiscard]] bool writeHeader(QFileDevice &file);
void writeFooter(QFileDevice &file);
void finish();
const QString _basePath;
QBuffer _buffer;
QDataStream _stream;
QByteArray _safeData;
QString _base;
HashMd5 _md5;
int _fullSize = 0;
};
bool ReadFile(
FileReadDescriptor &result,
const QString &name,
const QString &basePath);
bool DecryptLocal(
EncryptedDescriptor &result,
const QByteArray &encrypted,
const MTP::AuthKeyPtr &key);
bool ReadEncryptedFile(
FileReadDescriptor &result,
const QString &name,
const QString &basePath,
const MTP::AuthKeyPtr &key);
bool ReadEncryptedFile(
FileReadDescriptor &result,
const FileKey &fkey,
const QString &basePath,
const MTP::AuthKeyPtr &key);
} // namespace details
} // namespace Storage

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,161 @@
/*
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 "mtproto/dc_options.h"
#include "main/main_settings.h"
#include "storage/storage_account.h"
namespace Storage {
namespace details {
struct ReadSettingsContext {
[[nodiscard]] Main::Settings &sessionSettings() {
if (!sessionSettingsStorage) {
sessionSettingsStorage = std::make_unique<Main::Settings>();
}
return *sessionSettingsStorage;
}
// This field is read in ReadSetting.
bool hasCustomDayBackground = false;
// Those fields are written in ReadSetting.
MTP::DcOptions dcOptions;
qint64 cacheTotalSizeLimit = 0;
qint32 cacheTotalTimeLimit = 0;
qint64 cacheBigFileTotalSizeLimit = 0;
qint32 cacheBigFileTotalTimeLimit = 0;
std::unique_ptr<Main::Settings> sessionSettingsStorage;
FileKey themeKeyLegacy = 0;
FileKey themeKeyDay = 0;
FileKey themeKeyNight = 0;
FileKey langPackKey = 0;
FileKey languagesKey = 0;
QByteArray callSettings;
};
[[nodiscard]] bool ReadSetting(
quint32 blockId,
QDataStream &stream,
int version,
ReadSettingsContext &context);
enum {
dbiKey = 0x00,
dbiUser = 0x01,
dbiDcOptionOldOld = 0x02,
dbiChatSizeMax = 0x03,
dbiMutePeer = 0x04,
dbiSendKeyOld = 0x05,
dbiAutoStart = 0x06,
dbiStartMinimized = 0x07,
dbiSoundFlashBounceNotify = 0x08,
dbiWorkMode = 0x09,
dbiSeenTrayTooltip = 0x0a,
dbiDesktopNotify = 0x0b,
dbiAutoUpdate = 0x0c,
dbiLastUpdateCheck = 0x0d,
dbiWindowPosition = 0x0e,
dbiConnectionTypeOld = 0x0f,
// 0x10 reserved
dbiDefaultAttach = 0x11,
dbiCatsAndDogs = 0x12,
dbiReplaceEmojiOld = 0x13,
dbiAskDownloadPath = 0x14,
dbiDownloadPathOld = 0x15,
dbiScaleOld = 0x16,
dbiEmojiTabOld = 0x17,
dbiRecentEmojiOldOld = 0x18,
dbiLoggedPhoneNumber = 0x19,
dbiMutedPeers = 0x1a,
// 0x1b reserved
dbiNotifyView = 0x1c,
dbiSendToMenu = 0x1d,
dbiCompressPastedImage = 0x1e,
dbiLangOld = 0x1f,
dbiLangFileOld = 0x20,
dbiTileBackgroundOld = 0x21,
dbiAutoLock = 0x22,
dbiDialogLastPath = 0x23,
dbiRecentEmojiOld = 0x24,
dbiEmojiVariantsOld = 0x25,
dbiRecentStickers = 0x26,
dbiDcOptionOld = 0x27,
dbiTryIPv6 = 0x28,
dbiSongVolume = 0x29,
dbiWindowsNotificationsOld = 0x30,
dbiIncludeMutedOld = 0x31,
dbiMegagroupSizeMax = 0x32,
dbiDownloadPath = 0x33,
dbiAutoDownloadOld = 0x34,
dbiSavedGifsLimit = 0x35,
dbiShowingSavedGifsOld = 0x36,
dbiAutoPlayOld = 0x37,
dbiAdaptiveForWide = 0x38,
dbiHiddenPinnedMessages = 0x39,
dbiRecentEmoji = 0x3a,
dbiEmojiVariants = 0x3b,
dbiDialogsModeOld = 0x40,
dbiModerateMode = 0x41,
dbiVideoVolume = 0x42,
dbiStickersRecentLimit = 0x43,
dbiNativeNotifications = 0x44,
dbiNotificationsCount = 0x45,
dbiNotificationsCorner = 0x46,
dbiThemeKeyOld = 0x47,
dbiDialogsWidthRatioOld = 0x48,
dbiUseExternalVideoPlayer = 0x49,
dbiDcOptions = 0x4a,
dbiMtpAuthorization = 0x4b,
dbiLastSeenWarningSeenOld = 0x4c,
dbiSessionSettings = 0x4d,
dbiLangPackKey = 0x4e,
dbiConnectionType = 0x4f,
dbiStickersFavedLimit = 0x50,
dbiSuggestStickersByEmojiOld = 0x51,
dbiSuggestEmojiOld = 0x52,
dbiTxtDomainStringOld = 0x53,
dbiThemeKey = 0x54,
dbiTileBackground = 0x55,
dbiCacheSettingsOld = 0x56,
dbiAnimationsDisabled = 0x57,
dbiScalePercent = 0x58,
dbiPlaybackSpeed = 0x59,
dbiLanguagesKey = 0x5a,
dbiCallSettings = 0x5b,
dbiCacheSettings = 0x5c,
dbiTxtDomainString = 0x5d,
dbiApplicationSettings = 0x5e,
dbiDialogsFilters = 0x5f,
dbiEncryptedWithSalt = 333,
dbiEncrypted = 444,
// 500-600 reserved
dbiVersion = 666,
};
enum {
dbictAuto = 0,
dbictHttpAuto = 1, // not used
dbictHttpProxy = 2,
dbictTcpProxy = 3,
dbictProxiesListOld = 4,
dbictProxiesList = 5,
};
inline constexpr auto kProxyTypeShift = 1024;
} // namespace details
} // namespace Storage

View File

@ -13,7 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwidget.h"
#include "mainwindow.h"
#include "core/application.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "storage/file_download_mtproto.h"
#include "storage/file_download_web.h"
#include "platform/platform_file_utilities.h"
@ -425,7 +425,9 @@ bool FileLoader::finalizeResult() {
if (_localStatus == LocalStatus::NotFound) {
if (const auto key = fileLocationKey()) {
if (!_filename.isEmpty()) {
Local::writeFileLocation(*key, FileLocation(_filename));
_session->local().writeFileLocation(
*key,
FileLocation(_filename));
}
}
const auto key = cacheKey();

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "storage/file_download.h"
#include "storage/cache/storage_cache_database.h"
#include "storage/localimageloader.h"
#include "main/main_session.h"
@ -26,6 +25,9 @@ struct Language;
} // namespace Lang
namespace Storage {
namespace details {
struct ReadSettingsContext;
} // namespace details
class EncryptionKey;
} // namespace Storage
@ -45,23 +47,16 @@ namespace Local {
void start();
void finish();
void readSettings();
void writeSettings();
void writeUserSettings();
void writeMtpData();
void writeAutoupdatePrefix(const QString &prefix);
QString readAutoupdatePrefix();
void reset();
bool checkPasscode(const QByteArray &passcode);
void setPasscode(const QByteArray &passcode);
enum ClearManagerTask {
ClearManagerAll = 0xFFFF,
ClearManagerDownloads = 0x01,
ClearManagerStorage = 0x02,
};
struct ClearManagerData;
@ -89,73 +84,12 @@ private:
};
enum ReadMapState {
ReadMapFailed = 0,
ReadMapDone = 1,
ReadMapPassNeeded = 2,
};
ReadMapState readMap(const QByteArray &pass);
int32 oldMapVersion();
int32 oldSettingsVersion();
struct MessageDraft {
MessageDraft(MsgId msgId = 0, TextWithTags textWithTags = TextWithTags(), bool previewCancelled = false)
: msgId(msgId)
, textWithTags(textWithTags)
, previewCancelled(previewCancelled) {
}
MsgId msgId;
TextWithTags textWithTags;
bool previewCancelled;
};
void writeDrafts(const PeerId &peer, const MessageDraft &localDraft, const MessageDraft &editDraft);
void readDraftsWithCursors(History *h);
void writeDraftCursors(const PeerId &peer, const MessageCursor &localCursor, const MessageCursor &editCursor);
bool hasDraftCursors(const PeerId &peer);
bool hasDraft(const PeerId &peer);
void writeFileLocation(MediaKey location, const FileLocation &local);
FileLocation readFileLocation(MediaKey location);
void removeFileLocation(MediaKey location);
Storage::EncryptionKey cacheKey();
QString cachePath();
Storage::Cache::Database::Settings cacheSettings();
void updateCacheSettings(
Storage::Cache::Database::SettingsUpdate &update,
Storage::Cache::Database::SettingsUpdate &updateBig);
Storage::EncryptionKey cacheBigFileKey();
QString cacheBigFilePath();
Storage::Cache::Database::Settings cacheBigFileSettings();
void countVoiceWaveform(not_null<Data::DocumentMedia*> media);
void cancelTask(TaskId id);
void writeInstalledStickers();
void writeFeaturedStickers();
void writeRecentStickers();
void writeFavedStickers();
void writeArchivedStickers();
void readInstalledStickers();
void readFeaturedStickers();
void readRecentStickers();
void readFavedStickers();
void readArchivedStickers();
int32 countStickersHash(bool checkOutdatedInfo = false);
int32 countRecentStickersHash();
int32 countFavedStickersHash();
int32 countFeaturedStickersHash();
void writeSavedGifs();
void readSavedGifs();
int32 countSavedGifsHash();
void writeBackground(const Data::WallPaper &paper, const QImage &image);
bool readBackground();
void writeTheme(const Window::Theme::Saved &saved);
void clearTheme();
[[nodiscard]] Window::Theme::Saved readThemeAfterSwitch();
@ -167,46 +101,23 @@ void pushRecentLanguage(const Lang::Language &language);
std::vector<Lang::Language> readRecentLanguages();
void saveRecentLanguages(const std::vector<Lang::Language> &list);
void removeRecentLanguage(const QString &id);
void incrementRecentHashtag(RecentHashtagPack &recent, const QString &tag);
void writeRecentHashtagsAndBots();
void readRecentHashtagsAndBots();
void saveRecentSentHashtags(const QString &text);
void saveRecentSearchHashtags(const QString &text);
void WriteExportSettings(const Export::Settings &settings);
Export::Settings ReadExportSettings();
void writeSelf();
void readSelf(const QByteArray &serialized, int32 streamVersion);
void makeBotTrusted(UserData *bot);
bool isBotTrusted(UserData *bot);
bool encrypt(const void *src, void *dst, uint32 len, const void *key128);
bool decrypt(const void *src, void *dst, uint32 len, const void *key128);
bool readOldMtpData(
bool remove,
Storage::details::ReadSettingsContext &context);
bool readOldUserSettings(
bool remove,
Storage::details::ReadSettingsContext &context);
namespace internal {
class Manager : public QObject {
Q_OBJECT
class Manager final : public QObject {
public:
Manager();
void writeMap(bool fast);
void writingMap();
void writeLocations(bool fast);
void writingLocations();
void finish();
public slots:
void mapWriteTimeout();
void locationsWriteTimeout();
private:
QTimer _mapWriteTimer;
QTimer _locationsWriteTimer;
};
} // namespace internal

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,265 @@
/*
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 "base/timer.h"
#include "storage/cache/storage_cache_database.h"
#include "data/stickers/data_stickers_set.h"
class History;
class FileLocation;
namespace Export {
struct Settings;
} // namespace Export
namespace Main {
class Account;
class Settings;
} // namespace Main
namespace Data {
class WallPaper;
} // namespace Data
namespace MTP {
class AuthKey;
using AuthKeyPtr = std::shared_ptr<AuthKey>;
} // namespace MTP
namespace Storage {
namespace details {
struct ReadSettingsContext;
} // namespace details
class EncryptionKey;
using FileKey = quint64;
enum class StartResult : uchar {
Success,
IncorrectPasscode,
};
struct MessageDraft {
MsgId msgId = 0;
TextWithTags textWithTags;
bool previewCancelled = false;
};
class Account final {
public:
Account(not_null<Main::Account*> owner, const QString &dataName);
~Account();
[[nodiscard]] StartResult start(const QByteArray &passcode);
[[nodiscard]] int oldMapVersion() const {
return _oldMapVersion;
}
[[nodiscard]] bool checkPasscode(const QByteArray &passcode) const;
void setPasscode(const QByteArray &passcode);
void writeSettings();
void writeMtpData();
void writeBackground(const Data::WallPaper &paper, const QImage &image);
bool readBackground();
void writeDrafts(
const PeerId &peer,
const MessageDraft &localDraft,
const MessageDraft &editDraft);
void readDraftsWithCursors(not_null<History*> history);
void writeDraftCursors(
const PeerId &peer,
const MessageCursor &localCursor,
const MessageCursor &editCursor);
[[nodiscard]] bool hasDraftCursors(const PeerId &peer);
[[nodiscard]] bool hasDraft(const PeerId &peer);
void writeFileLocation(MediaKey location, const FileLocation &local);
[[nodiscard]] FileLocation readFileLocation(MediaKey location);
void removeFileLocation(MediaKey location);
[[nodiscard]] EncryptionKey cacheKey() const;
[[nodiscard]] QString cachePath() const;
[[nodiscard]] Cache::Database::Settings cacheSettings() const;
void updateCacheSettings(
Cache::Database::SettingsUpdate &update,
Cache::Database::SettingsUpdate &updateBig);
[[nodiscard]] EncryptionKey cacheBigFileKey() const;
[[nodiscard]] QString cacheBigFilePath() const;
[[nodiscard]] Cache::Database::Settings cacheBigFileSettings() const;
void writeInstalledStickers();
void writeFeaturedStickers();
void writeRecentStickers();
void writeFavedStickers();
void writeArchivedStickers();
void readInstalledStickers();
void readFeaturedStickers();
void readRecentStickers();
void readFavedStickers();
void readArchivedStickers();
void writeSavedGifs();
void readSavedGifs();
void writeRecentHashtagsAndBots();
void readRecentHashtagsAndBots();
void saveRecentSentHashtags(const QString &text);
void saveRecentSearchHashtags(const QString &text);
void writeExportSettings(const Export::Settings &settings);
[[nodiscard]] Export::Settings readExportSettings();
void writeSelf();
void readSelf(const QByteArray &serialized, int32 streamVersion);
void markBotTrusted(not_null<UserData*> bot);
[[nodiscard]] bool isBotTrusted(not_null<UserData*> bot);
[[nodiscard]] bool encrypt(
const void *src,
void *dst,
uint32 len,
const void *key128) const;
[[nodiscard]] bool decrypt(
const void *src,
void *dst,
uint32 len,
const void *key128) const;
void reset();
private:
enum class ReadMapResult {
Success,
IncorrectPasscode,
Failed,
};
[[nodiscard]] base::flat_set<QString> collectGoodNames() const;
[[nodiscard]] auto prepareReadSettingsContext() const
-> details::ReadSettingsContext;
[[nodiscard]] ReadMapResult readMap(const QByteArray &passcode);
void writeMapDelayed();
void writeMapQueued();
void writeMap();
void readLocations();
void writeLocations();
void writeLocationsQueued();
void writeLocationsDelayed();
std::unique_ptr<Main::Settings> readSettings();
void writeSettings(Main::Settings *stored);
bool readOldUserSettings(
bool remove,
details::ReadSettingsContext &context);
void readOldUserSettingsFields(
QIODevice *device,
qint32 &version,
details::ReadSettingsContext &context);
void readOldMtpDataFields(
QIODevice *device,
qint32 &version,
details::ReadSettingsContext &context);
bool readOldMtpData(bool remove, details::ReadSettingsContext &context);
void readMtpData();
std::unique_ptr<Main::Settings> applyReadContext(
details::ReadSettingsContext &&context);
[[nodiscard]] QByteArray serializeCallSettings();
void deserializeCallSettings(QByteArray &settings);
void readDraftCursors(
const PeerId &peer,
MessageCursor &localCursor,
MessageCursor &editCursor);
void clearDraftCursors(const PeerId &peer);
void writeStickerSet(
QDataStream &stream,
const Data::StickersSet &set);
template <typename CheckSet>
void writeStickerSets(
FileKey &stickersKey,
CheckSet checkSet,
const Data::StickersSetsOrder &order);
void readStickerSets(
FileKey &stickersKey,
Data::StickersSetsOrder *outOrder = nullptr,
MTPDstickerSet::Flags readingFlags = 0);
void importOldRecentStickers();
void readTrustedBots();
void writeTrustedBots();
std::optional<RecentHashtagPack> saveRecentHashtags(
Fn<RecentHashtagPack()> getPack,
const QString &text);
const not_null<Main::Account*> _owner;
const QString _dataName;
const FileKey _dataNameKey = 0;
const QString _basePath;
const QString _databasePath;
MTP::AuthKeyPtr _localKey;
MTP::AuthKeyPtr _passcodeKey;
QByteArray _passcodeKeySalt;
QByteArray _passcodeKeyEncrypted;
base::flat_map<PeerId, FileKey> _draftsMap;
base::flat_map<PeerId, FileKey> _draftCursorsMap;
base::flat_map<PeerId, bool> _draftsNotReadMap;
QMultiMap<MediaKey, FileLocation> _fileLocations;
QMap<QString, QPair<MediaKey, FileLocation>> _fileLocationPairs;
QMap<MediaKey, MediaKey> _fileLocationAliases;
FileKey _locationsKey = 0;
FileKey _trustedBotsKey = 0;
FileKey _installedStickersKey = 0;
FileKey _featuredStickersKey = 0;
FileKey _recentStickersKey = 0;
FileKey _favedStickersKey = 0;
FileKey _archivedStickersKey = 0;
FileKey _savedGifsKey = 0;
FileKey _recentStickersKeyOld = 0;
FileKey _backgroundKeyDay = 0;
FileKey _backgroundKeyNight = 0;
FileKey _settingsKey = 0;
FileKey _recentHashtagsAndBotsKey = 0;
FileKey _exportSettingsKey = 0;
qint64 _cacheTotalSizeLimit = 0;
qint64 _cacheBigFileTotalSizeLimit = 0;
qint32 _cacheTotalTimeLimit = 0;
qint32 _cacheBigFileTotalTimeLimit = 0;
base::flat_set<uint64> _trustedBots;
bool _trustedBotsRead = false;
bool _backgroundCanWrite = true;
bool _readingUserSettings = false;
bool _recentHashtagsAndBotsWereRead = false;
int _oldMapVersion = 0;
base::Timer _writeMapTimer;
base::Timer _writeLocationsTimer;
bool _mapChanged = false;
bool _locationsChanged = false;
};
} // namespace Storage

View File

@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h"
#include "apiwrap.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "storage/localimageloader.h"
#include "storage/file_upload.h"
#include "base/parse_helper.h"
@ -529,6 +530,10 @@ ChatBackground::ChatBackground() : _adjustableColors({
});
}
Storage::Account &ChatBackground::local() const {
return Core::App().activeAccount().local();
}
void ChatBackground::setThemeData(QImage &&themeImage, bool themeTile) {
_themeImage = validateBackgroundImage(std::move(themeImage));
_themeTile = themeTile;
@ -538,7 +543,7 @@ void ChatBackground::start() {
if (!Data::details::IsUninitializedWallPaper(_paper)) {
return;
}
if (!Local::readBackground()) {
if (!local().readBackground()) {
set(Data::ThemeWallPaper());
}
@ -653,7 +658,7 @@ void ChatBackground::set(const Data::WallPaper &paper, QImage image) {
setPaper(Data::DefaultWallPaper().withParamsFrom(_paper));
image.load(qsl(":/gui/art/bg.jpg"));
}
Local::writeBackground(
local().writeBackground(
_paper,
((Data::IsDefaultWallPaper(_paper)
|| Data::IsLegacy1DefaultWallPaper(_paper))
@ -869,7 +874,7 @@ void ChatBackground::setTile(bool tile) {
if (this->tile() != old) {
if (!Data::details::IsTestingThemeWallPaper(_paper)
&& !Data::details::IsTestingDefaultWallPaper(_paper)) {
Local::writeUserSettings();
local().writeSettings();
}
notify(BackgroundUpdate(BackgroundUpdate::Type::Changed, tile));
}
@ -1024,9 +1029,9 @@ bool ChatBackground::isNonDefaultBackground() {
void ChatBackground::writeNewBackgroundSettings() {
if (tile() != _tileForRevert) {
Local::writeUserSettings();
local().writeSettings();
}
Local::writeBackground(
local().writeBackground(
_paper,
((Data::IsThemeWallPaper(_paper)
|| Data::IsDefaultWallPaper(_paper))
@ -1111,12 +1116,12 @@ void ChatBackground::reapplyWithNightMode(
ClearApplying();
keepApplied(saved.object, settingExactTheme);
if (tile() != _tileForRevert) {
Local::writeUserSettings();
local().writeSettings();
}
if (nightModeChanged) {
Local::writeSettings();
}
if (!settingExactTheme && !Local::readBackground()) {
if (!settingExactTheme && !local().readBackground()) {
set(Data::ThemeWallPaper());
}
};

View File

@ -14,6 +14,10 @@ namespace Main {
class Session;
} // namespace Main
namespace Storage {
class Account;
} // namespace Storage
namespace Window {
namespace Theme {
@ -177,6 +181,8 @@ private:
QColor original;
};
Storage::Account &local() const;
void ensureStarted();
void saveForRevert();
void setPreparedImage(QImage original, QImage prepared);

View File

@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_lock_widgets.h"
#include "lang/lang_keys.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "mainwindow.h"
#include "core/application.h"
#include "api/api_text_entities.h"
@ -147,9 +147,11 @@ void PasscodeLockWidget::submit() {
}
const auto passcode = _passcode->text().toUtf8();
const auto correct = window()->account().sessionExists()
? Local::checkPasscode(passcode)
: (Local::readMap(passcode) != Local::ReadMapPassNeeded);
auto &account = window()->account();
auto &local = window()->account().local();
const auto correct = account.sessionExists()
? local.checkPasscode(passcode)
: (local.start(passcode) != Storage::StartResult::IncorrectPasscode);
if (!correct) {
cSetPasscodeBadTries(cPasscodeBadTries() + 1);
cSetPasscodeLastTry(crl::now());

View File

@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/empty_userpic.h"
#include "mainwindow.h"
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "support/support_templates.h"
#include "settings/settings_common.h"
#include "base/qt_signal_producer.h"
@ -281,7 +282,7 @@ void MainMenu::refreshMenu() {
(*fix)->setChecked(!(*fix)->isChecked());
_controller->session().settings().setSupportFixChatsOrder(
(*fix)->isChecked());
Local::writeUserSettings();
_controller->session().local().writeSettings();
}, &st::mainMenuFixOrder, &st::mainMenuFixOrderOver);
(*fix)->setCheckable(true);
(*fix)->setChecked(