M enabled_unittests => enabled_unittests +2 -0
@@ 130,6 130,8 @@ TESTS_LIST["catch2-db"]="
SMS Templates Table tests;
Thread Record tests;
Threads Table tests;
+ Notifications Table tests;
+ Notifications Record tests;
"
#---------
TESTS_LIST["catch2-db-initializer"]="
M image/user/db/notifications_001.sql => image/user/db/notifications_001.sql +2 -1
@@ 4,5 4,6 @@
CREATE TABLE IF NOT EXISTS notifications(
_id INTEGER PRIMARY KEY,
key INTEGER UNIQUE DEFAULT 0,
- value INTEGER DEFAULT 0
+ value INTEGER DEFAULT 0,
+ contact_id INTEGER DEFAULT 0
);
M image/user/db/notifications_002.sql => image/user/db/notifications_002.sql +3 -4
@@ 1,7 1,6 @@
-- Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
-- For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-INSERT OR IGNORE INTO notifications (key, value) VALUES
- ('1', '0'),
- ('2', '0');
-
+INSERT OR IGNORE INTO notifications (key, value, contact_id) VALUES
+ ('1', '0', '0'),
+ ('2', '0', '0');
M module-apps/application-desktop/models/ActiveNotificationsModel.cpp => module-apps/application-desktop/models/ActiveNotificationsModel.cpp +2 -2
@@ 63,8 63,8 @@ auto ActiveNotificationsModel::create(const notifications::NotSeenCallNotificati
std::function<void()> onKeyLeftFunctionalCallback = nullptr;
if (notification->hasRecord()) {
- if (const auto &record = notification->getRecord(); !record->numbers.empty()) {
- onKeyLeftFunctionalCallback = [this, number = record->numbers[0].number]() {
+ if (const auto &record = notification->getRecord(); !record.numbers.empty()) {
+ onKeyLeftFunctionalCallback = [this, number = record.numbers[0].number]() {
app::manager::Controller::sendAction(parent->getApplication(),
app::manager::actions::Dial,
std::make_unique<app::ExecuteCallData>(number));
M module-apps/application-desktop/windows/DesktopMainWindow.cpp => module-apps/application-desktop/windows/DesktopMainWindow.cpp +1 -1
@@ 12,6 12,7 @@
#include <service-appmgr/Controller.hpp>
#include <service-time/ServiceTime.hpp>
#include <service-time/TimeMessage.hpp>
+#include <notifications/NotificationsModel.hpp>
#include <log/log.hpp>
@@ 136,7 137,6 @@ namespace gui
return app::manager::Controller::sendAction(
application, app::manager::actions::Dial, std::make_unique<app::EnterNumberData>("+"));
}
-
if (inputEvent.is(KeyCode::KEY_RF)) {
application->switchWindow(popup::window::power_off_window);
return true;
M module-apps/application-desktop/windows/DesktopMainWindow.hpp => module-apps/application-desktop/windows/DesktopMainWindow.hpp +2 -0
@@ 17,6 17,8 @@ namespace app
namespace gui
{
+ class NotificationsModel;
+
class DesktopMainWindow : public AppWindow
{
protected:
M module-apps/notifications/NotificationData.cpp => module-apps/notifications/NotificationData.cpp +19 -17
@@ 2,7 2,7 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "NotificationData.hpp"
-
+#include <gsl_assert>
uint32_t notifications::Notification::priorityPool = 0;
using namespace notifications;
@@ 35,33 35,35 @@ auto Notification::getPriority() const noexcept -> uint32_t
return priority;
}
-NotSeenSMSNotification::NotSeenSMSNotification(unsigned value)
- : Notification(NotificationType::NotSeenSms), value{value}
+NotificationWithContact::NotificationWithContact(NotificationType type,
+ unsigned value,
+ std::optional<ContactRecord> record)
+ : Notification(type), value{value}, record{std::move(record)}
{}
-auto NotSeenSMSNotification::getValue() const noexcept -> unsigned
+auto NotificationWithContact::hasRecord() const noexcept -> bool
{
- return value;
+ return record.has_value();
}
-NotSeenCallNotification::NotSeenCallNotification(unsigned value, std::unique_ptr<ContactRecord> record)
- : Notification(NotificationType::NotSeenCall), value{value}, record{std::move(record)}
-{}
-
-bool NotSeenCallNotification::hasRecord() const noexcept
+auto NotificationWithContact::getRecord() const noexcept -> const ContactRecord &
{
- return record != nullptr;
+ Expects(hasRecord());
+ return record.value();
}
-auto NotSeenCallNotification::getRecord() const noexcept -> const std::unique_ptr<ContactRecord> &
-{
- return record;
-}
-
-auto NotSeenCallNotification::getValue() const noexcept -> unsigned
+auto NotificationWithContact::getValue() const noexcept -> unsigned
{
return value;
}
+NotSeenSMSNotification::NotSeenSMSNotification(unsigned value, std::optional<ContactRecord> record)
+ : NotificationWithContact(NotificationType::NotSeenSms, value, std::move(record))
+{}
+
+NotSeenCallNotification::NotSeenCallNotification(unsigned value, std::optional<ContactRecord> record)
+ : NotificationWithContact(NotificationType::NotSeenCall, value, std::move(record))
+{}
+
TetheringNotification::TetheringNotification() : Notification(NotificationType::Tethering)
{}
M module-apps/notifications/NotificationData.hpp => module-apps/notifications/NotificationData.hpp +14 -10
@@ 44,26 44,30 @@ namespace notifications
virtual ~Notification() = default;
};
- class NotSeenSMSNotification : public Notification
+ class NotificationWithContact : public Notification
{
unsigned value = 0;
+ std::optional<ContactRecord> record;
+
+ protected:
+ NotificationWithContact(NotificationType type, unsigned value, std::optional<ContactRecord> record);
public:
- explicit NotSeenSMSNotification(unsigned value);
+ [[nodiscard]] auto hasRecord() const noexcept -> bool;
+ [[nodiscard]] auto getRecord() const noexcept -> const ContactRecord &;
[[nodiscard]] auto getValue() const noexcept -> unsigned;
};
- class NotSeenCallNotification : public Notification
+ class NotSeenSMSNotification : public NotificationWithContact
{
- unsigned value = 0;
- std::unique_ptr<ContactRecord> record;
-
public:
- explicit NotSeenCallNotification(unsigned value, std::unique_ptr<ContactRecord> record = nullptr);
+ NotSeenSMSNotification(unsigned value, std::optional<ContactRecord> record);
+ };
- [[nodiscard]] bool hasRecord() const noexcept;
- [[nodiscard]] auto getRecord() const noexcept -> const std::unique_ptr<ContactRecord> &;
- [[nodiscard]] auto getValue() const noexcept -> unsigned;
+ class NotSeenCallNotification : public NotificationWithContact
+ {
+ public:
+ NotSeenCallNotification(unsigned value, std::optional<ContactRecord> record);
};
class TetheringNotification : public Notification
M module-apps/notifications/NotificationListItem.cpp => module-apps/notifications/NotificationListItem.cpp +4 -3
@@ 12,7 12,6 @@
#include <map>
using namespace gui;
-// using namespace style::desktop;
namespace
{
@@ 36,14 35,15 @@ namespace
auto buildNotificationNameLabel(uint32_t width) -> gui::TextFixedSize *
{
auto text =
- new gui::TextFixedSize(nullptr, 0, 0, style::notifications::textMaxWidth, style::notifications::itemHeight);
- text->setMaximumSize(width, Axis::X);
+ new gui::TextFixedSize(nullptr, 0, 0, style::notifications::textMinWidth, style::notifications::itemHeight);
+ text->setMaximumSize(style::notifications::textMaxWidth, Axis::X);
text->setAlignment(Alignment(gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center));
text->setPenWidth(style::window::default_border_no_focus_w);
text->setUnderline(false);
text->setFont(style::window::font::medium);
text->activeItem = false;
+ text->setTextLimitType(TextLimitType::MaxLines, 1);
return text;
}
@@ 135,6 135,7 @@ NotificationWithEventCounter::NotificationWithEventCounter(notifications::Notifi
{
box->addWidget(buildImageInactive("dot_12px_hard_alpha_W_G"));
box->addWidget(buildNotificationCountText(indicator));
+ text->setMaximumSize(text->getSize(Axis::X), Axis::X);
}
NotificationWithOnOffButton::NotificationWithOnOffButton(notifications::NotificationType type, gui::ButtonState state)
M module-apps/notifications/NotificationProvider.cpp => module-apps/notifications/NotificationProvider.cpp +9 -6
@@ 7,26 7,29 @@
#include <service-appmgr/Controller.hpp>
#include <service-appmgr/data/NotificationsChangedActionsParams.hpp>
#include <service-db/DBNotificationMessage.hpp>
+#include <NotificationsRecord.hpp>
using namespace notifications;
NotificationProvider::NotificationProvider(sys::Service *ownerService) : ownerService{ownerService}
{}
-template <NotificationType type, typename T> bool NotificationProvider::handleNotSeenWithCounter(unsigned int value)
+template <NotificationType type, typename T>
+bool NotificationProvider::handleNotSeenWithCounter(NotificationsRecord &&record)
{
+ auto value = record.value;
if (notifications.count(type) > 0) {
if (value == 0) {
notifications.erase(type);
return true;
}
if (auto notification = static_cast<T *>(notifications[type].get()); value > notification->getValue()) {
- notifications[type] = std::make_shared<T>(value);
+ notifications[type] = std::make_shared<T>(value, std::move(record.contactRecord));
return true;
}
}
else if (value > 0) {
- notifications[type] = std::make_shared<T>(value);
+ notifications[type] = std::make_shared<T>(value, std::move(record.contactRecord));
return true;
}
return false;
@@ 38,15 41,15 @@ void NotificationProvider::handle(db::query::notifications::GetAllResult *msg)
auto records = *msg->getResult();
bool notificationsChanged = false;
- for (auto record : records) {
+ for (auto &&record : records) {
switch (record.key) {
case NotificationsRecord::Key::Calls:
notificationsChanged |=
- handleNotSeenWithCounter<NotificationType::NotSeenCall, NotSeenCallNotification>(record.value);
+ handleNotSeenWithCounter<NotificationType::NotSeenCall, NotSeenCallNotification>(std::move(record));
break;
case NotificationsRecord::Key::Sms:
notificationsChanged |=
- handleNotSeenWithCounter<NotificationType::NotSeenSms, NotSeenSMSNotification>(record.value);
+ handleNotSeenWithCounter<NotificationType::NotSeenSms, NotSeenSMSNotification>(std::move(record));
break;
default:
break;
M module-apps/notifications/NotificationProvider.hpp => module-apps/notifications/NotificationProvider.hpp +3 -1
@@ 11,6 11,8 @@ namespace sys
class Service;
}
+class NotificationsRecord;
+
namespace db
{
class NotificationMessage;
@@ 25,7 27,7 @@ namespace notifications
class NotificationProvider
{
- template <NotificationType type, typename T> bool handleNotSeenWithCounter(unsigned int value);
+ template <NotificationType type, typename T> bool handleNotSeenWithCounter(NotificationsRecord &&record);
public:
explicit NotificationProvider(sys::Service *ownerService);
M module-apps/notifications/NotificationsModel.cpp => module-apps/notifications/NotificationsModel.cpp +1 -1
@@ 65,7 65,7 @@ auto NotificationsModel::create(const notifications::NotSeenCallNotification *no
utils::to_string(notification->getValue()));
if (notification->hasRecord()) {
const auto &record = notification->getRecord();
- item->setName(record->getFormattedName());
+ item->setName(record.getFormattedName());
}
else {
item->setName(utils::translate("app_desktop_missed_calls"), true);
M module-db/Databases/NotificationsDB.hpp => module-db/Databases/NotificationsDB.hpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 9,7 9,7 @@
class NotificationsDB : public Database
{
public:
- NotificationsDB(const char *name);
+ explicit NotificationsDB(const char *name);
virtual ~NotificationsDB() = default;
NotificationsTable notifications;
M module-db/Interface/NotificationsRecord.cpp => module-db/Interface/NotificationsRecord.cpp +51 -32
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "NotificationsRecord.hpp"
@@ 6,15 6,17 @@
#include "module-db/queries/notifications/QueryNotificationsIncrement.hpp"
#include "module-db/queries/notifications/QueryNotificationsClear.hpp"
#include "module-db/queries/notifications/QueryNotificationsGetAll.hpp"
+#include "Databases/NotificationsDB.hpp"
#include <log/log.hpp>
#include <Utils.hpp>
#include <cassert>
#include <vector>
+#include <gsl_assert>
-NotificationsRecord::NotificationsRecord(const NotificationsTableRow &tableRow)
- : Record{tableRow.ID}, value{tableRow.value}
+NotificationsRecord::NotificationsRecord(const NotificationsTableRow &tableRow, std::optional<ContactRecord> record)
+ : Record{tableRow.ID}, value{tableRow.value}, contactRecord{std::move(record)}
{
if (tableRow.key > static_cast<uint32_t>(Key::NotValidKey) &&
tableRow.key < static_cast<uint32_t>(Key::NumberOfKeys)) {
@@ 26,16 28,6 @@ NotificationsRecord::NotificationsRecord(const NotificationsTableRow &tableRow)
ID = DB_ID_NONE;
}
-bool NotificationsRecord::isValidRecord() const
-{
- return isValid() && gotValidKey();
-}
-
-bool NotificationsRecord::gotValidKey() const
-{
- return isValidKey(key);
-}
-
bool NotificationsRecord::isValidKey(Key key)
{
return key != Key::NotValidKey && key != Key::NumberOfKeys;
@@ 44,13 36,18 @@ bool NotificationsRecord::isValidKey(Key key)
std::ostream &operator<<(std::ostream &out, const NotificationsRecord &rec)
{
out << " <id> " << rec.ID << " <key> " << static_cast<int>(rec.key) << " <value> " << rec.value;
-
+ if (rec.contactRecord.has_value()) {
+ out << " <contact_id> " << rec.contactRecord.value().ID;
+ }
return out;
}
-NotificationsRecordInterface::NotificationsRecordInterface(NotificationsDB *notificationsDb)
- : notificationsDb(notificationsDb)
-{}
+NotificationsRecordInterface::NotificationsRecordInterface(NotificationsDB *notificationsDb,
+ ContactRecordInterface *contactsDb)
+ : notificationsDb(notificationsDb), contactsDb(contactsDb)
+{
+ Expects(contactsDb != nullptr);
+}
bool NotificationsRecordInterface::Add(const NotificationsRecord &rec)
{
@@ 79,7 76,7 @@ std::unique_ptr<std::vector<NotificationsRecord>> NotificationsRecordInterface::
auto records = std::make_unique<std::vector<NotificationsRecord>>();
for (auto &r : rows) {
- records->push_back(NotificationsRecord{r});
+ records->push_back(NotificationsRecord{r, getContactRecord(r.contactID)});
}
return records;
@@ 92,8 89,10 @@ bool NotificationsRecordInterface::Update(const NotificationsRecord &rec)
return false;
}
- return notificationsDb->notifications.update(
- NotificationsTableRow{{.ID = rec.ID}, .key = static_cast<uint32_t>(rec.key), .value = rec.value});
+ uint32_t contactId = rec.contactRecord.has_value() ? rec.contactRecord.value().ID : DB_ID_NONE;
+
+ return notificationsDb->notifications.update(NotificationsTableRow{
+ {.ID = rec.ID}, .key = static_cast<uint32_t>(rec.key), .value = rec.value, .contactID = contactId});
}
bool NotificationsRecordInterface::RemoveByID(uint32_t id)
@@ 109,10 108,20 @@ bool NotificationsRecordInterface::RemoveByField(NotificationsRecordField field,
return false;
}
+std::optional<ContactRecord> NotificationsRecordInterface::getContactRecord(uint32_t id) const
+{
+ if (id != DB_ID_NONE) {
+ if (auto contactRecord = contactsDb->GetByIdWithTemporary(id); contactRecord.isValid()) {
+ return std::make_optional(std::move(contactRecord));
+ }
+ }
+ return std::nullopt;
+}
NotificationsRecord NotificationsRecordInterface::GetByID(uint32_t id)
{
- return NotificationsRecord{notificationsDb->notifications.getById(id)};
+ auto tableRow = notificationsDb->notifications.getById(id);
+ return NotificationsRecord{tableRow, getContactRecord(tableRow.contactID)};
}
uint32_t NotificationsRecordInterface::GetCount()
@@ 126,8 135,8 @@ NotificationsRecord NotificationsRecordInterface::GetByKey(NotificationsRecord::
return NotificationsRecord();
}
- NotificationsTableRow notificationsTableRow = notificationsDb->notifications.GetByKey(static_cast<uint32_t>(key));
- return NotificationsRecord{notificationsTableRow};
+ auto tableRow = notificationsDb->notifications.getByKey(static_cast<uint32_t>(key));
+ return NotificationsRecord{tableRow, getContactRecord(tableRow.contactID)};
}
std::unique_ptr<db::QueryResult> NotificationsRecordInterface::runQuery(std::shared_ptr<db::Query> query)
@@ 150,17 159,28 @@ std::unique_ptr<db::QueryResult> NotificationsRecordInterface::runQuery(std::sha
std::unique_ptr<db::query::notifications::GetResult> NotificationsRecordInterface::runQueryImpl(
const db::query::notifications::Get *query)
{
- auto value = GetByKey(query->key);
- return std::make_unique<db::query::notifications::GetResult>(value);
+ auto value = GetByKey(query->getKey());
+ return std::make_unique<db::query::notifications::GetResult>(std::move(value));
}
std::unique_ptr<db::query::notifications::IncrementResult> NotificationsRecordInterface::runQueryImpl(
const db::query::notifications::Increment *query)
{
auto ret = false;
-
- auto record = GetByKey(query->key);
- if (record.isValid() && record.key == query->key) {
+ if (auto record = GetByKey(query->getKey()); record.isValid()) {
+ auto ¤tContactRecord = record.contactRecord;
+ if (auto numberMatch = contactsDb->MatchByNumber(query->getNumber()); numberMatch.has_value()) {
+ if (record.value == 0) {
+ currentContactRecord = std::move(numberMatch.value().contact);
+ }
+ else if (currentContactRecord.has_value() &&
+ numberMatch.value().contactId != currentContactRecord.value().ID) {
+ currentContactRecord.reset();
+ }
+ }
+ else {
+ currentContactRecord.reset();
+ }
record.value++;
ret = Update(record);
}
@@ 171,11 191,10 @@ std::unique_ptr<db::query::notifications::ClearResult> NotificationsRecordInterf
const db::query::notifications::Clear *query)
{
auto ret = false;
-
- auto record = GetByKey(query->key);
- if (record.isValid() && record.key == query->key) {
+ if (auto record = GetByKey(query->getKey()); record.isValid()) {
record.value = 0;
- ret = Update(record);
+ record.contactRecord.reset();
+ ret = Update(record);
}
return std::make_unique<db::query::notifications::ClearResult>(ret);
}
M module-db/Interface/NotificationsRecord.hpp => module-db/Interface/NotificationsRecord.hpp +12 -10
@@ 1,18 1,21 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
#include "Common/Common.hpp"
-#include "Databases/NotificationsDB.hpp"
+#include "module-db/Tables/NotificationsTable.hpp"
#include "Record.hpp"
+#include "Interface/ContactRecord.hpp"
#include <utf8/UTF8.hpp>
-
#include <cstdint>
#include <vector>
// fw declarations
+class ContactRecordInterface;
+class NotificationsDB;
+
namespace db::query::notifications
{
class Get;
@@ 37,15 40,13 @@ struct NotificationsRecord : public Record
Key key = Key::NotValidKey;
uint32_t value = 0;
+ std::optional<ContactRecord> contactRecord;
friend std::ostream &operator<<(std::ostream &out, const NotificationsRecord &point);
NotificationsRecord() = default;
- ~NotificationsRecord() = default;
- explicit NotificationsRecord(const NotificationsTableRow &tableRow);
-
- bool isValidRecord() const;
- bool gotValidKey() const;
+ explicit NotificationsRecord(const NotificationsTableRow &tableRow,
+ std::optional<ContactRecord> record = std::nullopt);
static bool isValidKey(Key key);
};
@@ 58,8 59,7 @@ enum class NotificationsRecordField
class NotificationsRecordInterface : public RecordInterface<NotificationsRecord, NotificationsRecordField>
{
public:
- explicit NotificationsRecordInterface(NotificationsDB *notificationsDb);
- virtual ~NotificationsRecordInterface() = default;
+ NotificationsRecordInterface(NotificationsDB *notificationsDb, ContactRecordInterface *contactsDb);
bool Add(const NotificationsRecord &rec) override final;
bool RemoveByID(uint32_t id) override final;
@@ 79,7 79,9 @@ class NotificationsRecordInterface : public RecordInterface<NotificationsRecord,
private:
NotificationsDB *notificationsDb = nullptr;
+ ContactRecordInterface *contactsDb = nullptr;
+ std::optional<ContactRecord> getContactRecord(uint32_t id) const;
std::unique_ptr<db::query::notifications::GetResult> runQueryImpl(const db::query::notifications::Get *query);
std::unique_ptr<db::query::notifications::IncrementResult> runQueryImpl(
const db::query::notifications::Increment *query);
M module-db/Tables/NotificationsTable.cpp => module-db/Tables/NotificationsTable.cpp +17 -10
@@ 1,12 1,11 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "NotificationsTable.hpp"
-#include "module-db/Interface/NotificationsRecord.hpp"
+#include "Database/Database.hpp"
#include <log/log.hpp>
#include <Utils.hpp>
-
#include <cassert>
NotificationsTable::NotificationsTable(Database *db) : Table(db)
@@ 19,7 18,10 @@ bool NotificationsTable::create()
bool NotificationsTable::add(NotificationsTableRow entry)
{
- return db->execute("INSERT or IGNORE INTO notifications (key, value) VALUES (%lu, %lu);", entry.key, entry.value);
+ return db->execute("INSERT or IGNORE INTO notifications (key, value, contact_id) VALUES (%lu, %lu, %lu);",
+ entry.key,
+ entry.value,
+ entry.contactID);
}
bool NotificationsTable::removeById(uint32_t id)
@@ 42,8 44,11 @@ bool NotificationsTable::removeByField(NotificationsTableFields field, const cha
bool NotificationsTable::update(NotificationsTableRow entry)
{
- return db->execute(
- "UPDATE notifications SET key = %lu, value = %lu WHERE _id = %lu;", entry.key, entry.value, entry.ID);
+ return db->execute("UPDATE notifications SET key = %lu, value = %lu, contact_id = %lu WHERE _id = %lu;",
+ entry.key,
+ entry.value,
+ entry.contactID,
+ entry.ID);
}
NotificationsTableRow NotificationsTable::getById(uint32_t id)
@@ 59,12 64,12 @@ NotificationsTableRow NotificationsTable::getById(uint32_t id)
return NotificationsTableRow{
(*retQuery)[0].getUInt32(), // ID
(*retQuery)[1].getUInt32(), // key
- (*retQuery)[2].getUInt32() // value
-
+ (*retQuery)[2].getUInt32(), // value
+ (*retQuery)[3].getUInt32() // contactID
};
}
-NotificationsTableRow NotificationsTable::GetByKey(uint32_t key)
+NotificationsTableRow NotificationsTable::getByKey(uint32_t key)
{
auto retQuery = db->query("SELECT * FROM notifications WHERE key= %u;", key);
@@ 77,7 82,8 @@ NotificationsTableRow NotificationsTable::GetByKey(uint32_t key)
return NotificationsTableRow{
(*retQuery)[0].getUInt32(), // ID
(*retQuery)[1].getUInt32(), // key
- (*retQuery)[2].getUInt32() // value
+ (*retQuery)[2].getUInt32(), // value
+ (*retQuery)[3].getUInt32() // contactID
};
}
@@ 96,6 102,7 @@ std::vector<NotificationsTableRow> NotificationsTable::getLimitOffset(uint32_t o
(*retQuery)[0].getUInt32(), // ID
(*retQuery)[1].getUInt32(), // key
(*retQuery)[2].getUInt32(), // value
+ (*retQuery)[3].getUInt32() // contactID
});
} while (retQuery->nextRow());
M module-db/Tables/NotificationsTable.hpp => module-db/Tables/NotificationsTable.hpp +5 -3
@@ 1,18 1,20 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
#include "Table.hpp"
#include "Record.hpp"
-#include "Database/Database.hpp"
#include "utf8/UTF8.hpp"
#include "Common/Common.hpp"
+class Database;
+
struct NotificationsTableRow : public Record
{
uint32_t key = 0;
uint32_t value = 0;
+ uint32_t contactID = DB_ID_NONE;
};
enum class NotificationsTableFields
@@ 32,7 34,7 @@ class NotificationsTable : public Table<NotificationsTableRow, NotificationsTabl
bool removeByField(NotificationsTableFields field, const char *str) override final;
bool update(NotificationsTableRow entry) override final;
NotificationsTableRow getById(uint32_t id) override final;
- NotificationsTableRow GetByKey(uint32_t key);
+ NotificationsTableRow getByKey(uint32_t key);
uint32_t count() override final;
uint32_t countByFieldId(const char *field, uint32_t id) override final;
std::vector<NotificationsTableRow> getLimitOffset(uint32_t offset, uint32_t limit) override final;
M module-db/queries/calllog/QueryCalllogSetAllRead.hpp => module-db/queries/calllog/QueryCalllogSetAllRead.hpp +2 -3
@@ 1,9 1,8 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
-#include "Interface/NotificationsRecord.hpp"
#include <Common/Query.hpp>
#include <string>
@@ 20,7 19,7 @@ namespace db::query::calllog
class SetAllReadResult : public QueryResult
{
public:
- SetAllReadResult(bool ret);
+ explicit SetAllReadResult(bool ret);
[[nodiscard]] auto debugInfo() const -> std::string override;
const bool ret = true;
M module-db/queries/notifications/QueryNotificationsClear.cpp => module-db/queries/notifications/QueryNotificationsClear.cpp +6 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "QueryNotificationsClear.hpp"
@@ 13,6 13,11 @@ namespace db::query::notifications
return "Clear";
}
+ auto Clear::getKey() const noexcept -> NotificationsRecord::Key
+ {
+ return key;
+ }
+
ClearResult::ClearResult(bool ret) : ret(ret)
{}
M module-db/queries/notifications/QueryNotificationsClear.hpp => module-db/queries/notifications/QueryNotificationsClear.hpp +7 -5
@@ 1,9 1,9 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
-#include "module-db/Interface/NotificationsRecord.hpp"
+#include <Interface/NotificationsRecord.hpp>
#include <Common/Query.hpp>
#include <string>
@@ 11,10 11,12 @@ namespace db::query::notifications
{
class Clear : public Query
{
- public:
const NotificationsRecord::Key key;
- Clear(NotificationsRecord::Key key);
+ public:
+ explicit Clear(NotificationsRecord::Key key);
+
+ [[nodiscard]] auto getKey() const noexcept -> NotificationsRecord::Key;
[[nodiscard]] auto debugInfo() const -> std::string override;
};
@@ 23,7 25,7 @@ namespace db::query::notifications
bool ret;
public:
- ClearResult(bool ret);
+ explicit ClearResult(bool ret);
[[nodiscard]] auto getResult() const -> bool;
[[nodiscard]] auto debugInfo() const -> std::string override;
M module-db/queries/notifications/QueryNotificationsGet.cpp => module-db/queries/notifications/QueryNotificationsGet.cpp +7 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "QueryNotificationsGet.hpp"
@@ 13,7 13,12 @@ namespace db::query::notifications
return "Get";
}
- GetResult::GetResult(NotificationsRecord record) : record(record)
+ auto Get::getKey() const noexcept -> NotificationsRecord::Key
+ {
+ return key;
+ }
+
+ GetResult::GetResult(NotificationsRecord record) : record(std::move(record))
{}
auto GetResult::getResult() const -> NotificationsRecord
M module-db/queries/notifications/QueryNotificationsGet.hpp => module-db/queries/notifications/QueryNotificationsGet.hpp +7 -5
@@ 1,9 1,9 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
-#include "module-db/Interface/NotificationsRecord.hpp"
+#include <Interface/NotificationsRecord.hpp>
#include <Common/Query.hpp>
#include <string>
@@ 11,10 11,12 @@ namespace db::query::notifications
{
class Get : public Query
{
- public:
const NotificationsRecord::Key key;
- Get(NotificationsRecord::Key key);
+ public:
+ explicit Get(NotificationsRecord::Key key);
+
+ [[nodiscard]] auto getKey() const noexcept -> NotificationsRecord::Key;
[[nodiscard]] auto debugInfo() const -> std::string override;
};
@@ 23,7 25,7 @@ namespace db::query::notifications
NotificationsRecord record;
public:
- GetResult(NotificationsRecord record);
+ explicit GetResult(NotificationsRecord record);
[[nodiscard]] auto getResult() const -> NotificationsRecord;
[[nodiscard]] auto debugInfo() const -> std::string override;
M module-db/queries/notifications/QueryNotificationsGetAll.hpp => module-db/queries/notifications/QueryNotificationsGetAll.hpp +3 -3
@@ 1,9 1,9 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
-#include "module-db/Interface/NotificationsRecord.hpp"
+#include <Interface/NotificationsRecord.hpp>
#include <Common/Query.hpp>
#include <string>
@@ 22,7 22,7 @@ namespace db::query::notifications
std::unique_ptr<std::vector<NotificationsRecord>> records;
public:
- GetAllResult(std::unique_ptr<std::vector<NotificationsRecord>> records);
+ explicit GetAllResult(std::unique_ptr<std::vector<NotificationsRecord>> records);
[[nodiscard]] auto getResult() -> std::unique_ptr<std::vector<NotificationsRecord>>;
[[nodiscard]] auto debugInfo() const -> std::string override;
M module-db/queries/notifications/QueryNotificationsIncrement.cpp => module-db/queries/notifications/QueryNotificationsIncrement.cpp +13 -3
@@ 1,13 1,23 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "QueryNotificationsIncrement.hpp"
namespace db::query::notifications
{
- Increment::Increment(NotificationsRecord::Key key) : Query(Query::Type::Update), key(key)
+ Increment::Increment(NotificationsRecord::Key key, const utils::PhoneNumber::View &number)
+ : Query(Query::Type::Update), key(key), number(number)
{}
+ auto Increment::getKey() const noexcept -> NotificationsRecord::Key
+ {
+ return key;
+ }
+ auto Increment::getNumber() const noexcept -> const utils::PhoneNumber::View &
+ {
+ return number;
+ }
+
auto Increment::debugInfo() const -> std::string
{
return "Increment";
@@ 16,7 26,7 @@ namespace db::query::notifications
IncrementResult::IncrementResult(bool ret) : ret(ret)
{}
- auto IncrementResult::getResult() const -> bool
+ auto IncrementResult::getResult() const noexcept -> bool
{
return ret;
}
M module-db/queries/notifications/QueryNotificationsIncrement.hpp => module-db/queries/notifications/QueryNotificationsIncrement.hpp +12 -6
@@ 1,19 1,25 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
-#include "module-db/Interface/NotificationsRecord.hpp"
+#include <Interface/NotificationsRecord.hpp>
#include <Common/Query.hpp>
#include <string>
+#include <PhoneNumber.hpp>
namespace db::query::notifications
{
class Increment : public Query
{
- public:
const NotificationsRecord::Key key;
- Increment(NotificationsRecord::Key key);
+ const utils::PhoneNumber::View number;
+
+ public:
+ Increment(NotificationsRecord::Key key, const utils::PhoneNumber::View &number);
+
+ [[nodiscard]] auto getKey() const noexcept -> NotificationsRecord::Key;
+ [[nodiscard]] auto getNumber() const noexcept -> const utils::PhoneNumber::View &;
[[nodiscard]] auto debugInfo() const -> std::string override;
};
@@ 23,8 29,8 @@ namespace db::query::notifications
bool ret;
public:
- IncrementResult(bool ret);
- [[nodiscard]] auto getResult() const -> bool;
+ explicit IncrementResult(bool ret);
+ [[nodiscard]] auto getResult() const noexcept -> bool;
[[nodiscard]] auto debugInfo() const -> std::string override;
};
M module-db/tests/CMakeLists.txt => module-db/tests/CMakeLists.txt +2 -2
@@ 22,8 22,8 @@ add_catch2_executable(
#EventsTable_tests.cpp
NotesRecord_tests.cpp
NotesTable_tests.cpp
- #NotificationsRecord_tests.cpp
- #NotificationsTable_tests.cpp
+ NotificationsRecord_tests.cpp
+ NotificationsTable_tests.cpp
QueryInterface.cpp
SMSRecord_tests.cpp
SMSTable_tests.cpp
M module-db/tests/NotificationsRecord_tests.cpp => module-db/tests/NotificationsRecord_tests.cpp +132 -23
@@ 1,15 1,18 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+#include "common.hpp"
#include <catch2/catch.hpp>
-#include "Interface/NotificationsRecord.hpp"
-#include "Database/Database.hpp"
-#include "Databases/NotificationsDB.hpp"
-#include "module-db/queries/notifications/QueryNotificationsGet.hpp"
-#include "module-db/queries/notifications/QueryNotificationsIncrement.hpp"
-#include "module-db/queries/notifications/QueryNotificationsClear.hpp"
-#include "module-db/queries/notifications/QueryNotificationsGetAll.hpp"
+#include <Interface/NotificationsRecord.hpp>
+#include <Interface/ContactRecord.hpp>
+#include <Database/Database.hpp>
+#include <Databases/NotificationsDB.hpp>
+#include <Databases/ContactsDB.hpp>
+#include <queries/notifications/QueryNotificationsGet.hpp>
+#include <queries/notifications/QueryNotificationsIncrement.hpp>
+#include <queries/notifications/QueryNotificationsClear.hpp>
+#include <queries/notifications/QueryNotificationsGetAll.hpp>
#include <filesystem>
@@ 21,16 24,6 @@
TEST_CASE("Notifications Record tests")
{
- Database::initialize();
-
- const auto notificationsPath = (std::filesystem::path{"sys/user"} / "notifications.db");
- if (std::filesystem::exists(notificationsPath)) {
- REQUIRE(std::filesystem::remove(notificationsPath));
- }
-
- NotificationsDB notificationsDb{notificationsPath.c_str()};
-
- REQUIRE(notificationsDb.isInitialized());
SECTION("Default Constructor")
{
@@ 39,27 32,43 @@ TEST_CASE("Notifications Record tests")
REQUIRE(testRec.ID == DB_ID_NONE);
REQUIRE(testRec.key == NotificationsRecord::Key::NotValidKey);
REQUIRE(testRec.value == 0);
+ REQUIRE_FALSE(testRec.contactRecord.has_value());
}
SECTION("Constructor from NotificationsTableRow")
{
NotificationsTableRow tableRow{
{.ID = 10}, .key = static_cast<uint32_t>(NotificationsRecord::Key::Calls), .value = 2};
-
NotificationsRecord testRec(tableRow);
REQUIRE(testRec.isValid());
REQUIRE(testRec.ID == 10);
REQUIRE(testRec.key == NotificationsRecord::Key::Calls);
REQUIRE(testRec.value == 2);
+ REQUIRE_FALSE(testRec.contactRecord.has_value());
}
+ Database::initialize();
+ const auto notificationsPath = (std::filesystem::path{"sys/user"} / "notifications.db");
+ const auto contactsPath = (std::filesystem::path{"sys/user"} / "contacts.db");
+ RemoveDbFiles(notificationsPath.stem());
+ RemoveDbFiles(contactsPath.stem());
+
+ NotificationsDB notificationsDb{notificationsPath.c_str()};
+ ContactsDB contactsDb{contactsPath.c_str()};
+ REQUIRE(notificationsDb.isInitialized());
+ REQUIRE(contactsDb.isInitialized());
+
const auto notificationsCount = notificationsDb.notifications.count() + 1;
// clear notifications table
for (std::size_t id = 1; id <= notificationsCount; id++) {
REQUIRE(notificationsDb.notifications.removeById(id));
}
- NotificationsRecordInterface notificationsRecordInterface(¬ificationsDb);
+
+ ContactRecordInterface contactRecordInterface(&contactsDb);
+ NotificationsRecordInterface notificationsRecordInterface(¬ificationsDb, &contactRecordInterface);
+ REQUIRE(contactRecordInterface.GetCount() == 0);
REQUIRE(notificationsRecordInterface.GetCount() == 0);
+
NotificationsTableRow callsRow{
{.ID = DB_ID_NONE}, .key = static_cast<uint32_t>(NotificationsRecord::Key::Calls), .value = 0};
@@ 80,12 89,14 @@ TEST_CASE("Notifications Record tests")
REQUIRE(callsNotifications.ID == 1);
REQUIRE(callsNotifications.key == NotificationsRecord::Key::Calls);
REQUIRE(callsNotifications.value == 0);
+ REQUIRE_FALSE(callsNotifications.contactRecord.has_value());
auto smsNotifications = notificationsRecordInterface.GetByID(2);
REQUIRE(smsNotifications.isValid());
REQUIRE(smsNotifications.ID == 2);
REQUIRE(smsNotifications.key == NotificationsRecord::Key::Sms);
REQUIRE(smsNotifications.value == 0);
+ REQUIRE_FALSE(smsNotifications.contactRecord.has_value());
}
SECTION("Get entry by key")
@@ 180,7 191,9 @@ TEST_CASE("Notifications Record tests")
REQUIRE(entryPost.value == entryPre.value);
}
- auto getByKey = [&](NotificationsRecord::Key key, uint32_t val) {
+ auto getByKey = [&](NotificationsRecord::Key key,
+ uint32_t expectedValue,
+ const std::optional<ContactRecord> &expectedContactRecord = std::nullopt) {
auto query = std::make_shared<db::query::notifications::Get>(key);
auto ret = notificationsRecordInterface.runQuery(query);
auto result = dynamic_cast<db::query::notifications::GetResult *>(ret.get());
@@ 188,11 201,16 @@ TEST_CASE("Notifications Record tests")
auto record = result->getResult();
REQUIRE(record.isValid());
REQUIRE(record.key == key);
- REQUIRE(record.value == val);
+ REQUIRE(record.value == expectedValue);
+ REQUIRE(record.contactRecord.has_value() == expectedContactRecord.has_value());
+ if (expectedContactRecord.has_value()) {
+ REQUIRE(record.contactRecord.value().ID == expectedContactRecord.value().ID);
+ }
};
- auto incrementByKey = [&](NotificationsRecord::Key key) {
- auto query = std::make_shared<db::query::notifications::Increment>(key);
+ auto incrementByKey = [&](NotificationsRecord::Key key, const std::string &phoneNumber = "+48500500500") {
+ utils::PhoneNumber number(phoneNumber);
+ auto query = std::make_shared<db::query::notifications::Increment>(key, number.getView());
auto ret = notificationsRecordInterface.runQuery(query);
auto result = dynamic_cast<db::query::notifications::IncrementResult *>(ret.get());
REQUIRE(result != nullptr);
@@ 253,5 271,96 @@ TEST_CASE("Notifications Record tests")
REQUIRE(records->size() == numberOfNotifcations);
}
+ SECTION("Notification DB and Contact DB connection tests")
+ {
+ const std::string primaryNameTest_1 = "PrimaryTestNameOne";
+ const std::string numberUserTest_1 = "600123456";
+ ContactRecord testContactRecord_1;
+ testContactRecord_1.primaryName = primaryNameTest_1;
+ testContactRecord_1.numbers =
+ std::vector<ContactRecord::Number>({ContactRecord::Number(utils::PhoneNumber(numberUserTest_1).getView())});
+
+ const std::string primaryNameTest_2 = "PrimaryTestNameTwo";
+ const std::string numberUserTest_2 = "600600600";
+ ContactRecord testContactRecord_2;
+ testContactRecord_2.primaryName = primaryNameTest_2;
+ testContactRecord_2.numbers =
+ std::vector<ContactRecord::Number>({ContactRecord::Number(utils::PhoneNumber(numberUserTest_2).getView())});
+
+ REQUIRE(contactRecordInterface.Add(testContactRecord_1));
+ REQUIRE(contactRecordInterface.Add(testContactRecord_2));
+
+ const auto someUnknownNumber = "500200300";
+ const auto noNotificationExpected = 0;
+ const auto contactNotExpected = std::nullopt;
+
+ SECTION("Tests preconditions")
+ {
+ getByKey(NotificationsRecord::Key::Calls, noNotificationExpected);
+ }
+
+ SECTION("Single call notification from unknown number")
+ {
+ const auto expectedNotificationValue = 1;
+ incrementByKey(NotificationsRecord::Key::Calls, someUnknownNumber);
+ getByKey(NotificationsRecord::Key::Calls, expectedNotificationValue, contactNotExpected);
+ }
+
+ SECTION("Single call notification from known number")
+ {
+ const auto expectedNotificationValue = 1;
+ incrementByKey(NotificationsRecord::Key::Calls, numberUserTest_1);
+ getByKey(NotificationsRecord::Key::Calls, expectedNotificationValue, testContactRecord_1);
+ clearByKey(NotificationsRecord::Key::Calls);
+ getByKey(NotificationsRecord::Key::Calls, noNotificationExpected, contactNotExpected);
+ }
+
+ SECTION("Multiple call notifications from single known number")
+ {
+ const auto expectedNotificationValue = 3;
+ for (int i = 0; i < expectedNotificationValue; i++)
+ incrementByKey(NotificationsRecord::Key::Calls, numberUserTest_1);
+ getByKey(NotificationsRecord::Key::Calls, expectedNotificationValue, testContactRecord_1);
+ clearByKey(NotificationsRecord::Key::Calls);
+ getByKey(NotificationsRecord::Key::Calls, noNotificationExpected, contactNotExpected);
+ }
+
+ SECTION("Multiple call notifications from multiple known numbers")
+ {
+ const auto expectedNotificationValue = 2 * 3;
+ for (int i = 0; i < expectedNotificationValue / 2; i++) {
+ incrementByKey(NotificationsRecord::Key::Calls, numberUserTest_1);
+ incrementByKey(NotificationsRecord::Key::Calls, numberUserTest_2);
+ }
+ getByKey(NotificationsRecord::Key::Calls, expectedNotificationValue, contactNotExpected);
+ clearByKey(NotificationsRecord::Key::Calls);
+ getByKey(NotificationsRecord::Key::Calls, noNotificationExpected, contactNotExpected);
+ }
+
+ SECTION("Multiple call notifications in sequence of known-unknown-known numbers")
+ {
+ incrementByKey(NotificationsRecord::Key::Calls, numberUserTest_1);
+ getByKey(NotificationsRecord::Key::Calls, 1, testContactRecord_1);
+
+ incrementByKey(NotificationsRecord::Key::Calls, someUnknownNumber);
+ getByKey(NotificationsRecord::Key::Calls, 2, contactNotExpected);
+
+ incrementByKey(NotificationsRecord::Key::Calls, numberUserTest_1);
+ getByKey(NotificationsRecord::Key::Calls, 3, contactNotExpected);
+ }
+
+ SECTION("Multiple call notifications in sequence of unknown-known-unknown numbers")
+ {
+ incrementByKey(NotificationsRecord::Key::Calls, someUnknownNumber);
+ getByKey(NotificationsRecord::Key::Calls, 1, contactNotExpected);
+
+ incrementByKey(NotificationsRecord::Key::Calls, numberUserTest_1);
+ getByKey(NotificationsRecord::Key::Calls, 2, contactNotExpected);
+
+ incrementByKey(NotificationsRecord::Key::Calls, someUnknownNumber);
+ getByKey(NotificationsRecord::Key::Calls, 3, contactNotExpected);
+ }
+ }
+
Database::deinitialize();
}
M module-db/tests/NotificationsTable_tests.cpp => module-db/tests/NotificationsTable_tests.cpp +15 -11
@@ 1,6 1,7 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+#include "common.hpp"
#include <catch2/catch.hpp>
#include "Database/Database.hpp"
@@ 17,12 18,8 @@
TEST_CASE("Notifications Table tests")
{
Database::initialize();
-
const auto notificationsPath = (std::filesystem::path{"sys/user"} / "notifications.db");
- if (std::filesystem::exists(notificationsPath)) {
- REQUIRE(std::filesystem::remove(notificationsPath));
- }
-
+ RemoveDbFiles(notificationsPath.stem());
NotificationsDB notificationsDb{notificationsPath.c_str()};
REQUIRE(notificationsDb.isInitialized());
@@ 50,11 47,12 @@ TEST_CASE("Notifications Table tests")
REQUIRE(testRow.ID == DB_ID_NONE);
REQUIRE(testRow.key == 0);
REQUIRE(testRow.value == 0);
+ REQUIRE(testRow.contactID == DB_ID_NONE);
REQUIRE_FALSE(testRow.isValid());
}
REQUIRE(notificationsTbl.add({{.ID = 0}, .key = 3, .value = 8}));
- REQUIRE(notificationsTbl.add({{.ID = 0}, .key = 4, .value = 16}));
+ REQUIRE(notificationsTbl.add({{.ID = 0}, .key = 4, .value = 16, .contactID = 100}));
REQUIRE(notificationsTbl.count() == 4);
@@ 64,6 62,7 @@ TEST_CASE("Notifications Table tests")
REQUIRE(entry.ID == 4);
REQUIRE(entry.key == 4);
REQUIRE(entry.value == 16);
+ REQUIRE(entry.contactID == 100);
REQUIRE(entry.isValid());
}
@@ 73,6 72,7 @@ TEST_CASE("Notifications Table tests")
REQUIRE(entry.ID == 3);
REQUIRE(entry.key == 3);
REQUIRE(entry.value == 8);
+ REQUIRE(entry.contactID == DB_ID_NONE);
REQUIRE(entry.isValid());
}
@@ 93,11 93,12 @@ TEST_CASE("Notifications Table tests")
SECTION("Entry update")
{
- REQUIRE(notificationsTbl.update({{.ID = 3}, .key = 100, .value = 200}));
+ REQUIRE(notificationsTbl.update({{.ID = 3}, .key = 100, .value = 200, .contactID = 300}));
auto entry = notificationsTbl.getById(3);
REQUIRE(entry.ID == 3);
REQUIRE(entry.key == 100);
REQUIRE(entry.value == 200);
+ REQUIRE(entry.contactID == 300);
}
SECTION("Get entry - invalid ID")
@@ 107,14 108,16 @@ TEST_CASE("Notifications Table tests")
REQUIRE(entry.ID == DB_ID_NONE);
REQUIRE(entry.key == 0);
REQUIRE(entry.value == 0);
+ REQUIRE(entry.ID == DB_ID_NONE);
}
SECTION("Get by invalid key")
{
- auto entry = notificationsTbl.getById(100);
+ auto entry = notificationsTbl.getByKey(100);
REQUIRE(entry.ID == DB_ID_NONE);
REQUIRE(entry.key == 0);
REQUIRE(entry.value == 0);
+ REQUIRE(entry.ID == DB_ID_NONE);
REQUIRE_FALSE(entry.isValid());
}
@@ 158,13 161,14 @@ TEST_CASE("Notifications Table tests")
SECTION("Check uniqueness")
{
- REQUIRE(notificationsTbl.add({{.ID = 0}, .key = 3, .value = 100}));
+ REQUIRE(notificationsTbl.add({{.ID = 0}, .key = 3, .value = 100, .contactID = 200}));
REQUIRE(notificationsTbl.count() == 4);
- auto entry = notificationsTbl.getById(3);
+ auto entry = notificationsTbl.getByKey(3);
+ REQUIRE(entry.isValid());
REQUIRE(entry.ID == 3);
REQUIRE(entry.key == 3);
REQUIRE(entry.value == 8);
- REQUIRE(entry.isValid());
+ REQUIRE(entry.contactID == DB_ID_NONE);
}
Database::deinitialize();
M module-gui/gui/widgets/Style.hpp => module-gui/gui/widgets/Style.hpp +2 -1
@@ 249,7 249,8 @@ namespace style
inline constexpr auto spanSize = 8;
inline constexpr auto digitSize = 16;
inline constexpr auto iconWidth = 35;
- inline constexpr auto textMaxWidth = 250;
+ inline constexpr auto textMinWidth = 250;
+ inline constexpr auto textMaxWidth = 350;
inline constexpr auto itemHeight = 55;
namespace model
M module-services/service-cellular/ServiceCellular.cpp => module-services/service-cellular/ServiceCellular.cpp +18 -16
@@ 214,10 214,10 @@ ServiceCellular::ServiceCellular()
ongoingCall.setEndCallAction([=](const CalllogRecord &rec) {
if (DBServiceAPI::CalllogUpdate(this, rec) && rec.type == CallType::CT_MISSED) {
- DBServiceAPI::GetQuery(
- this,
- db::Interface::Name::Notifications,
- std::make_unique<db::query::notifications::Increment>(NotificationsRecord::Key::Calls));
+ DBServiceAPI::GetQuery(this,
+ db::Interface::Name::Notifications,
+ std::make_unique<db::query::notifications::Increment>(
+ NotificationsRecord::Key::Calls, rec.phoneNumber));
}
return true;
});
@@ 1841,21 1841,23 @@ SMSRecord ServiceCellular::createSMSRecord(const UTF8 &decodedMessage,
bool ServiceCellular::dbAddSMSRecord(const SMSRecord &record)
{
- return DBServiceAPI::AddSMS(this, record, db::QueryCallback::fromFunction([this](auto response) {
- auto result = dynamic_cast<db::query::SMSAddResult *>(response);
- if (result == nullptr || !result->result) {
- return false;
- }
- onSMSReceived();
- return true;
- }));
+ return DBServiceAPI::AddSMS(
+ this, record, db::QueryCallback::fromFunction([this, number = record.number](auto response) {
+ auto result = dynamic_cast<db::query::SMSAddResult *>(response);
+ if (result == nullptr || !result->result) {
+ return false;
+ }
+ onSMSReceived(number);
+ return true;
+ }));
}
-void ServiceCellular::onSMSReceived()
+void ServiceCellular::onSMSReceived(const utils::PhoneNumber::View &number)
{
- DBServiceAPI::GetQuery(this,
- db::Interface::Name::Notifications,
- std::make_unique<db::query::notifications::Increment>(NotificationsRecord::Key::Sms));
+ DBServiceAPI::GetQuery(
+ this,
+ db::Interface::Name::Notifications,
+ std::make_unique<db::query::notifications::Increment>(NotificationsRecord::Key::Sms, number));
const auto guard = [&]() { return !phoneModeObserver->isInMode(sys::phone_modes::PhoneMode::DoNotDisturb); };
auto filePath = AudioServiceAPI::GetSound(this, audio::PlaybackType::TextMessageRingtone);
M module-services/service-cellular/service-cellular/ServiceCellular.hpp => module-services/service-cellular/service-cellular/ServiceCellular.hpp +1 -1
@@ 279,7 279,7 @@ class ServiceCellular : public sys::Service
const time_t messageDate,
const SMSType &smsType = SMSType::INBOX) const noexcept;
bool dbAddSMSRecord(const SMSRecord &record);
- void onSMSReceived();
+ void onSMSReceived(const utils::PhoneNumber::View &number);
[[nodiscard]] bool receiveAllMessages();
/// @}
M module-services/service-db/ServiceDB.cpp => module-services/service-db/ServiceDB.cpp +2 -1
@@ 263,7 263,8 @@ sys::ReturnCodes ServiceDB::InitHandler()
notesRecordInterface = std::make_unique<NotesRecordInterface>(notesDB.get());
calllogRecordInterface = std::make_unique<CalllogRecordInterface>(calllogDB.get(), contactsDB.get());
countryCodeRecordInterface = std::make_unique<CountryCodeRecordInterface>(countryCodesDB.get());
- notificationsRecordInterface = std::make_unique<NotificationsRecordInterface>(notificationsDB.get());
+ notificationsRecordInterface =
+ std::make_unique<NotificationsRecordInterface>(notificationsDB.get(), contactRecordInterface.get());
eventsRecordInterface = std::make_unique<EventsRecordInterface>(eventsDB.get());
quotesRecordInterface = std::make_unique<Quotes::QuotesAgent>(quotesDB.get());
M module-services/service-db/ServiceDB.hpp => module-services/service-db/ServiceDB.hpp +0 -1
@@ 19,7 19,6 @@
#include <Interface/CountryCodeRecord.hpp>
#include <Interface/EventsRecord.hpp>
#include <Interface/NotesRecord.hpp>
-#include <Interface/NotificationsRecord.hpp>
#include <Interface/SMSRecord.hpp>
#include <Interface/SMSTemplateRecord.hpp>
#include <Interface/ThreadRecord.hpp>