~aleteoryx/muditaos

2f8cda20f51681db2ba15ccc89caafd0ab60e87f — Marek Niepieklo 3 years ago 2e8d3dd
[MOS-143] Fix notifications for unread message/missed calls

Added Notifications Decrement query
Fixed updating notifications on home/lock screen
M module-apps/application-messages/windows/MessagesMainWindow.cpp => module-apps/application-messages/windows/MessagesMainWindow.cpp +0 -5
@@ 13,7 13,6 @@
#include <header/SearchAction.hpp>
#include <i18n/i18n.hpp>
#include <log/log.hpp>
#include <module-db/queries/notifications/QueryNotificationsClear.hpp>
#include <module-db/queries/messages/threads/QueryThreadGetByNumber.hpp>
#include <service-db/DBNotificationMessage.hpp>
#include <service-db/DBServiceAPI.hpp>


@@ 128,10 127,6 @@ namespace gui
            }
        }

        DBServiceAPI::GetQuery(application,
                               db::Interface::Name::Notifications,
                               std::make_unique<db::query::notifications::Clear>(NotificationsRecord::Key::Sms));

        list->rebuildList(listview::RebuildType::InPlace);
    }


M module-apps/application-messages/windows/SMSThreadViewWindow.cpp => module-apps/application-messages/windows/SMSThreadViewWindow.cpp +28 -20
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ApplicationMessages.hpp"


@@ 7,6 7,7 @@
#include "SMSThreadViewWindow.hpp"

#include <log/log.hpp>
#include <module-db/queries/notifications/QueryNotificationsDecrement.hpp>
#include <module-db/queries/phonebook/QueryContactGetByNumberID.hpp>
#include <module-db/queries/phonebook/QueryNumberGetByID.hpp>
#include <OptionsMessages.hpp>


