M changelog.md => changelog.md +2 -2
@@ 8,6 8,8 @@
### Changed
+* `[messages]` Use different thread for each of contact's number.
+
### Fixed
* `[desktopApp]` Fixed endpoint handling.
@@ 20,8 22,6 @@
### Other
* `[desktopApp]` Added functional tests.
-
-
## [0.36.1 2020-09-04]
### Added
M image/user/sms.db => image/user/sms.db +0 -0
M module-apps/application-messages/windows/NewMessage.cpp => module-apps/application-messages/windows/NewMessage.cpp +18 -20
@@ 32,6 32,7 @@ namespace gui
if (data == nullptr) {
return;
}
+
if (auto pdata = dynamic_cast<PhonebookSearchReuqest *>(data); pdata != nullptr) {
LOG_INFO("received search results");
recipient->setText(pdata->result->getFormattedName());
@@ 45,11 46,12 @@ namespace gui
}
if (auto pdata = dynamic_cast<SMSSendRequest *>(data); pdata != nullptr) {
LOG_INFO("recieved sms send request");
- auto number = pdata->getPhoneNumber();
- auto retContact = DBServiceAPI::MatchContactByPhoneNumber(application, number);
+ phoneNumber = pdata->getPhoneNumber();
+ LOG_INFO("Number to send sms to: %s", phoneNumber.getFormatted().c_str());
+ auto retContact = DBServiceAPI::MatchContactByPhoneNumber(application, phoneNumber);
if (!retContact) {
- LOG_WARN("not valid contact for number %s", number.getEntered().c_str());
- recipient->setText(number.getFormatted());
+ LOG_WARN("not valid contact for number %s", phoneNumber.getEntered().c_str());
+ recipient->setText(phoneNumber.getFormatted());
message->setText(pdata->textData);
return;
}
@@ 77,9 79,16 @@ namespace gui
{
auto app = dynamic_cast<app::ApplicationMessages *>(application);
assert(app != nullptr);
- // if a valid contact was found, choose it. Otherwise, get a raw entered number
- auto number = (contact && contact->numbers.size() != 0) ? contact->numbers[0].number
- : utils::PhoneNumber(recipient->getText()).getView();
+ utils::PhoneNumber::View number;
+
+ if (phoneNumber.getEntered().size() > 0) {
+ number = phoneNumber;
+ }
+ else {
+ number = (contact && contact->numbers.size() != 0) ? contact->numbers[0].number
+ : utils::PhoneNumber(recipient->getText()).getView();
+ }
+
auto ret = app->sendSms(number, message->getText());
if (!ret) {
LOG_ERROR("sendSms failed");
@@ 102,22 111,11 @@ namespace gui
bool NewSMS_Window::switchToThreadWindow(const utils::PhoneNumber::View &number)
{
- uint32_t contactId;
- if (!contact || contact->numbers.size() == 0) {
- // once the sms is send, there is assumption that contact exists
- auto retContact = DBServiceAPI::MatchContactByPhoneNumber(application, number);
- if (!retContact) {
- LOG_ERROR("not valid contact for number %s", number.getFormatted().c_str());
- return false;
- }
- contact = std::move(retContact);
- }
- contactId = contact->ID;
-
- auto thread = DBServiceAPI::ThreadGetByContact(application, contactId);
+ auto thread = DBServiceAPI::ThreadGetByNumber(application, number, getThreadTimeout);
if (thread) {
// clear data only when message is sent
contact = nullptr;
+ phoneNumber.clear();
recipient->setText("");
message->setText("");
setFocusItem(body);
M module-apps/application-messages/windows/NewMessage.hpp => module-apps/application-messages/windows/NewMessage.hpp +4 -0
@@ 12,10 12,14 @@ namespace gui
class NewSMS_Window : public AppWindow
{
private:
+ inline static const std::uint32_t getThreadTimeout = 1000;
+
gui::Text *recipient = nullptr;
gui::Text *message = nullptr;
gui::VBox *body = nullptr;
std::shared_ptr<ContactRecord> contact;
+ utils::PhoneNumber::View phoneNumber;
+ std::uint32_t numberId = 0;
bool selectContact();
bool sendSms();
M module-apps/application-messages/windows/ThreadViewWindow.cpp => module-apps/application-messages/windows/ThreadViewWindow.cpp +5 -1
@@ 70,7 70,7 @@ namespace gui
inputMessage->activatedCallback = [&](gui::Item &item) {
auto app = dynamic_cast<app::ApplicationMessages *>(application);
assert(app != nullptr);
- if (app->handleSendSmsFromThread(contact->numbers[0].number, inputMessage->inputText->getText())) {
+ if (app->handleSendSmsFromThread(*number, inputMessage->inputText->getText())) {
LOG_ERROR("handleSendSmsFromThread failed");
}
inputMessage->inputText->clear();
@@ 372,6 372,10 @@ namespace gui
contact = std::make_shared<ContactRecord>(ret->front());
// should be name number for now - easier to handle
setTitle(ret->front().getFormattedName());
+ auto retNumber = DBServiceAPI::GetNumberById(application, pdata->thread->numberID, numberIdTimeout);
+ assert(retNumber != nullptr);
+ number = std::move(retNumber);
+ LOG_INFO("Phone number for thread: %s", number->getFormatted().c_str());
}
}
if (auto pdata = dynamic_cast<SMSTextData *>(data)) {
M module-apps/application-messages/windows/ThreadViewWindow.hpp => module-apps/application-messages/windows/ThreadViewWindow.hpp +14 -11
@@ 1,18 1,19 @@
#pragma once
+#include <AppWindow.hpp>
+#include <application-messages/widgets/SMSInputWidget.hpp>
+#include <gui/widgets/BoxLayout.hpp>
+#include <gui/widgets/Image.hpp>
+#include <gui/widgets/Label.hpp>
+#include <gui/widgets/Window.hpp>
+#include <ListView.hpp>
+#include <PhoneNumber.hpp>
+#include <service-db/api/DBServiceAPI.hpp>
+#include <Text.hpp>
+
#include <functional>
#include <string>
-#include "AppWindow.hpp"
-#include "ListView.hpp"
-#include "gui/widgets/Image.hpp"
-#include "gui/widgets/Label.hpp"
-#include "gui/widgets/Window.hpp"
-#include "service-db/api/DBServiceAPI.hpp"
-#include <Text.hpp>
-#include <gui/widgets/BoxLayout.hpp>
-#include "application-messages/widgets/SMSInputWidget.hpp"
-
namespace gui
{
class ThreadViewWindow : public AppWindow
@@ 38,6 39,7 @@ namespace gui
const ssize_t maxsmsinwindow = 7;
std::shared_ptr<ContactRecord> contact;
+ std::unique_ptr<utils::PhoneNumber::View> number;
struct
{
@@ 48,7 50,8 @@ namespace gui
std::unique_ptr<std::vector<SMSRecord>> sms = nullptr; // loaded sms from db
} SMS;
- gui::SMSInputWidget *inputMessage = nullptr;
+ gui::SMSInputWidget *inputMessage = nullptr;
+ inline static const std::uint32_t numberIdTimeout = 1000;
public:
ThreadViewWindow(app::Application *app);
M module-db/CMakeLists.txt => module-db/CMakeLists.txt +2 -0
@@ 76,6 76,7 @@ set(SOURCES
queries/sms/QuerySMSTemplateGetCount.cpp
queries/sms/QuerySMSTemplateRemove.cpp
queries/sms/QuerySMSTemplateUpdate.cpp
+ queries/sms/QueryThreadGetByNumber.cpp
queries/calllog/QueryCalllogSetAllRead.cpp
queries/calllog/QueryCalllogGet.cpp
queries/calllog/QueryCalllogGetCount.cpp
@@ 90,6 91,7 @@ set(SOURCES
queries/phonebook/QueryContactAdd.cpp
queries/phonebook/QueryContactUpdate.cpp
queries/phonebook/QueryContactRemove.cpp
+ queries/phonebook/QueryNumberGetByID.cpp
queries/calendar/QueryEventsRemove.cpp
queries/calendar/QueryEventsGet.cpp
queries/calendar/QueryEventsGetAll.cpp
M module-db/Interface/CalllogRecord.cpp => module-db/Interface/CalllogRecord.cpp +7 -4
@@ 62,14 62,17 @@ CalllogRecordInterface::~CalllogRecordInterface()
bool CalllogRecordInterface::Add(const CalllogRecord &rec)
{
ContactRecordInterface contactInterface(contactsDB);
- auto contactRec = contactInterface.MatchByNumber(rec.phoneNumber, ContactRecordInterface::CreateTempContact::True);
- if (!contactRec) {
+ auto contactMatch =
+ contactInterface.MatchByNumber(rec.phoneNumber, ContactRecordInterface::CreateTempContact::True);
+ if (!contactMatch) {
LOG_ERROR("Cannot get contact, for number %s", rec.phoneNumber.getNonEmpty().c_str());
return false;
}
+ auto &contactRec = contactMatch->contact;
+
auto localRec = rec;
- localRec.contactId = std::to_string(contactRec->ID);
- localRec.name = contactRec->getFormattedName();
+ localRec.contactId = std::to_string(contactRec.ID);
+ localRec.name = contactRec.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
M module-db/Interface/ContactRecord.cpp => module-db/Interface/ContactRecord.cpp +39 -5
@@ 6,6 6,7 @@
#include <Utils.hpp>
#include <queries/phonebook/QueryContactGet.hpp>
+#include <queries/phonebook/QueryNumberGetByID.hpp>
#include <PhoneNumber.hpp>
#include <NumberHolderMatcher.hpp>
@@ 164,6 165,9 @@ std::unique_ptr<db::QueryResult> ContactRecordInterface::runQuery(std::shared_pt
else if (typeid(*query) == typeid(db::query::ContactRemove)) {
return removeQuery(query);
}
+ else if (typeid(*query) == typeid(db::query::NumberGetByID)) {
+ return numberGetByIdQuery(query);
+ }
else {
LOG_ERROR("Unexpected query type.");
return nullptr;
@@ 274,6 278,7 @@ std::unique_ptr<db::QueryResult> ContactRecordInterface::updateQuery(std::shared
response->setRequestQuery(query);
return response;
}
+
std::unique_ptr<db::QueryResult> ContactRecordInterface::removeQuery(std::shared_ptr<db::Query> query)
{
auto removeQuery = static_cast<db::query::ContactRemove *>(query.get());
@@ 283,6 288,15 @@ std::unique_ptr<db::QueryResult> ContactRecordInterface::removeQuery(std::shared
return response;
}
+std::unique_ptr<db::QueryResult> ContactRecordInterface::numberGetByIdQuery(std::shared_ptr<db::Query> query)
+{
+ auto numberQuery = static_cast<db::query::NumberGetByID *>(query.get());
+ auto ret = ContactRecordInterface::GetNumberById(numberQuery->getID());
+ auto response = std::make_unique<db::query::NumberGetByIDResult>(ret);
+ response->setRequestQuery(query);
+ return response;
+}
+
std::vector<std::uint32_t> ContactRecordInterface::splitNumberIDs(const std::string &numberIDs)
{
std::stringstream source(numberIDs);
@@ 874,9 888,10 @@ utils::NumberHolderMatcher<std::vector, ContactNumberHolder> ContactRecordInterf
std::cend(contactNumberHolders));
}
-std::optional<ContactRecord> ContactRecordInterface::MatchByNumber(const utils::PhoneNumber::View &numberView,
- CreateTempContact createTempContact,
- utils::PhoneNumber::Match matchLevel)
+std::optional<ContactRecordInterface::ContactNumberMatch> ContactRecordInterface::MatchByNumber(
+ const utils::PhoneNumber::View &numberView,
+ CreateTempContact createTempContact,
+ utils::PhoneNumber::Match matchLevel)
{
std::vector<ContactNumberHolder> contactNumberHolders;
auto numberMatcher = buildNumberMatcher(contactNumberHolders);
@@ 898,10 913,17 @@ std::optional<ContactRecord> ContactRecordInterface::MatchByNumber(const utils::
return std::nullopt;
}
- return GetByID(contactDB->getLastInsertRowId());
+ auto contactID = contactDB->getLastInsertRowId();
+ auto contactTableRow = contactDB->contacts.getById(contactID);
+ auto numberIDs = splitNumberIDs(contactTableRow.numbersID);
+ assert(numberIDs.size() == 1);
+ auto numberID = numberIDs[0];
+ return ContactRecordInterface::ContactNumberMatch(GetByID(contactID), contactID, numberID);
}
- return GetByID(matchedNumber->getContactID());
+ auto contactID = matchedNumber->getContactID();
+ auto numberID = matchedNumber->getNumberID();
+ return ContactRecordInterface::ContactNumberMatch(GetByID(contactID), contactID, numberID);
}
std::unique_ptr<std::vector<ContactRecord>> ContactRecordInterface::GetBySpeedDial(UTF8 speedDial)
@@ 1041,3 1063,15 @@ bool ContactRecord::isOnGroup(uint32_t groupId)
{
return groups.find(groupId) != groups.end();
}
+
+ContactRecordInterface::ContactNumberMatch::ContactNumberMatch(ContactRecord rec,
+ std::uint32_t contactId,
+ std::uint32_t numberId)
+ : contact(std::move(rec)), contactId(contactId), numberId(numberId)
+{}
+
+utils::PhoneNumber::View ContactRecordInterface::GetNumberById(std::uint32_t numberId)
+{
+ auto row = contactDB->number.getById(numberId);
+ return utils::PhoneNumber(row.numberUser, row.numbere164).getView();
+}
M module-db/Interface/ContactRecord.hpp => module-db/Interface/ContactRecord.hpp +13 -2
@@ 113,8 113,16 @@ class ContactNumberHolder
class ContactRecordInterface : public RecordInterface<ContactRecord, ContactRecordField>
{
-
public:
+ struct ContactNumberMatch
+ {
+ ContactRecord contact;
+ std::uint32_t contactId = DB_ID_NONE;
+ std::uint32_t numberId = DB_ID_NONE;
+
+ ContactNumberMatch(ContactRecord rec, std::uint32_t contactId, std::uint32_t numberId);
+ };
+
ContactRecordInterface(ContactsDB *db);
~ContactRecordInterface();
@@ 153,7 161,7 @@ class ContactRecordInterface : public RecordInterface<ContactRecord, ContactReco
std::unique_ptr<std::vector<ContactRecord>> GetByNumber(
const utils::PhoneNumber::View &numberView, CreateTempContact createTempContact = CreateTempContact::False);
- std::optional<ContactRecord> MatchByNumber(
+ std::optional<ContactNumberMatch> MatchByNumber(
const utils::PhoneNumber::View &numberView,
CreateTempContact createTempContact = CreateTempContact::False,
utils::PhoneNumber::Match matchLevel = utils::PhoneNumber::Match::POSSIBLE);
@@ 166,6 174,8 @@ class ContactRecordInterface : public RecordInterface<ContactRecord, ContactReco
std::unique_ptr<db::QueryResult> runQuery(std::shared_ptr<db::Query> query) override;
+ utils::PhoneNumber::View GetNumberById(std::uint32_t numberId);
+
private:
ContactsDB *contactDB;
@@ 192,4 202,5 @@ class ContactRecordInterface : public RecordInterface<ContactRecord, ContactReco
std::unique_ptr<db::QueryResult> addQuery(std::shared_ptr<db::Query> query);
std::unique_ptr<db::QueryResult> updateQuery(std::shared_ptr<db::Query> query);
std::unique_ptr<db::QueryResult> removeQuery(std::shared_ptr<db::Query> query);
+ std::unique_ptr<db::QueryResult> numberGetByIdQuery(std::shared_ptr<db::Query> query);
};
M module-db/Interface/SMSRecord.cpp => module-db/Interface/SMSRecord.cpp +10 -9
@@ 29,29 29,32 @@ SMSRecordInterface::SMSRecordInterface(SmsDB *smsDb, ContactsDB *contactsDb) : s
bool SMSRecordInterface::Add(const SMSRecord &rec)
{
ContactRecordInterface contactInterface(contactsDB);
- auto contactRec = contactInterface.MatchByNumber(rec.number, ContactRecordInterface::CreateTempContact::True);
- if (contactRec == std::nullopt) {
+ auto contactMatch = contactInterface.MatchByNumber(rec.number, ContactRecordInterface::CreateTempContact::True);
+ if (contactMatch == std::nullopt) {
LOG_ERROR("Cannot find contact, for number %s", rec.number.getFormatted().c_str());
return false;
}
- uint32_t contactID = contactRec->ID;
+ auto contactID = contactMatch->contactId;
+ auto numberID = contactMatch->numberId;
+
// Search for a thread with specified contactID
ThreadRecordInterface threadInterface(smsDB, contactsDB);
auto threadRec =
- threadInterface.GetLimitOffsetByField(0, 1, ThreadRecordField::ContactID, std::to_string(contactID).c_str());
+ threadInterface.GetLimitOffsetByField(0, 1, ThreadRecordField::NumberID, std::to_string(numberID).c_str());
// Thread not found, create one
if (threadRec->size() == 0) {
ThreadRecord re;
re.contactID = contactID;
+ re.numberID = numberID;
if (!threadInterface.Add(re)) {
LOG_ERROR("Cannot create new thread");
return false;
}
- threadRec = threadInterface.GetLimitOffsetByField(
- 0, 1, ThreadRecordField::ContactID, std::to_string(contactID).c_str());
+ threadRec =
+ threadInterface.GetLimitOffsetByField(0, 1, ThreadRecordField::NumberID, std::to_string(numberID).c_str());
if (threadRec->size() == 0) {
LOG_ERROR("Thread not found");
return false;
@@ 289,8 292,7 @@ SMSRecord SMSRecordInterface::GetByID(uint32_t id)
ContactRecordInterface contactInterface(contactsDB);
auto contactRec = contactInterface.GetByID(sms.contactID);
- // TODO: or numberUser?
- auto number = contactRec.numbers.size() != 0 ? contactRec.numbers[0].number : utils::PhoneNumber::View();
+ auto number = contactRec.numbers.size() != 0 ? contactRec.numbers[0].number : utils::PhoneNumber::View();
return SMSRecord{sms, number};
}
@@ 337,7 339,6 @@ std::unique_ptr<db::query::SMSSearchByTypeResult> SMSRecordInterface::runQueryIm
auto contactRec = contactInterface.GetByID(w.contactID);
if (contactRec.numbers.size() != 0) {
- // TODO: or numberUser? or other number
records->push_back({w, contactRec.numbers[0].number});
}
}
M module-db/Interface/ThreadRecord.cpp => module-db/Interface/ThreadRecord.cpp +41 -5
@@ 1,5 1,9 @@
#include "ThreadRecord.hpp"
#include "SMSRecord.hpp"
+#include "ContactRecord.hpp"
+
+#include <queries/sms/QueryThreadGetByNumber.hpp>
+
#include <cassert>
#include <log/log.hpp>
@@ 14,6 18,7 @@ bool ThreadRecordInterface::Add(const ThreadRecord &rec)
.msgCount = rec.msgCount,
.unreadMsgCount = rec.unreadMsgCount,
.contactID = rec.contactID,
+ .numberID = rec.numberID,
.snippet = rec.snippet,
.type = rec.type});
@@ 38,6 43,7 @@ bool ThreadRecordInterface::Update(const ThreadRecord &rec)
.msgCount = rec.msgCount,
.unreadMsgCount = rec.unreadMsgCount,
.contactID = rec.contactID,
+ .numberID = rec.numberID,
.snippet = rec.snippet,
.type = rec.type
@@ 74,16 80,21 @@ std::unique_ptr<std::vector<ThreadRecord>> ThreadRecordInterface::GetLimitOffset
{
auto records = std::make_unique<std::vector<ThreadRecord>>();
+ ThreadsTableFields threadsField;
switch (field) {
case ThreadRecordField::ContactID: {
- auto ret = smsDB->threads.getLimitOffsetByField(offset, limit, ThreadsTableFields::ContactID, str);
-
- for (const auto &w : ret) {
- records->push_back(w);
- }
+ threadsField = ThreadsTableFields::ContactID;
+ } break;
+ case ThreadRecordField::NumberID: {
+ threadsField = ThreadsTableFields::NumberID;
} break;
}
+ auto ret = smsDB->threads.getLimitOffsetByField(offset, limit, threadsField, str);
+ for (const auto &w : ret) {
+ records->push_back(w);
+ }
+
return records;
}
@@ 119,6 130,24 @@ ThreadRecord ThreadRecordInterface::GetByContact(uint32_t contact_id)
return ThreadRecord(ret[0]);
}
+ThreadRecord ThreadRecordInterface::GetByNumber(const utils::PhoneNumber::View &phoneNumber)
+{
+ auto contactInterface = ContactRecordInterface(contactsDB);
+ auto match = contactInterface.MatchByNumber(phoneNumber);
+
+ if (!match.has_value()) {
+ return ThreadRecord();
+ }
+
+ auto threadRec = GetLimitOffsetByField(0, 1, ThreadRecordField::NumberID, std::to_string(match->numberId).c_str());
+
+ if (threadRec->size() == 0) {
+ return ThreadRecord();
+ }
+
+ return threadRec->at(0);
+}
+
std::unique_ptr<db::QueryResult> ThreadRecordInterface::runQuery(std::shared_ptr<db::Query> query)
{
if (const auto localQuery = dynamic_cast<const db::query::SMSSearch *>(query.get())) {
@@ 142,6 171,13 @@ std::unique_ptr<db::QueryResult> ThreadRecordInterface::runQuery(std::shared_ptr
response->setRequestQuery(query);
return response;
}
+
+ if (const auto local_query = dynamic_cast<const db::query::ThreadGetByNumber *>(query.get())) {
+ auto response = std::make_unique<db::query::ThreadGetByNumberResult>(GetByNumber(local_query->getNumber()));
+ response->setRequestQuery(query);
+ return response;
+ }
+
return nullptr;
}
M module-db/Interface/ThreadRecord.hpp => module-db/Interface/ThreadRecord.hpp +5 -1
@@ 7,6 7,7 @@
#include "module-db/queries/sms/QuerySMSSearch.hpp"
#include "module-db/queries/sms/QuerySMSThreadsGet.hpp"
#include "module-db/queries/sms/QuerySmsThreadMarkAsRead.hpp"
+#include <PhoneNumber.hpp>
#include <utf8/UTF8.hpp>
@@ 19,11 20,12 @@ struct ThreadRecord : Record
UTF8 snippet;
SMSType type = SMSType::UNKNOWN;
uint32_t contactID = DB_ID_NONE;
+ uint32_t numberID = DB_ID_NONE;
ThreadRecord() = default;
ThreadRecord(const ThreadsTableRow &rec)
: date(rec.date), msgCount(rec.msgCount), unreadMsgCount(rec.unreadMsgCount), snippet(rec.snippet),
- type(rec.type), contactID(rec.contactID)
+ type(rec.type), contactID(rec.contactID), numberID(rec.numberID)
{
ID = rec.ID;
}
@@ 37,6 39,7 @@ struct ThreadRecord : Record
enum class ThreadRecordField
{
ContactID,
+ NumberID,
};
class ThreadRecordInterface : public RecordInterface<ThreadRecord, ThreadRecordField>
@@ 50,6 53,7 @@ class ThreadRecordInterface : public RecordInterface<ThreadRecord, ThreadRecordF
bool Update(const ThreadRecord &rec) override final;
ThreadRecord GetByID(uint32_t id) override final;
ThreadRecord GetByContact(uint32_t contact_id);
+ ThreadRecord GetByNumber(const utils::PhoneNumber::View &phoneNumber);
uint32_t GetCount() override final;
uint32_t GetCount(EntryState state);
M module-db/Tables/ThreadsTable.cpp => module-db/Tables/ThreadsTable.cpp +22 -13
@@ 24,14 24,16 @@ bool ThreadsTable::create()
bool ThreadsTable::add(ThreadsTableRow entry)
{
- return db->execute("INSERT or ignore INTO threads ( date, msg_count, read, contact_id, snippet, last_dir ) VALUES "
- "( %lu, %lu, %lu, %lu, '%q', %lu );",
- entry.date,
- entry.msgCount,
- entry.unreadMsgCount,
- entry.contactID,
- entry.snippet.c_str(),
- entry.type);
+ return db->execute(
+ "INSERT or ignore INTO threads ( date, msg_count, read, contact_id, number_id, snippet, last_dir ) VALUES "
+ "( %lu, %lu, %lu, %lu, %lu, '%q', %lu );",
+ entry.date,
+ entry.msgCount,
+ entry.unreadMsgCount,
+ entry.contactID,
+ entry.numberID,
+ entry.snippet.c_str(),
+ entry.type);
}
bool ThreadsTable::removeById(uint32_t id)
@@ 41,12 43,14 @@ bool ThreadsTable::removeById(uint32_t id)
bool ThreadsTable::update(ThreadsTableRow entry)
{
- return db->execute("UPDATE threads SET date = %lu, msg_count = %lu ,read = %lu, contact_id = %lu, snippet = '%q', "
+ return db->execute("UPDATE threads SET date = %lu, msg_count = %lu ,read = %lu, contact_id = %lu, number_id = %lu, "
+ "snippet = '%q', "
"last_dir = %lu WHERE _id=%lu;",
entry.date,
entry.msgCount,
entry.unreadMsgCount,
entry.contactID,
+ entry.numberID,
entry.snippet.c_str(),
entry.type,
entry.ID);
@@ 66,8 70,9 @@ ThreadsTableRow ThreadsTable::getById(uint32_t id)
(*retQuery)[2].getUInt32(), // msgCount
(*retQuery)[3].getUInt32(), // unreadMsgCount
(*retQuery)[4].getUInt32(), // contactID
- (*retQuery)[5].getString(), // snippet
- static_cast<SMSType>((*retQuery)[6].getUInt32()), // type/last-dir
+ (*retQuery)[5].getUInt32(), // numberID
+ (*retQuery)[6].getString(), // snippet
+ static_cast<SMSType>((*retQuery)[7].getUInt32()), // type/last-dir
};
}
@@ 80,8 85,9 @@ void fillRetQuery(std::vector<ThreadsTableRow> &ret, const std::unique_ptr<Query
(*retQuery)[2].getUInt32(), // msgCount
(*retQuery)[3].getUInt32(), // unreadMsgCount
(*retQuery)[4].getUInt32(), // contactID
- (*retQuery)[5].getString(), // snippet
- static_cast<SMSType>((*retQuery)[6].getUInt32()), // type/last-dir
+ (*retQuery)[5].getUInt32(), // numberID
+ (*retQuery)[6].getString(), // snippet
+ static_cast<SMSType>((*retQuery)[7].getUInt32()), // type/last-dir
});
} while (retQuery->nextRow());
}
@@ 117,6 123,9 @@ std::vector<ThreadsTableRow> ThreadsTable::getLimitOffsetByField(uint32_t offset
case ThreadsTableFields ::ContactID:
fieldName = "contact_id";
break;
+ case ThreadsTableFields ::NumberID:
+ fieldName = "number_id";
+ break;
default:
return std::vector<ThreadsTableRow>();
}
M module-db/Tables/ThreadsTable.hpp => module-db/Tables/ThreadsTable.hpp +3 -0
@@ 13,6 13,7 @@ struct ThreadsTableRow : public Record
uint32_t msgCount = 0;
uint32_t unreadMsgCount = 0;
uint32_t contactID = DB_ID_NONE;
+ uint32_t numberID = DB_ID_NONE;
UTF8 snippet;
SMSType type = SMSType::UNKNOWN;
};
@@ 23,6 24,7 @@ enum class ThreadsTableFields
MsgCount,
MsgRead,
ContactID,
+ NumberID,
Type
};
@@ 58,6 60,7 @@ class ThreadsTable : public Table<ThreadsTableRow, ThreadsTableFields>
"msg_count INTEGER,"
"read INTEGER,"
"contact_id INTEGER,"
+ "number_id INTEGER,"
"snippet TEXT NOT NULL,"
"last_dir INTEGER"
");";
A module-db/queries/phonebook/QueryNumberGetByID.cpp => module-db/queries/phonebook/QueryNumberGetByID.cpp +34 -0
@@ 0,0 1,34 @@
+#include "QueryNumberGetByID.hpp"
+
+#include <Common/Query.hpp>
+#include <PhoneNumber.hpp>
+
+#include <string>
+
+using namespace db::query;
+
+NumberGetByID::NumberGetByID(std::uint32_t id) : Query(Query::Type::Read), id(id)
+{}
+
+NumberGetByIDResult::NumberGetByIDResult(utils::PhoneNumber::View number) : number(std::move(number))
+{}
+
+[[nodiscard]] auto NumberGetByID::debugInfo() const -> std::string
+{
+ return "NumberGetByID";
+}
+
+[[nodiscard]] auto NumberGetByIDResult::debugInfo() const -> std::string
+{
+ return "NumberGetByIDResult";
+}
+
+auto NumberGetByID::getID() const noexcept -> std::uint32_t
+{
+ return id;
+}
+
+auto NumberGetByIDResult::getNumber() -> utils::PhoneNumber::View
+{
+ return std::move(number);
+}
A module-db/queries/phonebook/QueryNumberGetByID.hpp => module-db/queries/phonebook/QueryNumberGetByID.hpp +33 -0
@@ 0,0 1,33 @@
+#pragma once
+
+#include <Common/Query.hpp>
+#include <PhoneNumber.hpp>
+
+#include <string>
+
+namespace db::query
+{
+
+ class NumberGetByID : public Query
+ {
+ public:
+ NumberGetByID(std::uint32_t id);
+ [[nodiscard]] auto debugInfo() const -> std::string override;
+ auto getID() const noexcept -> std::uint32_t;
+
+ private:
+ std::uint32_t id;
+ };
+
+ class NumberGetByIDResult : public QueryResult
+ {
+ public:
+ NumberGetByIDResult(utils::PhoneNumber::View number);
+ [[nodiscard]] auto debugInfo() const -> std::string override;
+ auto getNumber() -> utils::PhoneNumber::View;
+
+ private:
+ utils::PhoneNumber::View number;
+ };
+
+}; // namespace db::query
A module-db/queries/sms/QueryThreadGetByNumber.cpp => module-db/queries/sms/QueryThreadGetByNumber.cpp +36 -0
@@ 0,0 1,36 @@
+#include "QueryThreadGetByNumber.hpp"
+
+#include <Interface/ThreadRecord.hpp>
+#include <PhoneNumber.hpp>
+
+#include <string>
+
+namespace db::query
+{
+ ThreadGetByNumber::ThreadGetByNumber(utils::PhoneNumber::View number)
+ : Query(Query::Type::Read), number(std::move(number))
+ {}
+
+ auto ThreadGetByNumber::getNumber() const -> const utils::PhoneNumber::View &
+ {
+ return number;
+ }
+
+ [[nodiscard]] auto ThreadGetByNumber::debugInfo() const -> std::string
+ {
+ return "ThreadGetByNumber";
+ }
+
+ ThreadGetByNumberResult::ThreadGetByNumberResult(ThreadRecord thread) : thread(std::move(thread))
+ {}
+
+ auto ThreadGetByNumberResult::getThread() -> ThreadRecord
+ {
+ return std::move(thread);
+ }
+
+ [[nodiscard]] auto ThreadGetByNumberResult::debugInfo() const -> std::string
+ {
+ return "ThreadGetByNumberResult";
+ }
+} // namespace db::query
A module-db/queries/sms/QueryThreadGetByNumber.hpp => module-db/queries/sms/QueryThreadGetByNumber.hpp +33 -0
@@ 0,0 1,33 @@
+#pragma once
+
+#include <Common/Query.hpp>
+#include <Interface/ThreadRecord.hpp>
+#include <PhoneNumber.hpp>
+
+#include <string>
+
+namespace db::query
+{
+
+ class ThreadGetByNumber : public Query
+ {
+ utils::PhoneNumber::View number;
+
+ public:
+ ThreadGetByNumber(utils::PhoneNumber::View number);
+ auto getNumber() const -> const utils::PhoneNumber::View &;
+
+ [[nodiscard]] auto debugInfo() const -> std::string override;
+ };
+
+ class ThreadGetByNumberResult : public QueryResult
+ {
+ ThreadRecord thread;
+
+ public:
+ ThreadGetByNumberResult(ThreadRecord record);
+ [[nodiscard]] auto getThread() -> ThreadRecord;
+ [[nodiscard]] auto debugInfo() const -> std::string override;
+ };
+
+}; // namespace db::query
M module-services/service-db/ServiceDB.cpp => module-services/service-db/ServiceDB.cpp +2 -2
@@ 341,8 341,8 @@ sys::Message_t ServiceDB::DataReceivedHandler(sys::DataMessage *msgl, sys::Respo
auto ret = contactRecordInterface->MatchByNumber(msg->numberView);
if (ret.has_value()) {
- responseMsg = std::make_shared<DBContactNumberResponseMessage>(sys::ReturnCodes::Success,
- std::make_unique<ContactRecord>(*ret));
+ responseMsg = std::make_shared<DBContactNumberResponseMessage>(
+ sys::ReturnCodes::Success, std::make_unique<ContactRecord>(ret->contact));
}
else {
responseMsg = std::make_shared<DBContactNumberResponseMessage>(sys::ReturnCodes::Failure,
M module-services/service-db/api/DBServiceAPI.cpp => module-services/service-db/api/DBServiceAPI.cpp +47 -0
@@ 10,6 10,11 @@
#include <messages/DBCalllogMessage.hpp>
#include <messages/DBCountryCodeMessage.hpp>
#include <messages/DBServiceMessage.hpp>
+#include <messages/QueryMessage.hpp>
+
+#include <Common/Query.hpp>
+#include <queries/phonebook/QueryNumberGetByID.hpp>
+#include <queries/sms/QueryThreadGetByNumber.hpp>
#include <ServiceDB.hpp>
#include <includes/DBServiceName.hpp>
@@ 191,6 196,27 @@ std::unique_ptr<ThreadRecord> DBServiceAPI::ThreadGetByContact(sys::Service *ser
}
}
+std::unique_ptr<ThreadRecord> DBServiceAPI::ThreadGetByNumber(sys::Service *serv,
+ const utils::PhoneNumber::View &phoneNumber,
+ std::uint32_t timeout)
+{
+ auto [code, msg] = DBServiceAPI::GetQueryWithReply(
+ serv, db::Interface::Name::SMSThread, std::make_unique<db::query::ThreadGetByNumber>(phoneNumber), timeout);
+
+ if (code == sys::ReturnCodes::Success && msg != nullptr) {
+ auto queryResponse = dynamic_cast<db::QueryResponse *>(msg.get());
+ assert(queryResponse != nullptr);
+
+ auto threadResponse = queryResponse->getResult();
+ auto threadResult = dynamic_cast<db::query::ThreadGetByNumberResult *>(threadResponse.get());
+ assert(threadResult != nullptr);
+
+ return std::make_unique<ThreadRecord>(std::move(threadResult->getThread()));
+ }
+
+ return nullptr;
+}
+
bool DBServiceAPI::ThreadRemove(sys::Service *serv, uint32_t id)
{
std::shared_ptr<DBThreadMessage> msg = std::make_shared<DBThreadMessage>(MessageType::DBThreadRemove);
@@ 805,3 831,24 @@ bool DBServiceAPI::DBBackup(sys::Service *serv, std::string backupPath)
return false;
}
}
+
+std::unique_ptr<utils::PhoneNumber::View> DBServiceAPI::GetNumberById(sys::Service *serv,
+ std::uint32_t numberId,
+ std::uint32_t timeout)
+{
+ auto [code, msg] = DBServiceAPI::GetQueryWithReply(
+ serv, db::Interface::Name::Contact, std::make_unique<db::query::NumberGetByID>(numberId), timeout);
+
+ if (code == sys::ReturnCodes::Success && msg != nullptr) {
+ auto queryResponse = dynamic_cast<db::QueryResponse *>(msg.get());
+ assert(queryResponse != nullptr);
+
+ auto numberResponse = queryResponse->getResult();
+ auto numberResult = dynamic_cast<db::query::NumberGetByIDResult *>(numberResponse.get());
+ assert(numberResult != nullptr);
+
+ return std::make_unique<utils::PhoneNumber::View>(std::move(numberResult->getNumber()));
+ }
+
+ return nullptr;
+}
M module-services/service-db/api/DBServiceAPI.hpp => module-services/service-db/api/DBServiceAPI.hpp +6 -0
@@ 56,6 56,9 @@ class DBServiceAPI
static std::unique_ptr<ThreadRecord> ThreadGet(sys::Service *serv, uint32_t id);
static std::unique_ptr<ThreadRecord> ThreadGetByContact(sys::Service *serv, uint32_t contactID);
+ static std::unique_ptr<ThreadRecord> ThreadGetByNumber(sys::Service *serv,
+ const utils::PhoneNumber::View &phoneNumber,
+ std::uint32_t timeout);
static bool ThreadRemove(sys::Service *serv, uint32_t id);
static bool ThreadGetLimitOffset(sys::Service *serv, uint32_t offset, uint32_t limit);
static uint32_t ThreadGetCount(sys::Service *serv, EntryState state = EntryState::ALL);
@@ 113,6 116,9 @@ class DBServiceAPI
UTF8 primaryName,
UTF8 alternativeName,
UTF8 number);
+ static std::unique_ptr<utils::PhoneNumber::View> GetNumberById(sys::Service *serv,
+ std::uint32_t numberId,
+ std::uint32_t timeout);
static bool AlarmAdd(sys::Service *serv, const AlarmsRecord &rec);
static bool AlarmRemove(sys::Service *serv, uint32_t id);
static bool AlarmUpdate(sys::Service *serv, const AlarmsRecord &rec);