Added all available calling codes on each country to CountrySelectBox.

This commit is contained in:
23rd 2021-09-02 21:41:31 +03:00 committed by John Preston
parent 45360adbc2
commit 48f7d715d6
4 changed files with 86 additions and 26 deletions

View file

@ -40,7 +40,7 @@ public:
void refresh(); void refresh();
[[nodiscard]] rpl::producer<QString> countryChosen() const { [[nodiscard]] rpl::producer<Entry> countryChosen() const {
return _countryChosen.events(); return _countryChosen.events();
} }
@ -64,7 +64,7 @@ private:
void updateSelectedRow(); void updateSelectedRow();
void updateRow(int index); void updateRow(int index);
void setPressed(int pressed); void setPressed(int pressed);
const std::vector<not_null<const Countries::Info*>> &current() const; const std::vector<Entry> &current() const;
Type _type = Type::Phones; Type _type = Type::Phones;
int _rowHeight = 0; int _rowHeight = 0;
@ -76,12 +76,12 @@ private:
std::vector<std::unique_ptr<RippleAnimation>> _ripples; std::vector<std::unique_ptr<RippleAnimation>> _ripples;
std::vector<not_null<const Countries::Info*>> _list; std::vector<Entry> _list;
std::vector<not_null<const Countries::Info*>> _filtered; std::vector<Entry> _filtered;
base::flat_map<QChar, std::vector<int>> _byLetter; base::flat_map<QChar, std::vector<int>> _byLetter;
std::vector<std::vector<QString>> _namesList; std::vector<std::vector<QString>> _namesList;
rpl::event_stream<QString> _countryChosen; rpl::event_stream<Entry> _countryChosen;
rpl::event_stream<ScrollToRequest> _mustScrollTo; rpl::event_stream<ScrollToRequest> _mustScrollTo;
}; };
@ -98,6 +98,16 @@ CountrySelectBox::CountrySelectBox(QWidget*, const QString &iso, Type type)
rpl::producer<QString> CountrySelectBox::countryChosen() const { rpl::producer<QString> CountrySelectBox::countryChosen() const {
Expects(_ownedInner != nullptr || _inner != nullptr); Expects(_ownedInner != nullptr || _inner != nullptr);
return (_ownedInner
? _ownedInner.data()
: _inner.data())->countryChosen() | rpl::map([](const Entry &e) {
return e.iso2;
});
}
rpl::producer<CountrySelectBox::Entry> CountrySelectBox::entryChosen() const {
Expects(_ownedInner != nullptr || _inner != nullptr);
return (_ownedInner return (_ownedInner
? _ownedInner.data() ? _ownedInner.data()
: _inner.data())->countryChosen(); : _inner.data())->countryChosen();
@ -180,25 +190,36 @@ CountrySelectBox::Inner::Inner(
LastValidISO = iso; 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()); _list.reserve(byISO2.size());
_namesList.reserve(byISO2.size()); _namesList.reserve(byISO2.size());
const auto l = byISO2.constFind(LastValidISO); const auto l = byISO2.constFind(LastValidISO);
const auto lastValid = (l != byISO2.cend()) ? (*l) : nullptr; const auto lastValid = (l != byISO2.cend()) ? (*l) : nullptr;
if (lastValid) { if (lastValid) {
_list.emplace_back(lastValid); extractEntries(*lastValid);
} }
for (const auto &entry : Countries::Instance().list()) { for (const auto &entry : Countries::Instance().list()) {
if (&entry != lastValid) { if (&entry != lastValid) {
_list.emplace_back(&entry); extractEntries(entry);
} }
} }
auto index = 0; auto index = 0;
for (const auto info : _list) { for (const auto info : _list) {
auto full = info->name auto full = info.country
+ ' ' + ' '
+ (!info->alternativeName.isEmpty() + (!info.alternativeName.isEmpty()
? info->alternativeName ? info.alternativeName
: QString()); : QString());
const auto namesList = std::move(full).toLower().split( const auto namesList = std::move(full).toLower().split(
QRegularExpression("[\\s\\-]"), 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 codeWidth = st::countryRowCodeFont->width(code);
auto name = list[i]->name; auto name = list[i].country;
auto nameWidth = st::countryRowNameFont->width(name); auto nameWidth = st::countryRowNameFont->width(name);
auto availWidth = width() - st::countryRowPadding.left() - st::countryRowPadding.right() - codeWidth - st::boxScroll.width; auto availWidth = width() - st::countryRowPadding.left() - st::countryRowPadding.right() - codeWidth - st::boxScroll.width;
if (nameWidth > availWidth) { if (nameWidth > availWidth) {
@ -399,9 +420,9 @@ void CountrySelectBox::Inner::selectSkipPage(int32 h, int32 dir) {
void CountrySelectBox::Inner::chooseCountry() { void CountrySelectBox::Inner::chooseCountry() {
const auto &list = current(); const auto &list = current();
_countryChosen.fire((_selected >= 0 && _selected < list.size()) _countryChosen.fire_copy((_selected >= 0 && _selected < list.size())
? QString(list[_selected]->iso2) ? list[_selected]
: QString()); : Entry());
} }
void CountrySelectBox::Inner::refresh() { void CountrySelectBox::Inner::refresh() {
@ -424,7 +445,7 @@ void CountrySelectBox::Inner::updateSelected(QPoint localPos) {
} }
auto CountrySelectBox::Inner::current() const auto CountrySelectBox::Inner::current() const
-> const std::vector<not_null<const Countries::Info*>> & { -> const std::vector<CountrySelectBox::Entry> & {
return _filter.isEmpty() ? _list : _filtered; return _filter.isEmpty() ? _list : _filtered;
} }

View file

@ -25,11 +25,18 @@ public:
Phones, Phones,
Countries, Countries,
}; };
struct Entry {
QString country;
QString iso2;
QString code;
QString alternativeName;
};
CountrySelectBox(QWidget*); CountrySelectBox(QWidget*);
CountrySelectBox(QWidget*, const QString &iso, Type type); CountrySelectBox(QWidget*, const QString &iso, Type type);
[[nodiscard]] rpl::producer<QString> countryChosen() const; [[nodiscard]] rpl::producer<QString> countryChosen() const;
[[nodiscard]] rpl::producer<Entry> entryChosen() const;
protected: protected:
void prepare() override; void prepare() override;

View file

@ -92,10 +92,33 @@ void CountryInput::mouseMoveEvent(QMouseEvent *e) {
void CountryInput::mousePressEvent(QMouseEvent *e) { void CountryInput::mousePressEvent(QMouseEvent *e) {
mouseMoveEvent(e); mouseMoveEvent(e);
if (_active) { if (_active) {
auto box = Ui::show(Box<Ui::CountrySelectBox>()); const auto box = Ui::show(Box<Ui::CountrySelectBox>());
box->countryChosen( box->entryChosen(
) | rpl::start_with_next([=](QString iso) { ) | rpl::start_with_next([=](
chooseCountry(iso); 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()); }, lifetime());
} }
} }
@ -130,23 +153,27 @@ void CountryInput::onChooseCode(const QString &code) {
} }
bool CountryInput::chooseCountry(const QString &iso) { bool CountryInput::chooseCountry(const QString &iso) {
Ui::hideLayer();
const auto &byISO2 = Countries::Instance().byISO2(); const auto &byISO2 = Countries::Instance().byISO2();
const auto i = byISO2.constFind(iso); const auto i = byISO2.constFind(iso);
const auto info = (i != byISO2.cend()) ? (*i) : nullptr; const auto info = (i != byISO2.cend()) ? (*i) : nullptr;
_chosenIso = QString(); _chosenIso = QString();
if (info) { if (info) {
_chosenIso = LastValidISO = info->iso2; chooseCountry(info, 0);
setText(info->name);
codeChanged(info->codes.front().callingCode);
update();
return true; return true;
} }
return false; return false;
} }
void CountryInput::chooseCountry(
not_null<const Countries::Info*> info,
int codeIndex) {
_chosenIso = LastValidISO = info->iso2;
setText(info->name);
codeChanged(info->codes[codeIndex].callingCode);
update();
}
void CountryInput::setText(const QString &newText) { void CountryInput::setText(const QString &newText) {
_text = _st.font->elided(newText, width() - _st.textMargins.left() - _st.textMargins.right()); _text = _st.font->elided(newText, width() - _st.textMargins.left() - _st.textMargins.right());
} }

View file

@ -14,6 +14,10 @@ namespace Data {
struct Info; struct Info;
} // namespace Data } // namespace Data
namespace Countries {
struct Info;
} // namespace Countries
namespace Ui { namespace Ui {
class MultiSelect; class MultiSelect;
class RippleAnimation; class RippleAnimation;
@ -44,6 +48,7 @@ protected:
void leaveEventHook(QEvent *e) override; void leaveEventHook(QEvent *e) override;
private: private:
void chooseCountry(not_null<const Countries::Info*> info, int codeIndex);
void setText(const QString &newText); void setText(const QString &newText);
const style::InputField &_st; const style::InputField &_st;