mirror of
https://github.com/mudita/MuditaOS.git
synced 2026-06-28 02:07:08 -04:00
Fix empty calllog title when number comes in national format. The problem was caused by: 1. making assumption that every number from cellular network comes in e164 format which is not true, 2. using e164 number when looking for contact matching calllog entry without checking if e164 exists for calllog entry. Fix problem by: a.d.1 - replacing `PhoneNumber::viewFromE164` with less strict `PhoneNumber::Parse` method which basically is a convenience method which creates `PhoneNumber` entity and uses it to create a `View`. a.d.2 - instead of fetching e164 directly introduce `getNonEmpty` method of a View, which returns e164 number if it is present and entered number otherwise. Signed-off-by: Marcin Smoczyński <smoczynski.marcin@gmail.com>
179 lines
4.8 KiB
C++
179 lines
4.8 KiB
C++
#include "PhoneNumber.hpp"
|
|
|
|
#include "country.hpp"
|
|
#include "log/log.hpp"
|
|
|
|
#include <phonenumbers/phonenumberutil.h>
|
|
#include <phonenumbers/asyoutypeformatter.h>
|
|
|
|
#include <stdexcept>
|
|
#include <string>
|
|
|
|
using namespace utils;
|
|
|
|
PhoneNumber::PhoneNumber(const std::string &phoneNumber, country::Id defaultCountryCode)
|
|
: countryCode(defaultCountryCode), util(*phn_util::GetInstance()), rawInput(phoneNumber)
|
|
{
|
|
util.ParseAndKeepRawInput(phoneNumber, country::getAlpha2Code(countryCode), &pbNumber);
|
|
}
|
|
|
|
bool PhoneNumber::isValid() const
|
|
{
|
|
return util.IsValidNumber(pbNumber);
|
|
}
|
|
|
|
const std::string &PhoneNumber::get() const
|
|
{
|
|
/// raw input can also be returned directly from pbNumber::rawInput() but
|
|
/// unfortunately if number parsing failed raw input is not preserved so
|
|
/// additional field had to be added in order to be able to always return
|
|
/// raw input
|
|
return rawInput;
|
|
}
|
|
|
|
std::string PhoneNumber::getFormatted() const
|
|
{
|
|
if (!isValid()) {
|
|
return rawInput;
|
|
}
|
|
|
|
std::string formatted;
|
|
util.FormatInOriginalFormat(pbNumber, country::getAlpha2Code(countryCode), &formatted);
|
|
return formatted;
|
|
}
|
|
|
|
std::string PhoneNumber::toE164() const
|
|
{
|
|
if (!isValid()) {
|
|
throw std::runtime_error("Can't create E164 format from an invalid number.");
|
|
}
|
|
|
|
std::string e164number;
|
|
util.Format(pbNumber, formatType::E164, &e164number);
|
|
|
|
return e164number;
|
|
}
|
|
|
|
bool PhoneNumber::operator==(const PhoneNumber &right) const
|
|
{
|
|
return util.IsNumberMatch(pbNumber, right.pbNumber) == phn_util::EXACT_MATCH;
|
|
}
|
|
|
|
bool PhoneNumber::operator==(const View &view) const
|
|
{
|
|
if (isValid() != view.isValid()) {
|
|
return false;
|
|
}
|
|
|
|
return isValid() ? toE164() == view.getE164() : rawInput == view.getEntered();
|
|
}
|
|
|
|
PhoneNumber::numberType PhoneNumber::getType() const
|
|
{
|
|
return util.GetNumberType(pbNumber);
|
|
}
|
|
|
|
bool PhoneNumber::e164format(const std::string &number, std::string &e164, country::Id defaultCountryCode)
|
|
{
|
|
i18n::phonenumbers::PhoneNumber phNumber;
|
|
auto &util = *phn_util::GetInstance();
|
|
|
|
auto result = util.Parse(number, country::getAlpha2Code(defaultCountryCode), &phNumber);
|
|
if (result != errCode::NO_PARSING_ERROR) {
|
|
return false;
|
|
}
|
|
|
|
util.Format(phNumber, formatType::E164, &e164);
|
|
|
|
return true;
|
|
}
|
|
|
|
PhoneNumber::View PhoneNumber::makeView() const
|
|
{
|
|
return PhoneNumber::View(get(), getFormatted(), isValid() ? toE164() : "", isValid());
|
|
}
|
|
|
|
PhoneNumber::View PhoneNumber::validateNumber(const std::string &e164, const std::string &entered)
|
|
{
|
|
auto &util = *phn_util::GetInstance();
|
|
|
|
// parse E164 number
|
|
i18n::phonenumbers::PhoneNumber pbNumberE164;
|
|
if (util.Parse(e164, country::getAlpha2Code(country::Id::UNKNOWN), &pbNumberE164) != errCode::NO_PARSING_ERROR) {
|
|
return PhoneNumber::View(entered, entered, e164, false);
|
|
}
|
|
|
|
// get region code from E164 number
|
|
std::string regionCode;
|
|
util.GetRegionCodeForNumber(pbNumberE164, ®ionCode);
|
|
if (regionCode == country::getAlpha2Code(country::Id::UNKNOWN)) {
|
|
return PhoneNumber::View(entered, entered, e164, false);
|
|
}
|
|
|
|
// use region code to parse number originally entered by the user
|
|
// keep raw input in order to be able to use original format in formatting
|
|
i18n::phonenumbers::PhoneNumber pbNumberEntered;
|
|
if (util.ParseAndKeepRawInput(entered, regionCode, &pbNumberEntered) != errCode::NO_PARSING_ERROR) {
|
|
return PhoneNumber::View(entered, entered, e164, false);
|
|
}
|
|
|
|
// check if numbers match
|
|
if (util.IsNumberMatch(pbNumberE164, pbNumberEntered) != phn_util::EXACT_MATCH) {
|
|
return PhoneNumber::View(entered, entered, e164, false);
|
|
}
|
|
|
|
// format number to generate full view of the number
|
|
std::string formatted;
|
|
util.FormatInOriginalFormat(pbNumberEntered, regionCode, &formatted);
|
|
|
|
return PhoneNumber::View(entered, formatted, e164, true);
|
|
}
|
|
|
|
void PhoneNumber::View::clear()
|
|
{
|
|
this->operator=(View());
|
|
}
|
|
|
|
PhoneNumber::View PhoneNumber::parse(const std::string &inputNumber)
|
|
{
|
|
PhoneNumber number(inputNumber);
|
|
return number.makeView();
|
|
}
|
|
|
|
const std::string &PhoneNumber::View::getEntered() const
|
|
{
|
|
return entered;
|
|
}
|
|
|
|
const std::string &PhoneNumber::View::getE164() const
|
|
{
|
|
return e164;
|
|
}
|
|
|
|
const std::string &PhoneNumber::View::getFormatted() const
|
|
{
|
|
return formatted;
|
|
}
|
|
|
|
bool PhoneNumber::View::isValid() const
|
|
{
|
|
return valid;
|
|
}
|
|
|
|
PhoneNumber::View::View(const std::string &enteredNumber,
|
|
const std::string &formattedNumber,
|
|
const std::string &e164Number,
|
|
bool valid)
|
|
: entered(enteredNumber), formatted(formattedNumber), e164(e164Number), valid(valid)
|
|
{}
|
|
|
|
bool PhoneNumber::View::operator==(const View &rhs) const
|
|
{
|
|
return valid == rhs.valid && e164 == rhs.e164;
|
|
}
|
|
|
|
const std::string &PhoneNumber::View::getNonEmpty() const
|
|
{
|
|
return valid ? e164 : entered;
|
|
}
|