Support cloud languages list and switching.

Add Lang::Current().updated() observable for retranslating the UI.
This commit is contained in:
John Preston 2017-04-18 18:21:03 +03:00
parent 139d4e72b5
commit f5dfeb0c50
16 changed files with 415 additions and 179 deletions

View File

@ -357,9 +357,9 @@ class Observable : public internal::BaseObservable<EventType, Handler, base::typ
public:
Observable() = default;
Observable(const Observable &other) = delete;
Observable(Observable &&other) = default;
Observable(Observable &&other) = delete;
Observable &operator=(const Observable &other) = delete;
Observable &operator=(Observable &&other) = default;
Observable &operator=(Observable &&other) = delete;
};

View File

@ -28,81 +28,119 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "mainwidget.h"
#include "mainwindow.h"
#include "lang/lang_instance.h"
#include "lang/lang_cloud_manager.h"
#include "styles/style_boxes.h"
class LanguageBox::Inner : public TWidget {
public:
Inner(QWidget *parent, gsl::not_null<Languages*> languages);
void setSelected(int index);
void refresh();
private:
void languageChanged(int languageIndex);
gsl::not_null<Languages*> _languages;
std::shared_ptr<Ui::RadiobuttonGroup> _group;
std::vector<object_ptr<Ui::Radiobutton>> _buttons;
};
LanguageBox::Inner::Inner(QWidget *parent, gsl::not_null<Languages*> languages) : TWidget(parent)
, _languages(languages) {
_group = std::make_shared<Ui::RadiobuttonGroup>(0);
_group->setChangedCallback([this](int value) { languageChanged(value); });
}
void LanguageBox::Inner::setSelected(int index) {
_group->setValue(index);
}
void LanguageBox::Inner::refresh() {
for (auto &button : _buttons) {
button.destroy();
}
_buttons.clear();
auto y = st::boxOptionListPadding.top();
_buttons.reserve(_languages->size());
auto index = 0;
for_const (auto &language, *_languages) {
_buttons.emplace_back(this, _group, index++, language.name, st::langsButton);
auto button = _buttons.back().data();
button->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), y + st::langsButton.margin.top());
button->show();
y += button->heightNoMargins() + st::boxOptionListSkip;
}
auto newHeight = y + st::boxOptionListPadding.bottom() + st::boxPadding.bottom();
resize(st::langsWidth, newHeight);
}
void LanguageBox::Inner::languageChanged(int languageIndex) {
Expects(languageIndex >= 0 && languageIndex < _languages->size());
auto languageId = (*_languages)[languageIndex].id;
if (languageId != qsl("custom")) {
Lang::CurrentCloudManager().switchToLanguage(languageId);
}
}
void LanguageBox::prepare() {
refreshLangItems();
subscribe(Lang::Current().updated(), [this] {
refreshLangItems();
});
_inner = setInnerWidget(object_ptr<Inner>(this, &_languages), st::boxLayerScroll);
refresh();
subscribe(Lang::CurrentCloudManager().languageListChanged(), [this] {
refresh();
});
}
void LanguageBox::refreshLangItems() {
clearButtons();
addButton(lang(lng_box_ok), [this] { closeBox(); });
setTitle(lang(lng_languages));
request(MTPlangpack_GetLanguages()).done([this](const MTPVector<MTPLangPackLanguage> &result) {
auto currentId = Lang::Current().id();
auto currentFound = false;
std::vector<QString> languageIds = { qsl("en") };
std::vector<QString> languageNames = { qsl("English") };
for (auto &language : result.v) {
t_assert(language.type() == mtpc_langPackLanguage);
auto &data = language.c_langPackLanguage();
auto languageId = qs(data.vlang_code);
auto languageName = qs(data.vname);
if (languageId != qstr("en")) {
languageIds.push_back(languageId);
languageNames.push_back(languageName);
}
}
if (currentId == qstr("custom")) {
languageIds.insert(languageIds.begin(), currentId);
languageNames.insert(languageNames.begin(), qsl("Custom LangPack"));
currentFound = true;
}
auto languageCount = languageIds.size();
_langGroup = std::make_shared<Ui::RadiobuttonGroup>(cLang());
auto y = st::boxOptionListPadding.top();
_langs.reserve(languageCount);
for (auto i = 0; i != languageCount; ++i) {
if (!currentFound && languageIds[i] == currentId) {
currentFound = true;
}
_langs.emplace_back(this, _langGroup, i, languageNames[i], st::langsButton);
auto button = _langs.back().data();
button->moveToLeft(st::boxPadding.left() + st::boxOptionListPadding.left(), y + st::langsButton.margin.top());
button->show();
y += button->heightNoMargins() + st::boxOptionListSkip;
}
_langGroup->setChangedCallback([this](int value) { languageChanged(value); });
setDimensions(st::langsWidth, st::boxOptionListPadding.top() + languageCount * st::langsButton.height + languageCount * st::boxOptionListSkip + st::boxOptionListPadding.bottom() + st::boxPadding.bottom());
}).fail([this](const RPCError &error) {
closeBox();
}).send();
setDimensions(st::langsWidth, st::langsWidth);
update();
}
void LanguageBox::languageChanged(int languageId) {
//Expects(languageId == languageTest || (languageId >= 0 && languageId < base::array_size(LanguageCodes)));
void LanguageBox::refresh() {
refreshLanguages();
//if (languageId == cLang()) {
// return;
//}
//Lang::FileParser::Result result;
//if (languageId > 0) {
// Lang::FileParser loader(qsl(":/langs/lang_") + LanguageCodes[languageId].c_str() + qsl(".strings"), { lng_sure_save_language, lng_cancel, lng_box_ok });
// result = loader.found();
//} else if (languageId == languageTest) {
// Lang::FileParser loader(cLangFile(), { lng_sure_save_language, lng_cancel, lng_box_ok });
// result = loader.found();
//}
//auto text = result.value(lng_sure_save_language, Lang::GetOriginalValue(lng_sure_save_language)),
// save = result.value(lng_box_ok, Lang::GetOriginalValue(lng_box_ok)),
// cancel = result.value(lng_cancel, Lang::GetOriginalValue(lng_cancel));
//Ui::show(Box<ConfirmBox>(text, save, cancel, base::lambda_guarded(this, [this, languageId] {
// cSetLang(languageId);
// Local::writeSettings();
// App::restart();
//}), base::lambda_guarded(this, [this] {
// _langGroup->setValue(cLang());
//})), KeepOtherLayers);
_inner->refresh();
auto maxHeight = st::boxOptionListPadding.top() + _languages.size() * (st::langsButton.height + st::boxOptionListSkip) + st::boxOptionListPadding.bottom() + st::boxPadding.bottom();
setDimensions(st::langsWidth, qMin(maxHeight, st::boxMaxListHeight));
}
void LanguageBox::refreshLanguages() {
_languages = Languages();
auto list = Lang::CurrentCloudManager().languageList();
_languages.reserve(list.size() + 1);
auto currentId = Lang::Current().id();
auto currentIndex = -1;
_languages.push_back({ qsl("en"), qsl("English") });
for (auto &language : list) {
auto isCurrent = (language.id == currentId);
if (language.id != qstr("en")) {
if (isCurrent) {
currentIndex = _languages.size();
}
_languages.push_back(language);
} else if (isCurrent) {
currentIndex = 0;
}
}
if (currentId == qstr("custom")) {
_languages.insert(_languages.begin(), { currentId, qsl("Custom LangPack") });
currentIndex = 0;
} else if (currentIndex < 0) {
currentIndex = _languages.size();
_languages.push_back({ currentId, lang(lng_language_name) });
}
_inner->setSelected(currentIndex);
}

View File

@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "lang/lang_cloud_manager.h"
#include "boxes/abstract_box.h"
#include "mtproto/sender.h"
@ -29,8 +30,6 @@ class Radiobutton;
} // namespace Ui
class LanguageBox : public BoxContent, private MTP::Sender {
Q_OBJECT
public:
LanguageBox(QWidget*) {
}
@ -39,9 +38,15 @@ protected:
void prepare() override;
private:
void languageChanged(int languageId);
using Languages = Lang::CloudManager::Languages;
std::shared_ptr<Ui::RadiobuttonGroup> _langGroup;
std::vector<object_ptr<Ui::Radiobutton>> _langs;
void refresh();
void refreshLanguages();
void refreshLangItems();
Languages _languages;
class Inner;
QPointer<Inner> _inner;
};

