diff --git a/Telegram/SourceFiles/ui/boxes/country_select_box.cpp b/Telegram/SourceFiles/ui/boxes/country_select_box.cpp index 5f7964fb0..cf4bd93e8 100644 --- a/Telegram/SourceFiles/ui/boxes/country_select_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/country_select_box.cpp @@ -40,7 +40,7 @@ public: void refresh(); - [[nodiscard]] rpl::producer countryChosen() const { + [[nodiscard]] rpl::producer countryChosen() const { return _countryChosen.events(); } @@ -64,7 +64,7 @@ private: void updateSelectedRow(); void updateRow(int index); void setPressed(int pressed); - const std::vector> ¤t() const; + const std::vector ¤t() const; Type _type = Type::Phones; int _rowHeight = 0; @@ -76,12 +76,12 @@ private: std::vector> _ripples; - std::vector> _list; - std::vector> _filtered; + std::vector _list; + std::vector _filtered; base::flat_map> _byLetter; std::vector> _namesList; - rpl::event_stream _countryChosen; + rpl::event_stream _countryChosen; rpl::event_stream _mustScrollTo; }; @@ -98,6 +98,16 @@ CountrySelectBox::CountrySelectBox(QWidget*, const QString &iso, Type type) rpl::producer CountrySelectBox::countryChosen() const { Expects(_ownedInner != nullptr || _inner != nullptr); + return (_ownedInner + ? _ownedInner.data() + : _inner.data())->countryChosen() | rpl::map([](const Entry &e) { + return e.iso2; + }); +} + +rpl::producer CountrySelectBox::entryChosen() const { + Expects(_ownedInner != nullptr || _inner != nullptr); + return (_ownedInner ? _ownedInner.data() : _inner.data())->countryChosen(); @@ -180,25 +190,36 @@ CountrySelectBox::Inner::Inner( LastValidISO = iso; } + const auto extractEntries = [&](const Countries::Info &info) { + for (const auto &code : info.codes) { + _list.push_back(Entry{ + .country = info.name, + .iso2 = info.iso2, + .code = code.callingCode, + .alternativeName = info.alternativeName, + }); + } + }; + _list.reserve(byISO2.size()); _namesList.reserve(byISO2.size()); const auto l = byISO2.constFind(LastValidISO); const auto lastValid = (l != byISO2.cend()) ? (*l) : nullptr; if (lastValid) { - _list.emplace_back(lastValid); + extractEntries(*lastValid); } for (const auto &entry : Countries::Instance().list()) { if (&entry != lastValid) { - _list.emplace_back(&entry); + extractEntries(entry); } } auto index = 0; for (const auto info : _list) { - auto full = info->name + auto full = info.country + ' ' - + (!info->alternativeName.isEmpty() - ? info->alternativeName + + (!info.alternativeName.isEmpty() + ? info.alternativeName : QString()); const auto namesList = std::move(full).toLower().split( QRegularExpression("[\\s\\-]"), @@ -256,10 +277,10 @@ void CountrySelectBox::Inner::paintEvent(QPaintEvent *e) { } } - auto code = QString("+") + list[i]->codes.front().callingCode; + auto code = QString("+") + list[i].code; auto codeWidth = st::countryRowCodeFont->width(code); - auto name = list[i]->name; + auto name = list[i].country; auto nameWidth = st::countryRowNameFont->width(name); auto availWidth = width() - st::countryRowPadding.left() - st::countryRowPadding.right() - codeWidth - st::boxScroll.width; if (nameWidth > availWidth) { @@ -399,9 +420,9 @@ void CountrySelectBox::Inner::selectSkipPage(int32 h, int32 dir) { void CountrySelectBox::Inner::chooseCountry() { const auto &list = current(); - _countryChosen.fire((_selected >= 0 && _selected < list.size()) - ? QString(list[_selected]->iso2) - : QString()); + _countryChosen.fire_copy((_selected >= 0 && _selected < list.size()) + ? list[_selected] + : Entry()); } void CountrySelectBox::Inner::refresh() { @@ -424,7 +445,7 @@ void CountrySelectBox::Inner::updateSelected(QPoint localPos) { } auto CountrySelectBox::Inner::current() const --> const std::vector> & { +-> const std::vector & { return _filter.isEmpty() ? _list : _filtered; } diff --git a/Telegram/SourceFiles/ui/boxes/country_select_box.h b/Telegram/SourceFiles/ui/boxes/country_select_box.h index feafada74..c36a6c74f 100644 --- a/Telegram/SourceFiles/ui/boxes/country_select_box.h +++ b/Telegram/SourceFiles/ui/boxes/country_select_box.h @@ -25,11 +25,18 @@ public: Phones, Countries, }; + struct Entry { + QString country; + QString iso2; + QString code; + QString alternativeName; + }; CountrySelectBox(QWidget*); CountrySelectBox(QWidget*, const QString &iso, Type type); [[nodiscard]] rpl::producer countryChosen() const; + [[nodiscard]] rpl::producer entryChosen() const; protected: void prepare() override; diff --git a/Telegram/SourceFiles/ui/countryinput.cpp b/Telegram/SourceFiles/ui/countryinput.cpp index 3050ecbcb..962bfc5be 100644 --- a/Telegram/SourceFiles/ui/countryinput.cpp +++ b/Telegram/SourceFiles/ui/countryinput.cpp @@ -92,10 +92,33 @@ void CountryInput::mouseMoveEvent(QMouseEvent *e) { void CountryInput::mousePressEvent(QMouseEvent *e) { mouseMoveEvent(e); if (_active) { - auto box = Ui::show(Box()); - box->countryChosen( - ) | rpl::start_with_next([=](QString iso) { - chooseCountry(iso); + const auto box = Ui::show(Box()); + box->entryChosen( + ) | rpl::start_with_next([=]( + const Ui::CountrySelectBox::Entry &entry) { + if (box) { + box->closeBox(); + } + + const auto &list = Countries::Instance().list(); + auto index = 0; + const auto infoIt = ranges::find( + list, + entry.iso2, + &Countries::Info::iso2); + if (infoIt == end(list)) { + return; + } + const auto info = *infoIt; + const auto it = ranges::find( + info.codes, + entry.code, + &Countries::CallingCodeInfo::callingCode); + if (it != end(info.codes)) { + chooseCountry( + &info, + std::distance(begin(info.codes), it)); + } }, lifetime()); } } @@ -130,23 +153,27 @@ void CountryInput::onChooseCode(const QString &code) { } bool CountryInput::chooseCountry(const QString &iso) { - Ui::hideLayer(); - const auto &byISO2 = Countries::Instance().byISO2(); const auto i = byISO2.constFind(iso); const auto info = (i != byISO2.cend()) ? (*i) : nullptr; _chosenIso = QString(); if (info) { - _chosenIso = LastValidISO = info->iso2; - setText(info->name); - codeChanged(info->codes.front().callingCode); - update(); + chooseCountry(info, 0); return true; } return false; } +void CountryInput::chooseCountry( + not_null info, + int codeIndex) { + _chosenIso = LastValidISO = info->iso2; + setText(info->name); + codeChanged(info->codes[codeIndex].callingCode); + update(); +} + void CountryInput::setText(const QString &newText) { _text = _st.font->elided(newText, width() - _st.textMargins.left() - _st.textMargins.right()); } diff --git a/Telegram/SourceFiles/ui/countryinput.h b/Telegram/SourceFiles/ui/countryinput.h index 7214a5d98..5e7069935 100644 --- a/Telegram/SourceFiles/ui/countryinput.h +++ b/Telegram/SourceFiles/ui/countryinput.h @@ -14,6 +14,10 @@ namespace Data { struct Info; } // namespace Data +namespace Countries { +struct Info; +} // namespace Countries + namespace Ui { class MultiSelect; class RippleAnimation; @@ -44,6 +48,7 @@ protected: void leaveEventHook(QEvent *e) override; private: + void chooseCountry(not_null info, int codeIndex); void setText(const QString &newText); const style::InputField &_st;