@@ 62,29 63,36 @@ namespace gui

    void SMSThreadViewWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        {
            auto pdata = dynamic_cast<SMSThreadData *>(data);
            if (pdata) {
                LOG_INFO("Thread data received: %" PRIu32, pdata->thread->ID);
                requestContact(pdata->thread->numberID);

                // Mark thread as Read
                if (pdata->thread->isUnread()) {
                    auto app = dynamic_cast<app::ApplicationMessages *>(application);
                    assert(app != nullptr);
                    if (application->getCurrentWindow() == this) {
                        app->markSmsThreadAsRead(pdata->thread->ID);
                    }
        if (auto pdata = dynamic_cast<SMSThreadData *>(data); pdata) {
            LOG_INFO("Thread data received: %" PRIu32, pdata->thread->ID);
            requestContact(pdata->thread->numberID);

            // Mark thread as Read
            if (pdata->thread->isUnread()) {
                auto app = dynamic_cast<app::ApplicationMessages *>(application);
                assert(app != nullptr);
                if (application->getCurrentWindow() == this) {
                    app->markSmsThreadAsRead(pdata->thread->ID);
                }
                smsModel->numberID    = pdata->thread->numberID;
                smsModel->smsThreadID = pdata->thread->ID;
                smsList->rebuildList();
            }
            else if (smsModel->numberID != DB_ID_NONE) {
                requestContact(smsModel->numberID);
            smsModel->numberID    = pdata->thread->numberID;
            smsModel->smsThreadID = pdata->thread->ID;
            smsList->rebuildList();

            if (pdata->thread->unreadMsgCount) {
                const auto countToClear = pdata->thread->unreadMsgCount;

                DBServiceAPI::GetQuery(
                    application,
                    db::Interface::Name::Notifications,
                    std::make_unique<db::query::notifications::Decrement>(NotificationsRecord::Key::Sms, countToClear));
            }
        }
        if (auto pdata = dynamic_cast<SMSTextData *>(data)) {
        else if (smsModel->numberID != DB_ID_NONE) {
            requestContact(smsModel->numberID);
        }

        if (auto pdata = dynamic_cast<SMSTextData *>(data); pdata) {
            auto txt = pdata->text;
            LOG_INFO("received sms templates data");
            pdata->concatenate == SMSTextData::Concatenate::True ? smsModel->smsInput->inputText->addText(txt)

M module-apps/apps-common/notifications/NotificationProvider.cpp => module-apps/apps-common/notifications/NotificationProvider.cpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "NotificationProvider.hpp"


@@ 24,7 24,7 @@ bool NotificationProvider::handleNotSeenWithCounter(NotificationsRecord &&record
            notifications.erase(type);
            return true;
        }
        if (auto notification = static_cast<T *>(notifications[type].get()); value > notification->getValue()) {
        else {
            notifications[type] = std::make_shared<T>(value, std::move(record.contactRecord));
            return true;
        }

M module-db/CMakeLists.txt => module-db/CMakeLists.txt +1 -0
@@ 109,6 109,7 @@ set(SOURCES
        queries/notifications/QueryNotificationsGet.cpp
        queries/notifications/QueryNotificationsGetAll.cpp
        queries/notifications/QueryNotificationsIncrement.cpp
        queries/notifications/QueryNotificationsDecrement.cpp
        queries/notifications/QueryNotificationsMultipleIncrement.cpp
        queries/phonebook/QueryCheckContactsListDuplicates.cpp
        queries/phonebook/QueryContactAdd.cpp

M module-db/Interface/NotificationsRecord.cpp => module-db/Interface/NotificationsRecord.cpp +32 -1
@@ 1,9 1,10 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "NotificationsRecord.hpp"
#include "module-db/queries/notifications/QueryNotificationsGet.hpp"
#include "module-db/queries/notifications/QueryNotificationsIncrement.hpp"
#include "module-db/queries/notifications/QueryNotificationsDecrement.hpp"
#include "module-db/queries/notifications/QueryNotificationsMultipleIncrement.hpp"
#include "module-db/queries/notifications/QueryNotificationsClear.hpp"
#include "module-db/queries/notifications/QueryNotificationsGetAll.hpp"


@@ 148,6 149,9 @@ std::unique_ptr<db::QueryResult> NotificationsRecordInterface::runQuery(std::sha
    if (const auto local_query = dynamic_cast<const db::query::notifications::Increment *>(query.get())) {
        return runQueryImpl(local_query);
    }
    if (const auto local_query = dynamic_cast<const db::query::notifications::Decrement *>(query.get())) {
        return runQueryImpl(local_query);
    }
    if (const auto local_query = dynamic_cast<const db::query::notifications::MultipleIncrement *>(query.get())) {
        return runQueryImpl(local_query);
    }


@@ 175,6 179,14 @@ std::unique_ptr<db::query::notifications::IncrementResult> NotificationsRecordIn
    return std::make_unique<db::query::notifications::IncrementResult>(ret);
}

std::unique_ptr<db::query::notifications::DecrementResult> NotificationsRecordInterface::runQueryImpl(
    const db::query::notifications::Decrement *query)
{
    auto ret = processDecrement(query->getKey(), query->getCount());

    return std::make_unique<db::query::notifications::DecrementResult>(ret);
}

std::unique_ptr<db::query::notifications::MultipleIncrementResult> NotificationsRecordInterface::runQueryImpl(
    const db::query::notifications::MultipleIncrement *query)
{


@@ 243,3 255,22 @@ bool NotificationsRecordInterface::processIncrement(NotificationsRecord::Key key

    return ret;
}

bool NotificationsRecordInterface::processDecrement(NotificationsRecord::Key key, size_t delta)
{
    auto ret = false;

    if (auto record = GetByKey(key); record.isValid() && record.value > 0) {
        if (delta >= record.value) {
            record.contactRecord.reset();
            record.value = 0;
        }
        else {
            record.value -= delta;
        }

        ret = Update(record);
    }

    return ret;
}

M module-db/Interface/NotificationsRecord.hpp => module-db/Interface/NotificationsRecord.hpp +7 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 21,9 21,11 @@ namespace db::query::notifications
    class Get;
    class GetResult;
    class Increment;
    class IncrementResult;
    class Decrement;
    class DecrementResult;
    class MultipleIncrement;
    class MultipleIncrementResult;
    class IncrementResult;
    class Clear;
    class ClearResult;
    class GetAll;


@@ 87,6 89,8 @@ class NotificationsRecordInterface : public RecordInterface<NotificationsRecord,
    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);
    std::unique_ptr<db::query::notifications::DecrementResult> runQueryImpl(
        const db::query::notifications::Decrement *query);
    std::unique_ptr<db::query::notifications::MultipleIncrementResult> runQueryImpl(
        const db::query::notifications::MultipleIncrement *query);
    std::unique_ptr<db::query::notifications::ClearResult> runQueryImpl(const db::query::notifications::Clear *query);


@@ 94,4 98,5 @@ class NotificationsRecordInterface : public RecordInterface<NotificationsRecord,
    [[nodiscard]] bool processIncrement(NotificationsRecord::Key key,
                                        std::optional<utils::PhoneNumber::View> &&number,
                                        size_t size);
    [[nodiscard]] bool processDecrement(NotificationsRecord::Key key, size_t size);
};

A module-db/queries/notifications/QueryNotificationsDecrement.cpp => module-db/queries/notifications/QueryNotificationsDecrement.cpp +38 -0
@@ 0,0 1,38 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QueryNotificationsDecrement.hpp"

namespace db::query::notifications
{
    Decrement::Decrement(NotificationsRecord::Key key, const size_t count)
        : Query(Query::Type::Update), key(key), count(count)
    {}

    auto Decrement::getKey() const noexcept -> NotificationsRecord::Key
    {
        return key;
    }
    auto Decrement::getCount() const noexcept -> size_t
    {
        return count;
    }

    auto Decrement::debugInfo() const -> std::string
    {
        return "Decrement";
    }

    DecrementResult::DecrementResult(bool ret) : ret(ret)
    {}

    auto DecrementResult::getResult() const noexcept -> bool
    {
        return ret;
    }

    auto DecrementResult::debugInfo() const -> std::string
    {
        return "DecrementResult";
    }
} // namespace db::query::notifications

A module-db/queries/notifications/QueryNotificationsDecrement.hpp => module-db/queries/notifications/QueryNotificationsDecrement.hpp +39 -0
@@ 0,0 1,39 @@
// Copyright (c) 2017-2022, 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>
#include <PhoneNumber.hpp>
#include <cstdint>

namespace db::query::notifications
{
    class Decrement : public Query
    {
        const NotificationsRecord::Key key;
        const size_t count;

      public:
        Decrement(NotificationsRecord::Key key, const size_t count);

        [[nodiscard]] auto getKey() const noexcept -> NotificationsRecord::Key;
        [[nodiscard]] auto getCount() const noexcept -> size_t;

        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

    class DecrementResult : public QueryResult
    {
        bool ret;

      public:
        explicit DecrementResult(bool ret);
        [[nodiscard]] auto getResult() const noexcept -> bool;

        [[nodiscard]] auto debugInfo() const -> std::string override;
    };

} // namespace db::query::notifications

M module-db/tests/NotificationsRecord_tests.cpp => module-db/tests/NotificationsRecord_tests.cpp +44 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "common.hpp"


@@ 11,6 11,7 @@
#include <Databases/ContactsDB.hpp>
#include <queries/notifications/QueryNotificationsGet.hpp>
#include <queries/notifications/QueryNotificationsIncrement.hpp>
#include <queries/notifications/QueryNotificationsDecrement.hpp>
#include <queries/notifications/QueryNotificationsClear.hpp>
#include <queries/notifications/QueryNotificationsGetAll.hpp>



@@ 217,6 218,14 @@ TEST_CASE("Notifications Record tests")
        REQUIRE(result->getResult());
    };

    auto decrementByKey = [&](NotificationsRecord::Key key, size_t count = 1) {
        auto query  = std::make_shared<db::query::notifications::Decrement>(key, count);
        auto ret    = notificationsRecordInterface.runQuery(query);
        auto result = dynamic_cast<db::query::notifications::DecrementResult *>(ret.get());
        REQUIRE(result != nullptr);
        REQUIRE(result->getResult());
    };

    auto clearByKey = [&](NotificationsRecord::Key key) {
        auto query  = std::make_shared<db::query::notifications::Clear>(key);
        auto ret    = notificationsRecordInterface.runQuery(query);


@@ 360,6 369,40 @@ TEST_CASE("Notifications Record tests")
            incrementByKey(NotificationsRecord::Key::Calls, someUnknownNumber);
            getByKey(NotificationsRecord::Key::Calls, 3, contactNotExpected);
        }

        SECTION("Clear SMS notifications from multiple known numbers")
        {
            const auto expectedNotificationPerContact = 3;
            const auto expectedNotificationValue      = 2 * expectedNotificationPerContact;
            for (int i = 0; i < expectedNotificationValue / 2; i++) {
                incrementByKey(NotificationsRecord::Key::Sms, numberUserTest_1);
                incrementByKey(NotificationsRecord::Key::Sms, numberUserTest_2);
            }
            getByKey(NotificationsRecord::Key::Sms, expectedNotificationValue, contactNotExpected);

            decrementByKey(NotificationsRecord::Key::Sms, expectedNotificationPerContact);
            getByKey(NotificationsRecord::Key::Sms, expectedNotificationPerContact, contactNotExpected);

            decrementByKey(NotificationsRecord::Key::Sms, expectedNotificationPerContact);
            getByKey(NotificationsRecord::Key::Sms, noNotificationExpected, contactNotExpected);
        }

        SECTION("Clear SMS notifications overflowing actual count")
        {
            const auto expectedNotificationPerContact = 3;
            const auto expectedNotificationValue      = 2 * expectedNotificationPerContact;
            for (int i = 0; i < expectedNotificationValue / 2; i++) {
                incrementByKey(NotificationsRecord::Key::Sms, numberUserTest_1);
                incrementByKey(NotificationsRecord::Key::Sms, numberUserTest_2);
            }
            getByKey(NotificationsRecord::Key::Sms, expectedNotificationValue, contactNotExpected);

            decrementByKey(NotificationsRecord::Key::Sms, expectedNotificationPerContact + 1);
            getByKey(NotificationsRecord::Key::Sms, 2, contactNotExpected);

            decrementByKey(NotificationsRecord::Key::Sms, expectedNotificationPerContact);
            getByKey(NotificationsRecord::Key::Sms, noNotificationExpected, contactNotExpected);
        }
    }

    Database::deinitialize();