View File

@ -0,0 +1,123 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "lang/lang_cloud_manager.h"
#include "lang/lang_instance.h"
#include "mtproto/mtp_instance.h"
#include "storage/localstorage.h"
#include "messenger.h"
#include "apiwrap.h"
#include "auth_session.h"
namespace Lang {
CloudManager::CloudManager(Instance &langpack, gsl::not_null<MTP::Instance*> mtproto) : MTP::Sender(mtproto)
, _langpack(langpack) {
requestLangPackDifference();
}
void CloudManager::requestLangPackDifference() {
auto &langpack = Lang::Current();
if (langpack.isCustom() || _langPackRequestId) {
return;
}
auto version = langpack.version();
if (version > 0) {
_langPackRequestId = request(MTPlangpack_GetDifference(MTP_int(version))).done([this](const MTPLangPackDifference &result) {
_langPackRequestId = 0;
applyLangPackDifference(result);
}).fail([this](const RPCError &error) {
_langPackRequestId = 0;
}).send();
} else {
_langPackRequestId = request(MTPlangpack_GetLangPack()).done([this](const MTPLangPackDifference &result) {
_langPackRequestId = 0;
applyLangPackDifference(result);
}).fail([this](const RPCError &error) {
_langPackRequestId = 0;
}).send();
}
}
void CloudManager::applyLangPackDifference(const MTPLangPackDifference &difference) {
Expects(difference.type() == mtpc_langPackDifference);
auto &current = Lang::Current();
if (current.isCustom()) {
return;
}
auto &langpack = difference.c_langPackDifference();
switchLangPackId(qs(langpack.vlang_code));
if (current.version() < langpack.vfrom_version.v) {
requestLangPackDifference();
} else if (!langpack.vstrings.v.isEmpty()) {
current.applyDifference(langpack);
Local::writeLangPack();
auto fullLangPackUpdated = (langpack.vfrom_version.v == 0);
if (fullLangPackUpdated) {
Lang::Current().updated().notify();
}
} else {
LOG(("Lang Info: Up to date."));
}
}
void CloudManager::requestLanguageList() {
_languagesRequestId = request(MTPlangpack_GetLanguages()).done([this](const MTPVector<MTPLangPackLanguage> &result) {
auto languages = Languages();
for_const (auto &langData, result.v) {
t_assert(langData.type() == mtpc_langPackLanguage);
auto &language = langData.c_langPackLanguage();
languages.push_back({ qs(language.vlang_code), qs(language.vname) });
}
if (_languages != languages) {
_languages = languages;
_languagesChanged.notify();
}
_languagesRequestId = 0;
}).fail([this](const RPCError &error) {
_languagesRequestId = 0;
}).send();
}
void CloudManager::switchToLanguage(const QString &id) {
switchLangPackId(id);
requestLangPackDifference();
}
void CloudManager::switchLangPackId(const QString &id) {
auto &current = Lang::Current();
if (current.id() != id) {
current.switchToId(id);
auto mtproto = requestMTP();
mtproto->reInitConnection(mtproto->mainDcId());
}
}
CloudManager &CurrentCloudManager() {
auto result = Messenger::Instance().langCloudManager();
t_assert(result != nullptr);
return *result;
}
} // namespace Lang

