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>
198 lines
6.9 KiB
C++
198 lines
6.9 KiB
C++
/*
|
|
* @file CalllogRecord.cpp
|
|
* @author Aleksander Rudnik (aleksander.rudnik@mudita.com)
|
|
* @date 23.09.2019
|
|
* @brief Call Log DB Record
|
|
* @copyright Copyright (C) 2019 mudita.com
|
|
* @details
|
|
*/
|
|
#include "CalllogRecord.hpp"
|
|
|
|
#include <ContactRecord.hpp>
|
|
#include <log/log.hpp>
|
|
#include <Tables/CalllogTable.hpp>
|
|
#include <PhoneNumber.hpp>
|
|
#include <Utils.hpp>
|
|
|
|
#include <cassert>
|
|
#include <exception>
|
|
#include <sstream>
|
|
#include <vector>
|
|
#include <utility>
|
|
|
|
CalllogRecord::CalllogRecord(const CalllogTableRow &tableRow)
|
|
: Record{tableRow.ID}, presentation(tableRow.presentation), date(tableRow.date), duration(tableRow.duration),
|
|
type(tableRow.type), name(tableRow.name), contactId(tableRow.contactId),
|
|
phoneNumber(utils::PhoneNumber::validateNumber(tableRow.e164number, tableRow.number))
|
|
{}
|
|
|
|
uint32_t CalllogRecord::getContactId() const
|
|
{
|
|
try {
|
|
return static_cast<uint32_t>(std::stoi(contactId));
|
|
}
|
|
catch (const std::exception &e) {
|
|
LOG_ERROR("Invalid contactId %s", contactId.c_str());
|
|
return DB_ID_NONE;
|
|
}
|
|
}
|
|
|
|
std::ostream &operator<<(std::ostream &out, const CalllogRecord &rec)
|
|
{
|
|
out << " <id> " << rec.ID << " <number> " << rec.phoneNumber.getEntered() << " <e164number> "
|
|
<< rec.phoneNumber.getE164() << " <formatted> " << rec.phoneNumber.getFormatted() << " <presentation> "
|
|
<< static_cast<uint32_t>(rec.presentation) << " <date> " << rec.date << " <duration> " << rec.duration
|
|
<< " <type> " << static_cast<uint32_t>(rec.type) << " <name> " << rec.name << " <contactID> " << rec.contactId;
|
|
|
|
return out;
|
|
}
|
|
|
|
CalllogRecordInterface::CalllogRecordInterface(CalllogDB *calllogDb, ContactsDB *contactsDb)
|
|
: calllogDB(calllogDb), contactsDB(contactsDb)
|
|
{}
|
|
|
|
CalllogRecordInterface::~CalllogRecordInterface()
|
|
{}
|
|
|
|
bool CalllogRecordInterface::Add(const CalllogRecord &rec)
|
|
{
|
|
ContactRecordInterface contactInterface(contactsDB);
|
|
auto contactRec =
|
|
contactInterface.GetByNumber(rec.phoneNumber.getNonEmpty(), ContactRecordInterface::CreateTempContact::True);
|
|
if (contactRec->size() == 0) {
|
|
LOG_ERROR("Cannot get contact, for number %s", rec.phoneNumber.getNonEmpty().c_str());
|
|
return false;
|
|
}
|
|
auto localRec = rec;
|
|
auto contact = (*contactRec)[0];
|
|
localRec.contactId = std::to_string(contact.ID);
|
|
localRec.name = contact.getFormattedName();
|
|
LOG_DEBUG("Adding calllog record %s", utils::to_string(localRec).c_str());
|
|
|
|
return calllogDB->calls.Add(CalllogTableRow{.ID = localRec.ID, // this is only to remove warning
|
|
.number = localRec.phoneNumber.getEntered(),
|
|
.e164number = localRec.phoneNumber.getE164(),
|
|
.presentation = localRec.presentation,
|
|
.date = localRec.date,
|
|
.duration = localRec.duration,
|
|
.type = localRec.type,
|
|
.name = localRec.name,
|
|
.contactId = localRec.contactId});
|
|
;
|
|
}
|
|
|
|
uint32_t CalllogRecordInterface::GetLastID()
|
|
{
|
|
return calllogDB->GetLastInsertRowID();
|
|
}
|
|
|
|
std::unique_ptr<std::vector<CalllogRecord>> CalllogRecordInterface::GetLimitOffsetByField(uint32_t offset,
|
|
uint32_t limit,
|
|
CalllogRecordField field,
|
|
const char *str)
|
|
{
|
|
// TODO: alek: need proper implementation
|
|
return GetLimitOffset(offset, limit);
|
|
}
|
|
|
|
ContactRecord CalllogRecordInterface::GetContactRecordByID(const UTF8 &contactId)
|
|
{
|
|
assert(contactsDB != nullptr);
|
|
ContactRecordInterface contactInterface(contactsDB);
|
|
try {
|
|
return contactInterface.GetByID(std::atoi(contactId.c_str()));
|
|
}
|
|
catch (const std::exception &e) {
|
|
LOG_ERROR("Exception %s occured", e.what());
|
|
return ContactRecord();
|
|
}
|
|
}
|
|
|
|
std::unique_ptr<std::vector<CalllogRecord>> CalllogRecordInterface::GetLimitOffset(uint32_t offset, uint32_t limit)
|
|
{
|
|
auto calls = calllogDB->calls.GetLimitOffset(offset, limit);
|
|
|
|
auto records = std::make_unique<std::vector<CalllogRecord>>();
|
|
|
|
for (auto &c : calls) {
|
|
auto contactRec = GetContactRecordByID(c.contactId);
|
|
if (contactRec.ID == DB_ID_NONE) {
|
|
LOG_ERROR("Cannot find contact for ID %s", c.contactId.c_str());
|
|
continue;
|
|
}
|
|
|
|
c.name = contactRec.getFormattedName();
|
|
records->push_back(c);
|
|
}
|
|
|
|
return records;
|
|
}
|
|
|
|
bool CalllogRecordInterface::Update(const CalllogRecord &rec)
|
|
{
|
|
|
|
auto call = calllogDB->calls.GetByID(rec.ID);
|
|
if (call.ID == 0) {
|
|
return false;
|
|
}
|
|
|
|
return calllogDB->calls.Update(CalllogTableRow{.ID = rec.ID,
|
|
.number = rec.phoneNumber.getEntered(),
|
|
.e164number = rec.phoneNumber.getE164(),
|
|
.presentation = rec.presentation,
|
|
.date = rec.date,
|
|
.duration = rec.duration,
|
|
.type = rec.type,
|
|
.name = rec.name,
|
|
.contactId = rec.contactId});
|
|
}
|
|
|
|
bool CalllogRecordInterface::RemoveByID(uint32_t id)
|
|
{
|
|
|
|
auto call = calllogDB->calls.GetByID(id);
|
|
if (call.ID == 0) {
|
|
return false;
|
|
}
|
|
|
|
return calllogDB->calls.RemoveByID(id);
|
|
}
|
|
|
|
bool CalllogRecordInterface::RemoveByField(CalllogRecordField field, const char *str)
|
|
{
|
|
|
|
switch (field) {
|
|
case CalllogRecordField::DATE:
|
|
return calllogDB->calls.RemoveByField(CalllogTableFields::DATE, str);
|
|
case CalllogRecordField::TYPE:
|
|
return calllogDB->calls.RemoveByField(CalllogTableFields::TYPE, str);
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
CalllogRecord CalllogRecordInterface::GetByID(uint32_t id)
|
|
{
|
|
auto call = calllogDB->calls.GetByID(id);
|
|
|
|
auto contactRec = GetContactRecordByID(call.contactId);
|
|
if (contactRec.ID == DB_ID_NONE) {
|
|
auto contactRec = GetContactRecordByID(call.contactId);
|
|
LOG_ERROR("Cannot find contact for ID %s", call.contactId.c_str());
|
|
return CalllogRecord();
|
|
}
|
|
|
|
call.name = contactRec.getFormattedName();
|
|
return CalllogRecord(call);
|
|
}
|
|
|
|
uint32_t CalllogRecordInterface::GetCount(EntryState state)
|
|
{
|
|
return calllogDB->calls.GetCount(state);
|
|
}
|
|
|
|
uint32_t CalllogRecordInterface::GetCount()
|
|
{
|
|
return GetCount(EntryState::ALL);
|
|
}
|