diff --git a/Telegram/SourceFiles/boxes/language_box.cpp b/Telegram/SourceFiles/boxes/language_box.cpp index 9ade20a39e..c116430891 100644 --- a/Telegram/SourceFiles/boxes/language_box.cpp +++ b/Telegram/SourceFiles/boxes/language_box.cpp @@ -84,18 +84,9 @@ void LanguageBox::Inner::refresh() { void LanguageBox::Inner::languageChanged(int languageIndex) { Expects(languageIndex >= 0 && languageIndex < _languages->size()); - auto currentId = Lang::Current().id(); + activateCurrent(); auto languageId = (*_languages)[languageIndex].id; - if (languageId == currentId) { - return; - } - - if (languageId == qsl("custom")) { - activateCurrent(); - Lang::Current().chooseCustomFile(); - } else { - Lang::CurrentCloudManager().switchToLanguage(languageId); - } + Lang::CurrentCloudManager().switchToLanguage(languageId); } void LanguageBox::Inner::activateCurrent() { diff --git a/Telegram/SourceFiles/intro/introphone.h b/Telegram/SourceFiles/intro/introphone.h index 2f1ae2ed45..9cdd9df3c4 100644 --- a/Telegram/SourceFiles/intro/introphone.h +++ b/Telegram/SourceFiles/intro/introphone.h @@ -53,10 +53,6 @@ public: protected: void resizeEvent(QResizeEvent *e) override; - bool hasChangeLanguageNoCover() const override { - return true; - } - private slots: void onInputChange(); void onCheckRequest(); diff --git a/Telegram/SourceFiles/intro/intropwdcheck.cpp b/Telegram/SourceFiles/intro/intropwdcheck.cpp index 555bd2f536..4748e5df4a 100644 --- a/Telegram/SourceFiles/intro/intropwdcheck.cpp +++ b/Telegram/SourceFiles/intro/intropwdcheck.cpp @@ -69,6 +69,9 @@ PwdCheckWidget::PwdCheckWidget(QWidget *parent, Widget::Data *data) : Step(paren void PwdCheckWidget::refreshLang() { if (_toRecover) _toRecover->setText(lang(lng_signin_recover)); if (_toPassword) _toPassword->setText(lang(lng_signin_try_password)); + if (!_hint.isEmpty()) { + _pwdHint->setText(lng_signin_hint(lt_password_hint, _hint)); + } updateControlsGeometry(); } diff --git a/Telegram/SourceFiles/intro/introwidget.cpp b/Telegram/SourceFiles/intro/introwidget.cpp index 18f50e6a4d..0c59748ec4 100644 --- a/Telegram/SourceFiles/intro/introwidget.cpp +++ b/Telegram/SourceFiles/intro/introwidget.cpp @@ -113,7 +113,7 @@ void Widget::createLanguageLink() { _changeLanguage->entity()->setClickedCallback([this, languageId] { Lang::CurrentCloudManager().switchToLanguage(languageId); }); - _changeLanguage->toggleAnimated(getStep()->hasChangeLanguage()); + _changeLanguage->toggleAnimated(!_resetAccount); updateControlsGeometry(); }; @@ -189,7 +189,7 @@ void Widget::historyMove(Direction direction) { auto stepHasCover = getStep()->hasCover(); _settings->toggleAnimated(!stepHasCover); if (_update) _update->toggleAnimated(!stepHasCover); - if (_changeLanguage) _changeLanguage->toggleAnimated(getStep()->hasChangeLanguage()); + if (_changeLanguage) _changeLanguage->toggleAnimated(!_resetAccount); _next->setText([this] { return getStep()->nextButtonText(); }); if (_resetAccount) _resetAccount->hideAnimated(); getStep()->showAnimated(direction); @@ -238,6 +238,7 @@ void Widget::showResetButton() { updateControlsGeometry(); } _resetAccount->showAnimated(); + if (_changeLanguage) _changeLanguage->hideAnimated(); } void Widget::resetAccount() { @@ -298,7 +299,7 @@ void Widget::showControls() { auto hasCover = getStep()->hasCover(); _settings->toggleFast(!hasCover); if (_update) _update->toggleFast(!hasCover); - if (_changeLanguage) _changeLanguage->toggleFast(getStep()->hasChangeLanguage()); + if (_changeLanguage) _changeLanguage->toggleFast(!_resetAccount); _back->toggleFast(getStep()->hasBack()); } diff --git a/Telegram/SourceFiles/intro/introwidget.h b/Telegram/SourceFiles/intro/introwidget.h index 2fa647ab46..6cc3f2372f 100644 --- a/Telegram/SourceFiles/intro/introwidget.h +++ b/Telegram/SourceFiles/intro/introwidget.h @@ -111,9 +111,6 @@ public: bool animating() const; bool hasCover() const; - bool hasChangeLanguage() const { - return hasCover() || hasChangeLanguageNoCover(); - } virtual bool hasBack() const; virtual void activate(); virtual void cancelled(); @@ -164,9 +161,6 @@ public: void showResetButton() { if (_showResetCallback) _showResetCallback(); } - virtual bool hasChangeLanguageNoCover() const { - return false; - } private: struct CoverAnimation { diff --git a/Telegram/SourceFiles/lang/lang_cloud_manager.cpp b/Telegram/SourceFiles/lang/lang_cloud_manager.cpp index 72782ed88f..6c76397122 100644 --- a/Telegram/SourceFiles/lang/lang_cloud_manager.cpp +++ b/Telegram/SourceFiles/lang/lang_cloud_manager.cpp @@ -27,6 +27,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "apiwrap.h" #include "auth_session.h" #include "boxes/confirm_box.h" +#include "lang/lang_file_parser.h" +#include "core/file_utilities.h" namespace Lang { @@ -87,6 +89,9 @@ void CloudManager::applyLangPackDifference(const MTPLangPackDifference &differen auto langpackId = qs(langpack.vlang_code); if (needToApplyLangPack(langpackId)) { applyLangPackData(langpack); + if (_restartAfterSwitch) { + App::restart(); + } } else { LOG(("Lang Warning: Ignoring update for '%1' because our language is '%2'").arg(langpackId).arg(_langpack.id())); } @@ -152,17 +157,13 @@ bool CloudManager::showOfferSwitchBox() { if (_offerSwitchToId.isEmpty()) { return; } - if (_offerSwitchToData) { - t_assert(_offerSwitchToData->type() == mtpc_langPackDifference); - applyLangPackData(base::take(_offerSwitchToData)->c_langPackDifference()); - } else { - switchToLanguage(_offerSwitchToId); - } + request(_langPackRequestId).cancel(); + performSwitchAndRestart(_offerSwitchToId); }, [this] { Ui::hideLayer(); changeIdAndReInitConnection(DefaultLanguageId()); Local::writeLangPack(); - })); + }), KeepOtherLayers); return true; } @@ -178,11 +179,108 @@ void CloudManager::applyLangPackData(const MTPDlangPackDifference &data) { } } -void CloudManager::switchToLanguage(const QString &id) { +bool CloudManager::canApplyWithoutRestart(const QString &id) const { + if (id == qstr("TEST_X") || id == qstr("TEST_0")) { + return true; + } + + // We don't support instant language switch if the auth session exists :( + return !AuthSession::Exists(); +} + +void CloudManager::resetToDefault() { + performSwitch(DefaultLanguageId()); +} + +void CloudManager::switchToLanguage(QString id) { + if (id.isEmpty()) { + id = DefaultLanguageId(); + } + if (_langpack.id() == id) { + return; + } + + request(_switchingToLanguageRequest).cancel(); + if (id == qstr("custom")) { + performSwitchToCustom(); + } else if (canApplyWithoutRestart(id)) { + performSwitch(id); + } else { + QVector keys; + keys.reserve(3); + keys.push_back(MTP_string("lng_sure_save_language")); + keys.push_back(MTP_string("lng_box_ok")); + keys.push_back(MTP_string("lng_cancel")); + _switchingToLanguageRequest = request(MTPlangpack_GetStrings(MTP_string(id), MTP_vector(std::move(keys)))).done([this, id](const MTPVector &result) { + auto values = Instance::ParseStrings(result); + auto getValue = [&values](LangKey key) { + auto it = values.find(key); + return (it == values.cend()) ? GetOriginalValue(key) : it->second; + }; + auto text = getValue(lng_sure_save_language); + auto save = getValue(lng_box_ok); + auto cancel = getValue(lng_cancel); + Ui::show(Box(text, save, cancel, [this, id] { + performSwitchAndRestart(id); + }), KeepOtherLayers); + }).send(); + } +} + +void CloudManager::performSwitchToCustom() { + auto filter = qsl("Language files (*.strings)"); + auto title = qsl("Choose language .strings file"); + FileDialog::GetOpenPath(title, filter, [weak = base::weak_unique_ptr(this)](const FileDialog::OpenResult &result) { + if (!weak || result.paths.isEmpty()) { + return; + } + + auto filePath = result.paths.front(); + Lang::FileParser loader(filePath, { lng_sure_save_language, lng_box_ok, lng_cancel }); + if (loader.errors().isEmpty()) { + weak->request(weak->_switchingToLanguageRequest).cancel(); + if (weak->canApplyWithoutRestart(qsl("custom"))) { + weak->_langpack.switchToCustomFile(filePath); + } else { + auto values = loader.found(); + auto getValue = [&values](LangKey key) { + auto it = values.find(key); + return (it == values.cend()) ? GetOriginalValue(key) : it.value(); + }; + auto text = getValue(lng_sure_save_language); + auto save = getValue(lng_box_ok); + auto cancel = getValue(lng_cancel); + Ui::show(Box(text, save, cancel, [weak, filePath] { + weak->_langpack.switchToCustomFile(filePath); + App::restart(); + }), KeepOtherLayers); + } + } else { + Ui::show(Box("Custom lang failed :(\n\nError: " + loader.errors()), KeepOtherLayers); + } + }); +} + +void CloudManager::switchToTestLanguage() { + auto testLanguageId = (_langpack.id() == qstr("TEST_X")) ? qsl("TEST_0") : qsl("TEST_X"); + performSwitch(testLanguageId); +} + +void CloudManager::performSwitch(const QString &id) { + _restartAfterSwitch = false; switchLangPackId(id); requestLangPackDifference(); } +void CloudManager::performSwitchAndRestart(const QString &id) { + performSwitch(id); + if (_langPackRequestId) { + _restartAfterSwitch = true; + } else { + App::restart(); + } +} + void CloudManager::switchLangPackId(const QString &id) { auto currentId = _langpack.id(); auto notChanged = (currentId == id) || (currentId.isEmpty() && id == DefaultLanguageId()); diff --git a/Telegram/SourceFiles/lang/lang_cloud_manager.h b/Telegram/SourceFiles/lang/lang_cloud_manager.h index ff02f20958..d1acdefdd1 100644 --- a/Telegram/SourceFiles/lang/lang_cloud_manager.h +++ b/Telegram/SourceFiles/lang/lang_cloud_manager.h @@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #pragma once #include "mtproto/sender.h" +#include "base/weak_unique_ptr.h" namespace MTP { class Instance; @@ -30,7 +31,7 @@ namespace Lang { class Instance; -class CloudManager : private MTP::Sender, private base::Subscriber { +class CloudManager : public base::enable_weak_from_this, private MTP::Sender, private base::Subscriber { public: CloudManager(Instance &langpack, gsl::not_null mtproto); @@ -50,7 +51,9 @@ public: void requestLangPackDifference(); void applyLangPackDifference(const MTPLangPackDifference &difference); - void switchToLanguage(const QString &id); + void resetToDefault(); + void switchToLanguage(QString id); + void switchToTestLanguage(); void setSuggestedLanguage(const QString &langCode); QString suggestedLanguage() const { return _suggestedLanguage; @@ -60,6 +63,10 @@ public: } private: + bool canApplyWithoutRestart(const QString &id) const; + void performSwitchToCustom(); + void performSwitch(const QString &id); + void performSwitchAndRestart(const QString &id); void offerSwitchLangPack(); bool showOfferSwitchBox(); QString findOfferedLanguageName(); @@ -76,12 +83,14 @@ private: mtpRequestId _languagesRequestId = 0; QString _offerSwitchToId; - std::unique_ptr _offerSwitchToData; + bool _restartAfterSwitch = false; QString _suggestedLanguage; bool _languageWasSuggested = false; base::Observable _firstLanguageSuggestion; + mtpRequestId _switchingToLanguageRequest = 0; + }; inline bool operator==(const CloudManager::Language &a, const CloudManager::Language &b) { diff --git a/Telegram/SourceFiles/lang/lang_instance.cpp b/Telegram/SourceFiles/lang/lang_instance.cpp index 53d57f0b05..49c8e89557 100644 --- a/Telegram/SourceFiles/lang/lang_instance.cpp +++ b/Telegram/SourceFiles/lang/lang_instance.cpp @@ -21,12 +21,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "lang/lang_instance.h" #include "messenger.h" -#include "lang/lang_file_parser.h" #include "storage/serialize_common.h" #include "storage/localstorage.h" #include "platform/platform_specific.h" -#include "core/file_utilities.h" #include "boxes/confirm_box.h" +#include "lang/lang_file_parser.h" namespace Lang { namespace { @@ -262,24 +261,6 @@ void Instance::switchToId(const QString &id) { } } -void Instance::chooseCustomFile() { - auto filter = qsl("Language files (*.strings)"); - auto title = qsl("Choose language .strings file"); - FileDialog::GetOpenPath(title, filter, [weak = base::weak_unique_ptr(this)](const FileDialog::OpenResult &result) { - if (!weak || result.paths.isEmpty()) { - return; - } - - auto filePath = result.paths.front(); - Lang::FileParser loader(filePath, { lng_language_name }); - if (loader.errors().isEmpty()) { - weak->switchToCustomFile(filePath); - } else { - Ui::show(Box("Custom lang failed :(\n\nError: " + loader.errors())); - } - }); -} - void Instance::switchToCustomFile(const QString &filePath) { reset(); fillFromCustomFile(filePath); @@ -319,7 +300,6 @@ QString Instance::systemLangCode() const { _systemLanguage = DefaultLanguageId(); } } - _systemLanguage = "de"; // TESTING } return _systemLanguage; } diff --git a/Telegram/SourceFiles/lang/lang_instance.h b/Telegram/SourceFiles/lang/lang_instance.h index f32b8a940a..91277e7178 100644 --- a/Telegram/SourceFiles/lang/lang_instance.h +++ b/Telegram/SourceFiles/lang/lang_instance.h @@ -34,13 +34,12 @@ QString DefaultLanguageId(); class Instance; Instance &Current(); -class Instance : public base::enable_weak_from_this { +class Instance { public: Instance() { fillDefaults(); } void switchToId(const QString &id); - void chooseCustomFile(); void switchToCustomFile(const QString &filePath); Instance(const Instance &other) = delete; diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index 2aa41056ba..da585be158 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -71,9 +71,7 @@ void FeedLangTestingKey(int key) { } if (codeState == 4) { codeState = 0; - - auto testLanguageId = (Lang::Current().id() == qstr("TEST_X")) ? qsl("TEST_0") : qsl("TEST_X"); - Lang::CurrentCloudManager().switchToLanguage(testLanguageId); + Lang::CurrentCloudManager().switchToTestLanguage(); } } diff --git a/Telegram/SourceFiles/mtproto/mtp_instance.cpp b/Telegram/SourceFiles/mtproto/mtp_instance.cpp index 5f7e95f55e..ab8cd146eb 100644 --- a/Telegram/SourceFiles/mtproto/mtp_instance.cpp +++ b/Telegram/SourceFiles/mtproto/mtp_instance.cpp @@ -1085,7 +1085,7 @@ bool Instance::Private::onErrorDefault(mtpRequestId requestId, const RPCError &e } return true; } else if (err == qstr("CONNECTION_LANG_CODE_INVALID")) { - Lang::CurrentCloudManager().switchToLanguage(qsl("en")); + Lang::CurrentCloudManager().resetToDefault(); } else if (err == qstr("MSG_WAIT_FAILED")) { mtpRequest request; { diff --git a/Telegram/SourceFiles/settings/settings_general_widget.cpp b/Telegram/SourceFiles/settings/settings_general_widget.cpp index e8dfcc1dc8..abbd908075 100644 --- a/Telegram/SourceFiles/settings/settings_general_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_general_widget.cpp @@ -207,7 +207,7 @@ void GeneralWidget::refreshControls() { void GeneralWidget::onChangeLanguage() { if ((_changeLanguage->clickModifiers() & Qt::ShiftModifier) && (_changeLanguage->clickModifiers() & Qt::AltModifier)) { - Lang::Current().chooseCustomFile(); + Lang::CurrentCloudManager().switchToLanguage(qsl("custom")); return; } auto manager = Messenger::Instance().langCloudManager(); diff --git a/Telegram/SourceFiles/settings/settings_widget.cpp b/Telegram/SourceFiles/settings/settings_widget.cpp index 62a1cb8461..bb93c2c0d4 100644 --- a/Telegram/SourceFiles/settings/settings_widget.cpp +++ b/Telegram/SourceFiles/settings/settings_widget.cpp @@ -33,6 +33,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "storage/localstorage.h" #include "boxes/confirm_box.h" #include "lang/lang_keys.h" +#include "lang/lang_cloud_manager.h" #include "messenger.h" #include "mtproto/mtp_instance.h" #include "mtproto/dc_options.h" @@ -61,7 +62,7 @@ void fillCodes() { })); }); Codes.insert(qsl("loadlang"), [] { - Lang::Current().chooseCustomFile(); + Lang::CurrentCloudManager().switchToLanguage(qsl("custom")); }); Codes.insert(qsl("debugfiles"), [] { if (!cDebug()) return; diff --git a/Telegram/SourceFiles/ui/widgets/input_fields.cpp b/Telegram/SourceFiles/ui/widgets/input_fields.cpp index bc12f5af8b..b17a72f279 100644 --- a/Telegram/SourceFiles/ui/widgets/input_fields.cpp +++ b/Telegram/SourceFiles/ui/widgets/input_fields.cpp @@ -1335,7 +1335,7 @@ void FlatTextarea::refreshPlaceholder() { auto skipWidth = placeholderSkipWidth(); auto placeholderText = _placeholderFactory ? _placeholderFactory() : QString(); _placeholder = _st.font->elided(placeholderText, width() - _st.textMrg.left() - _st.textMrg.right() - _st.phPos.x() - 1 - skipWidth); - if (_placeholderVisible) update(); + update(); } void FlatTextarea::updatePlaceholder() { @@ -2477,12 +2477,12 @@ void InputArea::refreshPlaceholder() { } else { _placeholder = _st.placeholderFont->elided(placeholderText, availableWidth); } + update(); } void InputArea::setPlaceholder(base::lambda placeholderFactory) { _placeholderFactory = std::move(placeholderFactory); refreshPlaceholder(); - update(); } void InputArea::showError() { @@ -3243,12 +3243,12 @@ void InputField::refreshPlaceholder() { } else { _placeholder = _st.placeholderFont->elided(placeholderText, availableWidth); } + update(); } void InputField::setPlaceholder(base::lambda placeholderFactory) { _placeholderFactory = std::move(placeholderFactory); refreshPlaceholder(); - update(); } void InputField::showError() { @@ -3534,12 +3534,12 @@ void MaskedInputField::refreshPlaceholder() { } else { _placeholder = _st.placeholderFont->elided(placeholderText, availableWidth); } + update(); } void MaskedInputField::setPlaceholder(base::lambda placeholderFactory) { _placeholderFactory = std::move(placeholderFactory); refreshPlaceholder(); - update(); } void MaskedInputField::contextMenuEvent(QContextMenuEvent *e) {