View File

@ -0,0 +1,77 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include "mtproto/sender.h"
namespace MTP {
class Instance;
} // namespace MTP
namespace Lang {
class Instance;
class CloudManager : private MTP::Sender {
public:
CloudManager(Instance &langpack, gsl::not_null<MTP::Instance*> mtproto);
struct Language {
QString id;
QString name;
};
using Languages = QVector<Language>;
void requestLanguageList();
Languages languageList() const {
return _languages;
}
base::Observable<void> &languageListChanged() {
return _languagesChanged;
}
void requestLangPackDifference();
void applyLangPackDifference(const MTPLangPackDifference &difference);
void switchToLanguage(const QString &id);
private:
void applyLangPack(const MTPUpdates &updates);
void switchLangPackId(const QString &id);
Instance &_langpack;
Languages _languages;
base::Observable<void> _languagesChanged;
mtpRequestId _langPackRequestId = 0;
mtpRequestId _languagesRequestId = 0;
};
inline bool operator==(const CloudManager::Language &a, const CloudManager::Language &b) {
return (a.id == b.id) && (a.name == b.name);
}
inline bool operator!=(const CloudManager::Language &a, const CloudManager::Language &b) {
return !(a == b);
}
CloudManager &CurrentCloudManager();
} // namespace Lang

