diff --git a/Telegram/SourceFiles/boxes/language_box.cpp b/Telegram/SourceFiles/boxes/language_box.cpp index 1001c63833..99f496c7fc 100644 --- a/Telegram/SourceFiles/boxes/language_box.cpp +++ b/Telegram/SourceFiles/boxes/language_box.cpp @@ -1141,15 +1141,16 @@ void LanguageBox::prepare() { label->fire(Ui::Translate::LocalesFromSettings()); translateSkip->setClickedCallback([=] { Ui::BoxShow(this).showBox( - Box(Ui::ChooseLanguageBox, [=](QLocale locale) { - label->fire({ locale }); - const auto result = (locale.language() == QLocale::English) - ? QLocale::c() - : locale; - Core::App().settings().setSkipTranslationForLanguages( - { result.language() }); + Box(Ui::ChooseLanguageBox, [=](std::vector locales) { + label->fire_copy(locales); + const auto result = ranges::views::all( + locales + ) | ranges::views::transform([](const QLocale &l) { + return int(l.language()); + }) | ranges::to_vector; + Core::App().settings().setSkipTranslationForLanguages(result); Core::App().saveSettingsDelayed(); - }), + }, Ui::Translate::LocalesFromSettings()), Ui::LayerOption::KeepOther); }); Settings::AddSkip(topContainer); diff --git a/Telegram/SourceFiles/boxes/translate_box.cpp b/Telegram/SourceFiles/boxes/translate_box.cpp index 1251180071..e98ec17be0 100644 --- a/Telegram/SourceFiles/boxes/translate_box.cpp +++ b/Telegram/SourceFiles/boxes/translate_box.cpp @@ -21,12 +21,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #endif #include "ui/effects/loading_element.h" #include "ui/layers/generic_box.h" +#include "ui/painter.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" +#include "ui/widgets/multi_select.h" #include "ui/wrap/fade_wrap.h" #include "ui/wrap/slide_wrap.h" #include "styles/style_boxes.h" #include "styles/style_chat_helpers.h" +#include "styles/style_info.h" // inviteLinkListItem. #include "styles/style_layers.h" #include "styles/style_settings.h" // settingsSubsectionTitlePadding. @@ -80,7 +83,84 @@ namespace { }; } -class ShowButton : public RpWidget { +class Row final : public Ui::SettingsButton { +public: + Row(not_null parent, const QLocale &locale); + + [[nodiscard]] bool filtered(const QString &query) const; + [[nodiscard]] QLocale locale() const; + + int resizeGetHeight(int newWidth) override; + +protected: + void paintEvent(QPaintEvent *e) override; + +private: + const style::PeerListItem &_st; + const QLocale _locale; + const QString _status; + const QString _titleText; + Ui::Text::String _title; + +}; + +Row::Row(not_null parent, const QLocale &locale) +: SettingsButton(parent, rpl::never()) +, _st(st::inviteLinkListItem) +, _locale(locale) +, _status(QLocale::languageToString(locale.language())) +, _titleText(LanguageName(locale)) +, _title(_st.nameStyle, _titleText) { +} + +QLocale Row::locale() const { + return _locale; +} + +bool Row::filtered(const QString &query) const { + return _status.startsWith(query, Qt::CaseInsensitive) + || _titleText.startsWith(query, Qt::CaseInsensitive); +} + +int Row::resizeGetHeight(int newWidth) { + return _st.height; +} + +void Row::paintEvent(QPaintEvent *e) { + auto p = Painter(this); + + const auto paintOver = (isOver() || isDown()) && !isDisabled(); + Ui::SettingsButton::paintBg(p, e->rect(), paintOver); + Ui::SettingsButton::paintRipple(p, 0, 0); + Ui::SettingsButton::paintToggle(p, width()); + + const auto &color = st::windowSubTextFg; + p.setPen(Qt::NoPen); + p.setBrush(color); + + const auto left = st::settingsSubsectionTitlePadding.left(); + const auto toggleRect = Ui::SettingsButton::maybeToggleRect(); + const auto right = left + + (toggleRect.isEmpty() ? 0 : (width() - toggleRect.x())); + + p.setPen(_st.nameFg); + _title.drawLeft( + p, + left, + _st.namePosition.y(), + width() - left - right, + width() - left - right); + + p.setPen(paintOver ? _st.statusFgOver : _st.statusFg); + p.setFont(st::contactsStatusFont); + p.drawTextLeft( + left, + _st.statusPosition.y(), + width() - left - right, + _status); +} + +class ShowButton final : public RpWidget { public: ShowButton(not_null parent); @@ -157,6 +237,8 @@ QString LanguageName(const QLocale &locale) { && (locale.country() == QLocale::UnitedStates || locale.country() == QLocale::AnyCountry)) { return u"English"_q; + } else if (locale.language() == QLocale::Spanish) { + return QString::fromUtf8("\x45\x73\x70\x61\xc3\xb1\x6f\x6c"); } else { const auto name = locale.nativeLanguageName(); return name.left(1).toUpper() + name.mid(1); @@ -318,28 +400,96 @@ void TranslateBox( if (loading->toggled()) { return; } - Ui::BoxShow(box).showBox(Box(ChooseLanguageBox, [=](QLocale locale) { + Ui::BoxShow(box).showBox(Box(ChooseLanguageBox, [=]( + std::vector locales) { + const auto &locale = locales.front(); state->locale.fire_copy(locale); loading->show(anim::type::instant); translated->hide(anim::type::instant); send(locale.name().mid(0, 2)); - })); + }, std::vector())); }); - } void ChooseLanguageBox( not_null box, - Fn callback) { + Fn)> callback, + std::vector toggled) { + box->setMinHeight(st::boxWidth); + box->setMaxHeight(st::boxWidth); box->setTitle(tr::lng_languages()); - for (const auto &lang : Languages()) { + + const auto hasToggled = !toggled.empty(); + + const auto multiSelect = box->setPinnedToTopContent( + object_ptr( + box, + st::defaultMultiSelect, + tr::lng_participant_filter())); + box->setFocusCallback([=] { multiSelect->setInnerFocus(); }); + + const auto container = box->verticalLayout(); + const auto langs = Languages(); + auto rows = std::vector*>>(); + rows.reserve(langs.size()); + for (const auto &lang : langs) { const auto locale = QLocale(lang); - const auto button = Settings::AddButton( - box->verticalLayout(), - rpl::single(LanguageName(locale)), - st::defaultSettingsButton); - button->setClickedCallback([=] { - callback(locale); + const auto button = container->add( + object_ptr>( + container, + object_ptr(container, locale))); + if (hasToggled) { + button->entity()->toggleOn( + rpl::single(ranges::contains(toggled, locale)), + false); + } else { + button->entity()->setClickedCallback([=] { + callback({ locale }); + box->closeBox(); + }); + } + rows.push_back(button); + } + + multiSelect->setQueryChangedCallback([=](const QString &query) { + for (const auto &row : rows) { + const auto toggled = row->entity()->filtered(query); + if (toggled != row->toggled()) { + row->toggle(toggled, anim::type::instant); + } + } + }); + + { + const auto label = Ui::CreateChild( + box.get(), + tr::lng_languages_none(), + st::membersAbout); + box->verticalLayout()->geometryValue( + ) | rpl::start_with_next([=](const QRect &geometry) { + const auto shown = (geometry.height() <= 0); + label->setVisible(shown); + if (shown) { + label->moveToLeft( + (geometry.width() - label->width()) / 2, + geometry.y() + st::membersAbout.style.font->height * 4); + label->stackUnder(box->verticalLayout()); + } + }, label->lifetime()); + } + + if (hasToggled) { + box->addButton(tr::lng_settings_save(), [=] { + auto result = ranges::views::all( + rows + ) | ranges::views::filter([](const auto &row) { + return row->entity()->toggled(); + }) | ranges::views::transform([](const auto &row) { + return row->entity()->locale(); + }) | ranges::to_vector; + if (!result.empty()) { + callback(std::move(result)); + } box->closeBox(); }); } diff --git a/Telegram/SourceFiles/boxes/translate_box.h b/Telegram/SourceFiles/boxes/translate_box.h index 267d6a17f8..e417ebab74 100644 --- a/Telegram/SourceFiles/boxes/translate_box.h +++ b/Telegram/SourceFiles/boxes/translate_box.h @@ -29,6 +29,7 @@ void TranslateBox( void ChooseLanguageBox( not_null box, - Fn callback); + Fn)> callback, + std::vector toggled); } // namespace Ui diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 580e6a561f..f339dd3771 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 580e6a561f7d252a94888b54c206e06ac0237c38 +Subproject commit f339dd377100beaef79af8512c67a3c16f950c3f