From 8748265b004830e47c54602b953826a5d7be36b6 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Wed, 28 Dec 2022 18:09:03 +0300 Subject: [PATCH] Added support of multiple phone pattern groups. --- .../countries/countries_instance.cpp | 53 +++++++++++++++---- .../ui/widgets/fields/special_fields.cpp | 44 +++++++++------ .../ui/widgets/fields/special_fields.h | 4 ++ 3 files changed, 75 insertions(+), 26 deletions(-) diff --git a/Telegram/SourceFiles/countries/countries_instance.cpp b/Telegram/SourceFiles/countries/countries_instance.cpp index 6fd903653d..36af0ce12f 100644 --- a/Telegram/SourceFiles/countries/countries_instance.cpp +++ b/Telegram/SourceFiles/countries/countries_instance.cpp @@ -356,24 +356,55 @@ FormatResult CountriesInstance::format(FormatArgs args) { const auto codeSize = int(bestCallingCodePtr->callingCode.size()); if (args.onlyGroups && args.incomplete) { - auto groups = args.skipCode + auto initialGroups = args.skipCode ? QVector() : QVector{ codeSize }; - auto groupSize = 0; + auto initialGroupsSize = 0; if (bestCallingCodePtr->patterns.empty()) { - return FormatResult{ .groups = std::move(groups) }; + return FormatResult{ .groups = std::move(initialGroups) }; } - for (const auto &c : bestCallingCodePtr->patterns.front()) { - if (c == ' ') { - groups.push_back(base::take(groupSize)); - } else { - groupSize++; + auto bestGroups = initialGroups; + auto bestGroupsSize = initialGroupsSize; + auto bestPatternMaxMatches = -1; + for (const auto &pattern : bestCallingCodePtr->patterns) { + auto groups = initialGroups; + auto groupSize = initialGroupsSize; + auto lastSpacesCount = 0; + auto maxMatchedDigits = 0; + auto isNotBestPattern = false; + for (auto i = 0; i < pattern.size(); i++) { + const auto c = pattern.at(i); + if (c.isDigit()) { + const auto n = (i - lastSpacesCount) + codeSize; + if (n < phoneNumber.size()) { + if (phoneNumber.at(n) == c) { + maxMatchedDigits++; + } else { + isNotBestPattern = true; + } + } else { + isNotBestPattern = true; + } + } + if (c.isSpace()) { + groups.push_back(base::take(groupSize)); + lastSpacesCount++; + } else { + groupSize++; + } + } + if (maxMatchedDigits > bestPatternMaxMatches) { + bestPatternMaxMatches = isNotBestPattern + ? -1 + : maxMatchedDigits; + bestGroups = std::move(groups); + bestGroupsSize = groupSize; } } - if (groupSize) { - groups.push_back(base::take(groupSize)); + if (bestGroupsSize) { + bestGroups.push_back(base::take(bestGroupsSize)); } - return FormatResult{ .groups = std::move(groups) }; + return FormatResult{ .groups = std::move(bestGroups) }; } const auto formattedPart = phoneNumber.mid(codeSize); diff --git a/Telegram/SourceFiles/ui/widgets/fields/special_fields.cpp b/Telegram/SourceFiles/ui/widgets/fields/special_fields.cpp index e9b4a3d430..488c3bf2be 100644 --- a/Telegram/SourceFiles/ui/widgets/fields/special_fields.cpp +++ b/Telegram/SourceFiles/ui/widgets/fields/special_fields.cpp @@ -134,6 +134,12 @@ void PhonePartInput::correctValue( int wasCursor, QString &now, int &nowCursor) { + if (!now.isEmpty() && (_lastDigits != now)) { + _lastDigits = now; + _lastDigits.replace(QRegularExpression("[^\\d]"), QString()); + updatePattern(_groupsCallback(_code + _lastDigits)); + } + QString newText; int oldPos(nowCursor), newPos(-1), oldLen(now.length()), digitCount = 0; for (int i = 0; i < oldLen; ++i) { @@ -212,21 +218,8 @@ void PhonePartInput::addedToNumber(const QString &added) { } void PhonePartInput::chooseCode(const QString &code) { - _pattern = _groupsCallback(code); - if (!_pattern.isEmpty() && _pattern.at(0) == code.size()) { - _pattern.pop_front(); - } else { - _pattern.clear(); - } - _additionalPlaceholder = QString(); - if (!_pattern.isEmpty()) { - _additionalPlaceholder.reserve(20); - for (const auto part : std::as_const(_pattern)) { - _additionalPlaceholder.append(' '); - _additionalPlaceholder.append(QString(part, QChar(0x2212))); - } - } - setPlaceholderHidden(!_additionalPlaceholder.isEmpty()); + _code = code; + updatePattern(_groupsCallback(_code)); auto wasText = getLastText(); auto wasCursor = cursorPosition(); @@ -239,6 +232,27 @@ void PhonePartInput::chooseCode(const QString &code) { update(); } +void PhonePartInput::updatePattern(QVector &&pattern) { + if (_pattern == pattern) { + return; + } + _pattern = std::move(pattern); + if (!_pattern.isEmpty() && _pattern.at(0) == _code.size()) { + _pattern.pop_front(); + } else { + _pattern.clear(); + } + _additionalPlaceholder = QString(); + if (!_pattern.isEmpty()) { + _additionalPlaceholder.reserve(20); + for (const auto &part : _pattern) { + _additionalPlaceholder.append(' '); + _additionalPlaceholder.append(QString(part, QChar(0x2212))); + } + } + setPlaceholderHidden(!_additionalPlaceholder.isEmpty()); +} + UsernameInput::UsernameInput( QWidget *parent, const style::InputField &st, diff --git a/Telegram/SourceFiles/ui/widgets/fields/special_fields.h b/Telegram/SourceFiles/ui/widgets/fields/special_fields.h index ebade9cfc2..d1dded516c 100644 --- a/Telegram/SourceFiles/ui/widgets/fields/special_fields.h +++ b/Telegram/SourceFiles/ui/widgets/fields/special_fields.h @@ -68,6 +68,10 @@ protected: void paintAdditionalPlaceholder(QPainter &p) override; private: + void updatePattern(QVector &&pattern); + + QString _code; + QString _lastDigits; QVector _pattern; QString _additionalPlaceholder; rpl::event_stream> _frontBackspaceEvent;