View File

@ -22,9 +22,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "messenger.h"
#include "lang/lang_file_parser.h"
#include "platform/platform_specific.h"
#include "storage/serialize_common.h"
#include "storage/localstorage.h"
#include "platform/platform_specific.h"
namespace Lang {
namespace {
@ -32,6 +32,16 @@ namespace {
constexpr auto kDefaultLanguage = str_const("en");
constexpr auto kLangValuesLimit = 20000;
constexpr str_const kLegacyLanguages[] = {
"en",
"it",
"es",
"de",
"nl",
"pt_BR",
"ko",
};
class ValueParser {
public:
ValueParser(const QByteArray &key, LangKey keyIndex, const QByteArray &value);
@ -220,14 +230,38 @@ bool ValueParser::parse() {
} // namespace
void Instance::fillDefaults() {
void Instance::switchToId(const QString &id) {
reset();
_id = id;
}
void Instance::switchToCustomFile(const QString &filePath) {
reset();
fillFromCustomFile(filePath);
}
void Instance::reset() {
_values.clear();
_nonDefaultValues.clear();
_legacyId = kLegacyLanguageNone;
_customFilePathAbsolute = QString();
_customFilePathRelative = QString();
_customFileContent = QByteArray();
_version = 0;
fillDefaults();
}
void Instance::fillDefaults() {
Expects(_values.empty());
_values.reserve(kLangKeysCount);
for (auto i = 0; i != kLangKeysCount; ++i) {
_values.emplace_back(GetOriginalValue(LangKey(i)));
}
_id = str_const_toString(kDefaultLanguage);
_legacyId = kLegacyDefaultLanguage;
}
QString Instance::DefaultLanguageId() {
return str_const_toString(kDefaultLanguage);
}
QString Instance::cloudLangCode() const {
@ -235,7 +269,7 @@ QString Instance::cloudLangCode() const {
if (_systemLanguage.isEmpty()) {
_systemLanguage = Platform::SystemLanguage();
if (_systemLanguage.isEmpty()) {
_systemLanguage = str_const_toString(kDefaultLanguage);
_systemLanguage = Instance::DefaultLanguageId();
}
}
return _systemLanguage;

View File

@ -27,36 +27,23 @@ namespace Lang {
constexpr auto kLegacyLanguageNone = -2;
constexpr auto kLegacyCustomLanguage = -1;
constexpr auto kLegacyDefaultLanguage = 0;
constexpr str_const kLegacyLanguages[] = {
"en",
"it",
"es",
"de",
"nl",
"pt_BR",
"ko",
};
class Instance {
public:
Instance() {
fillDefaults();
}
struct CreateFromIdTag {};
Instance(const QString &id, CreateFromIdTag) {
fillDefaults();
_id = id;
}
struct CreateFromCustomFileTag {};
Instance(const QString &filePath, CreateFromCustomFileTag) {
fillDefaults();
fillFromCustomFile(filePath);
}
void switchToId(const QString &id);
void switchToCustomFile(const QString &filePath);
Instance(const Instance &other) = delete;
Instance &operator=(const Instance &other) = delete;
Instance(Instance &&other) = default;
Instance &operator=(Instance &&other) = default;
static QString DefaultLanguageId();
QString cloudLangCode() const;
QString id() const {
return _id;
}
@ -66,13 +53,15 @@ public:
int version() const {
return _version;
}
QString cloudLangCode() const;
QByteArray serialize() const;
void fillFromSerialized(const QByteArray &data);
void fillFromLegacy(int legacyId, const QString &legacyPath);
void applyDifference(const MTPDlangPackDifference &difference);
base::Observable<void> &updated() {
return _updated;
}
QString getValue(LangKey key) {
Expects(key >= 0 && key < kLangKeysCount);
@ -83,6 +72,7 @@ public:
private:
void applyValue(const QByteArray &key, const QByteArray &value);
void resetValue(const QByteArray &key);
void reset();
void fillDefaults();
void fillFromCustomFile(const QString &filePath);
void loadFromContent(const QByteArray &content);
@ -94,6 +84,8 @@ private:
QString _customFilePathRelative;
QByteArray _customFileContent;
int _version = 0;
base::Observable<void> _updated;
mutable QString _systemLanguage;
std::vector<QString> _values;

View File

@ -38,6 +38,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "history/history_service_layout.h"
#include "overviewwidget.h"
#include "lang/lang_keys.h"
#include "lang/lang_cloud_manager.h"
#include "boxes/add_contact_box.h"
#include "storage/file_upload.h"
#include "messenger.h"
@ -5689,11 +5690,11 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
////// Cloud langpacks
case mtpc_updateLangPack: {
auto &langpack = update.c_updateLangPack();
Messenger::Instance().mtp()->applyLangPackDifference(langpack.vdifference);
Messenger::Instance().langCloudManager()->applyLangPackDifference(langpack.vdifference);
} break;
case mtpc_updateLangPackTooLong: {
Messenger::Instance().mtp()->requestLangPackDifference();
Messenger::Instance().langCloudManager()->requestLangPackDifference();
} break;
}

View File

@ -31,6 +31,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "calls/calls_instance.h"
#include "lang/lang_file_parser.h"
#include "lang/lang_translator.h"
#include "lang/lang_cloud_manager.h"
#include "observer_peer.h"
#include "storage/file_upload.h"
#include "mainwidget.h"
@ -318,6 +319,8 @@ void Messenger::startMtp() {
}
_private->storedAuthSession.reset();
}
_langCloudManager = std::make_unique<Lang::CloudManager>(langpack(), mtp());
}
void Messenger::destroyMtpKeys(MTP::AuthKeysList &&keys) {

View File

@ -50,6 +50,7 @@ class Instance;
namespace Lang {
class Instance;
class Translator;
class CloudManager;
} // namespace Lang
class Messenger final : public QObject, public RPCSender, private base::Subscriber {
@ -109,6 +110,9 @@ public:
Lang::Instance &langpack() {
return *_langpack;
}
Lang::CloudManager *langCloudManager() {
return _langCloudManager.get();
}
void authSessionCreate(UserId userId);
void authSessionDestroy();
base::Observable<void> &authSessionChanged() {
@ -197,6 +201,7 @@ private:
FileUploader *_uploader = nullptr;
std::unique_ptr<Lang::Instance> _langpack;
std::unique_ptr<Lang::CloudManager> _langCloudManager;
std::unique_ptr<Lang::Translator> _translator;
std::unique_ptr<MTP::DcOptions> _dcOptions;
std::unique_ptr<MTP::Instance> _mtproto;

View File

@ -33,7 +33,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace MTP {
class Instance::Private : public Sender {
class Instance::Private : private Sender {
public:
Private(Instance *instance, DcOptions *options, Instance::Mode mode);
@ -51,8 +51,6 @@ public:
void requestConfig();
void requestCDNConfig();
void requestLangPackDifference();
void applyLangPackDifference(const MTPLangPackDifference &difference);
void restart();
void restart(ShiftedDcId shiftedDcId);
@ -64,6 +62,7 @@ public:
void killSession(ShiftedDcId shiftedDcId);
void killSession(std::unique_ptr<internal::Session> session);
void stopSession(ShiftedDcId shiftedDcId);
void reInitConnection(DcId dcId);
void logout(RPCDoneHandlerPtr onDone, RPCFailHandlerPtr onFail);
internal::DcenterPtr getDcById(ShiftedDcId shiftedDcId);
@ -129,8 +128,6 @@ private:
void checkDelayedRequests();
void switchLangPackId(const QString &id);
Instance *_instance = nullptr;
DcOptions *_dcOptions = nullptr;
Instance::Mode _mode = Instance::Mode::Normal;
@ -183,8 +180,6 @@ private:
base::Timer _checkDelayedTimer;
mtpRequestId _langPackRequestId = 0;
// Debug flag to find out how we end up crashing.
bool MustNotCreateSessions = false;
@ -246,7 +241,6 @@ void Instance::Private::start(Config &&config) {
t_assert((_mainDcId == Config::kNoneMainDc) == isKeysDestroyer());
if (!isKeysDestroyer()) {
requestConfig();
requestLangPackDifference();
}
}
@ -303,58 +297,6 @@ void Instance::Private::requestCDNConfig() {
}).send();
}
void Instance::Private::requestLangPackDifference() {
auto &langpack = Lang::Current();
if (langpack.isCustom() || _langPackRequestId) {
return;
}
auto version = langpack.version();
if (version > 0) {
_langPackRequestId = request(MTPlangpack_GetDifference(MTP_int(version))).done([this](const MTPLangPackDifference &result) {
_langPackRequestId = 0;
applyLangPackDifference(result);
}).fail([this](const RPCError &error) {
_langPackRequestId = 0;
}).send();
} else {
_langPackRequestId = request(MTPlangpack_GetLangPack()).done([this](const MTPLangPackDifference &result) {
_langPackRequestId = 0;
applyLangPackDifference(result);
}).fail([this](const RPCError &error) {
_langPackRequestId = 0;
}).send();
}
}
void Instance::Private::applyLangPackDifference(const MTPLangPackDifference &difference) {
Expects(difference.type() == mtpc_langPackDifference);
auto &current = Lang::Current();
if (current.isCustom()) {
return;
}
auto &langpack = difference.c_langPackDifference();
switchLangPackId(qs(langpack.vlang_code));
if (current.version() < langpack.vfrom_version.v) {
requestLangPackDifference();
} else if (!langpack.vstrings.v.isEmpty()) {
current.applyDifference(langpack);
Local::writeLangPack();
} else {
LOG(("Lang Info: Up to date."));
}
}
void Instance::Private::switchLangPackId(const QString &id) {
auto &current = Lang::Current();
if (current.id() != id) {
current = Lang::Instance(id, Lang::Instance::CreateFromIdTag());
restart(maindc());
}
}
void Instance::Private::restart() {
for (auto &session : _sessions) {
session.second->restart();
@ -477,7 +419,9 @@ void Instance::Private::killSession(ShiftedDcId shiftedDcId) {
_sessions.emplace(_mainDcId, std::move(main));
_mainSession->start();
}
QMetaObject::invokeMethod(_instance, "onClearKilledSessions", Qt::QueuedConnection);
InvokeQueued(_instance, [this] {
clearKilledSessions();
});
}
void Instance::Private::clearKilledSessions() {
@ -493,6 +437,11 @@ void Instance::Private::stopSession(ShiftedDcId shiftedDcId) {
}
}
void Instance::Private::reInitConnection(DcId dcId) {
killSession(dcId);
getSession(dcId)->notifyLayerInited(false);
}
void Instance::Private::logout(RPCDoneHandlerPtr onDone, RPCFailHandlerPtr onFail) {
_instance->send(MTPauth_LogOut(), onDone, onFail);
@ -1333,14 +1282,6 @@ void Instance::requestCDNConfig() {
_private->requestCDNConfig();
}
void Instance::requestLangPackDifference() {
_private->requestLangPackDifference();
}
void Instance::applyLangPackDifference(const MTPLangPackDifference &difference) {
_private->applyLangPackDifference(difference);
}
void Instance::connectionFinished(internal::Connection *connection) {
_private->connectionFinished(connection);
}
@ -1381,6 +1322,10 @@ void Instance::stopSession(ShiftedDcId shiftedDcId) {
_private->stopSession(shiftedDcId);
}
void Instance::reInitConnection(DcId dcId) {
_private->reInitConnection(dcId);
}
void Instance::logout(RPCDoneHandlerPtr onDone, RPCFailHandlerPtr onFail) {
_private->logout(onDone, onFail);
}
@ -1489,10 +1434,6 @@ void Instance::onKeyDestroyed(qint32 shiftedDcId) {
_private->completedKeyDestroy(shiftedDcId);
}
void Instance::onClearKilledSessions() {
_private->clearKilledSessions();
}
Instance::~Instance() {
_private->prepareToDestroy();
}

View File

@ -89,6 +89,7 @@ public:
int32 state(mtpRequestId requestId); // < 0 means waiting for such count of ms
void killSession(ShiftedDcId shiftedDcId);
void stopSession(ShiftedDcId shiftedDcId);
void reInitConnection(DcId dcId);
void logout(RPCDoneHandlerPtr onDone, RPCFailHandlerPtr onFail);
internal::DcenterPtr getDcById(ShiftedDcId shiftedDcId);
@ -122,8 +123,6 @@ public:
void requestConfig();
void requestCDNConfig();
void requestLangPackDifference();
void applyLangPackDifference(const MTPLangPackDifference &difference);
~Instance();
@ -138,7 +137,6 @@ signals:
private slots:
void onKeyDestroyed(qint32 shiftedDcId);
void onClearKilledSessions();
private:
internal::Session *getSession(ShiftedDcId shiftedDcId);

View File

@ -288,13 +288,16 @@ public:
SentRequestWrap request(mtpRequestId requestId) noexcept WARN_UNUSED_RESULT;
void requestSendDelayed() {
MTP::sendAnything();
_instance->sendAnything();
}
void requestCancellingDiscard() {
for (auto &request : _requests) {
request.handled();
}
}
gsl::not_null<Instance*> requestMTP() const {
return _instance;
}
private:
class RequestWrap {

View File

@ -34,6 +34,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "boxes/about_box.h"
#include "core/file_utilities.h"
#include "lang/lang_file_parser.h"
#include "lang/lang_cloud_manager.h"
#include "messenger.h"
#include "autoupdater.h"
namespace Settings {
@ -220,7 +222,7 @@ void GeneralWidget::chooseCustomLang() {
save = result.value(lng_box_ok, Lang::GetOriginalValue(lng_box_ok)),
cancel = result.value(lng_cancel, Lang::GetOriginalValue(lng_cancel));
Ui::show(Box<ConfirmBox>(text, save, cancel, base::lambda_guarded(this, [this, filePath] {
Lang::Current() = Lang::Instance(filePath, Lang::Instance::CreateFromCustomFileTag());
Lang::Current().switchToCustomFile(filePath);
Local::writeLangPack();
onRestart();
})));
@ -233,9 +235,19 @@ void GeneralWidget::chooseCustomLang() {
void GeneralWidget::onChangeLanguage() {
if ((_changeLanguage->clickModifiers() & Qt::ShiftModifier) && (_changeLanguage->clickModifiers() & Qt::AltModifier)) {
chooseCustomLang();
return;
}
auto manager = Messenger::Instance().langCloudManager();
if (manager->languageList().isEmpty()) {
_languagesLoadedSubscription = subscribe(manager->languageListChanged(), [this] {
unsubscribe(base::take(_languagesLoadedSubscription));
Ui::show(Box<LanguageBox>());
});
} else {
unsubscribe(base::take(_languagesLoadedSubscription));
Ui::show(Box<LanguageBox>());
}
manager->requestLanguageList();
}
void GeneralWidget::onRestart() {

View File

@ -117,6 +117,8 @@ private:
object_ptr<Ui::WidgetSlideWrap<Ui::Checkbox>> _startMinimized = { nullptr };
object_ptr<Ui::Checkbox> _addInSendTo = { nullptr };
int _languagesLoadedSubscription = 0;
};
} // namespace Settings

View File

@ -177,6 +177,8 @@
<(src_loc)/intro/introsignup.h
<(src_loc)/intro/introstart.cpp
<(src_loc)/intro/introstart.h
<(src_loc)/lang/lang_cloud_manager.cpp
<(src_loc)/lang/lang_cloud_manager.h
<(src_loc)/lang/lang_file_parser.cpp
<(src_loc)/lang/lang_file_parser.h
<(src_loc)/lang/lang_instance.cpp