~aleteoryx/muditaos

eda92600a7df852e18bdb44388966248a4af3c77 — Maciej Gibowicz 10 months ago 71c88ba
[BH-2095] Add quote interval setting

Modifying the time after which new quotes are displayed on the Harmony
screen.
M module-services/service-db/DBServiceAPI.cpp => module-services/service-db/DBServiceAPI.cpp +6 -0
@@ 356,6 356,12 @@ void DBServiceAPI::QuotesGroupChanged(sys::Service *serv, const std::string &gro
    DBServiceAPI::GetQuery(serv, db::Interface::Name::Quotes, std::move(query));
}

void DBServiceAPI::QuotesIntervalChanged(sys::Service *serv, const std::string &interval)
{
    auto query = std::make_unique<Quotes::Messages::InformIntervalChanged>(interval);
    DBServiceAPI::GetQuery(serv, db::Interface::Name::Quotes, std::move(query));
}

auto DBServiceAPI::hasContactSameNumbers(sys::Service *serv, const ContactRecord &rec) -> bool
{
    std::shared_ptr<DBContactMessage> msg =

M module-services/service-db/agents/settings/SystemSettings.hpp => module-services/service-db/agents/settings/SystemSettings.hpp +1 -0
@@ 82,6 82,7 @@ namespace settings
        inline constexpr auto randomQuotesList        = "quotes_random_list";
        inline constexpr auto randomQuoteIDUpdateTime = "quotes_random_id_update_time";
        inline constexpr auto selectedGroup           = "quotes_group";
        inline constexpr auto selectedInterval        = "quotes_interval";
    } // namespace Quotes

    namespace Display

M module-services/service-db/include/service-db/DBServiceAPI.hpp => module-services/service-db/include/service-db/DBServiceAPI.hpp +1 -0
@@ 139,4 139,5 @@ class DBServiceAPI
                                std::unique_ptr<db::QueryListener> &&listener);
    static bool QuotesDeleteEntry(sys::Service *serv, std::uint32_t id, std::unique_ptr<db::QueryListener> &&listener);
    static void QuotesGroupChanged(sys::Service *serv, const std::string &group);
    static void QuotesIntervalChanged(sys::Service *serv, const std::string &interval);
};

M module-services/service-db/include/service-db/QuotesMessages.hpp => module-services/service-db/include/service-db/QuotesMessages.hpp +13 -0
@@ 432,6 432,19 @@ namespace Quotes
            }
        };

        class InformIntervalChanged : public db::Query
        {
          public:
            explicit InformIntervalChanged(const std::string &interval) : Query(Query::Type::Read), interval(interval)
            {}
            const std::string interval;

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

        class WriteQuoteRequest : public db::Query
        {
          public:

M module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp => module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp +1 -1
@@ 130,7 130,7 @@ namespace sdesktop::endpoints::json
        inline constexpr auto author   = "author";
        inline constexpr auto group    = "group";
        inline constexpr auto interval = "interval";
        inline constexpr auto quoteID = "quoteID";
        inline constexpr auto quoteID  = "quoteID";
    } // namespace quotes

} // namespace sdesktop::endpoints::json

M products/BellHybrid/services/db/agents/QuotesAgent.cpp => products/BellHybrid/services/db/agents/QuotesAgent.cpp +18 -0
@@ 36,6 36,9 @@ namespace Quotes
        else if (typeid(*query) == typeid(Messages::InformGroupChanged)) {
            return handleGroupChanged(query);
        }
        else if (typeid(*query) == typeid(Messages::InformIntervalChanged)) {
            return handleIntervalChanged(query);
        }
        return nullptr;
    }



@@ 149,4 152,19 @@ namespace Quotes
        shuffleQuoteModel.updateList(ListUpdateMode::Forced);
        return std::make_unique<Messages::NotificationResult>(true);
    }

    auto QuotesAgent::handleIntervalChanged(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>
    {
        const auto request = std::dynamic_pointer_cast<Messages::InformIntervalChanged>(query);
        if (request == nullptr) {
            return std::make_unique<Messages::NotificationResult>(false);
        }
        if (!utils::is_number(request->interval) && request->interval != atMidnight) {
            return std::make_unique<Messages::NotificationResult>(false);
        }

        settings->setValue(settings::Quotes::selectedInterval, request->interval, settings::SettingsScope::Global);
        shuffleQuoteModel.updateList(ListUpdateMode::Forced);
        return std::make_unique<Messages::NotificationResult>(true);
    }
} // namespace Quotes

M products/BellHybrid/services/db/agents/QuotesAgent.hpp => products/BellHybrid/services/db/agents/QuotesAgent.hpp +1 -0
@@ 34,5 34,6 @@ namespace Quotes
        auto handleEditEntry(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
        auto handleDeleteEntry(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
        auto handleGroupChanged(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
        auto handleIntervalChanged(std::shared_ptr<db::Query> query) -> std::unique_ptr<db::QueryResult>;
    };
} // namespace Quotes

M products/BellHybrid/services/db/agents/ShuffleQuoteModel.cpp => products/BellHybrid/services/db/agents/ShuffleQuoteModel.cpp +25 -5
@@ 7,6 7,7 @@
#include <log/log.hpp>
#include <bsp/trng/trng.hpp>
#include <service-db/agents/settings/SystemSettings.hpp>
#include <time/time_constants.hpp>

#include <memory>
#include <ctime>


@@ 28,6 29,12 @@ namespace
        }
        return (std::abs(current - last) > dayInSec); // If the day is the same but different month/year
    }

    bool isTimeElapsed(std::time_t current, std::time_t last, std::uint32_t intervalInMinutes)
    {
        const auto elapsedMinutes = std::abs(current - last) / utils::time::secondsInMinute;
        return elapsedMinutes >= intervalInMinutes;
    }
} // namespace

namespace Quotes


@@ 102,6 109,7 @@ namespace Quotes
        std::time_t lastTimestamp;
        const auto lastTimestampString =
            settings.getValue(settings::Quotes::randomQuoteIDUpdateTime, settings::SettingsScope::Global);
        const auto interval = settings.getValue(settings::Quotes::selectedInterval, settings::SettingsScope::Global);

        try {
            lastTimestamp = std::stoll(lastTimestampString);


@@ 112,12 120,24 @@ namespace Quotes
        }

        const auto currentTimestamp = std::time(nullptr);
        if (hasCrossedMidnight(currentTimestamp, lastTimestamp)) {
            settings.setValue(settings::Quotes::randomQuoteIDUpdateTime,
                              utils::to_string(currentTimestamp),
                              settings::SettingsScope::Global);
            return true;

        if (utils::is_number(interval)) {
            if (isTimeElapsed(currentTimestamp, lastTimestamp, utils::toNumeric(interval))) {
                settings.setValue(settings::Quotes::randomQuoteIDUpdateTime,
                                  utils::to_string(currentTimestamp),
                                  settings::SettingsScope::Global);
                return true;
            }
        }
        else if (interval == atMidnight) {
            if (hasCrossedMidnight(currentTimestamp, lastTimestamp)) {
                settings.setValue(settings::Quotes::randomQuoteIDUpdateTime,
                                  utils::to_string(currentTimestamp),
                                  settings::SettingsScope::Global);
                return true;
            }
        }

        return false;
    }
} // namespace Quotes

M products/BellHybrid/services/db/agents/ShuffleQuoteModel.hpp => products/BellHybrid/services/db/agents/ShuffleQuoteModel.hpp +1 -0
@@ 12,6 12,7 @@ namespace Quotes
{
    inline constexpr auto customGroup     = "Custom";
    inline constexpr auto predefinedGroup = "Predefined";
    inline constexpr auto atMidnight      = "AtMidnight";

    enum class ListUpdateMode
    {

A products/BellHybrid/services/db/databases/migration/settings_bell/current/b6dd0dff_Add_quote_interval_setting/.meta => products/BellHybrid/services/db/databases/migration/settings_bell/current/b6dd0dff_Add_quote_interval_setting/.meta +6 -0
@@ 0,0 1,6 @@
{
 "id": "b6dd0dff-d717-4bf7-97e8-cc3e6359d9ff",
 "date": "2025-01-30 13:47:07",
 "message": "Add quote interval setting",
 "parent": "91a948e7-4cff-4492-b25c-e219cfb4e8de"
}
\ No newline at end of file

A products/BellHybrid/services/db/databases/migration/settings_bell/current/b6dd0dff_Add_quote_interval_setting/down.sql => products/BellHybrid/services/db/databases/migration/settings_bell/current/b6dd0dff_Add_quote_interval_setting/down.sql +10 -0
@@ 0,0 1,10 @@
-- Copyright (c) 2017-2025, Mudita Sp. z.o.o. All rights reserved.
-- For licensing, see https://github.com/mudita/MuditaOS/blob/master/LICENSE.md

-- Message: Add quote interval setting
-- Revision: b6dd0dff-d717-4bf7-97e8-cc3e6359d9ff
-- Create Date: 2025-01-30 13:47:07

-- Insert SQL here

DELETE FROM settings_tab WHERE path = 'quotes_interval';

A products/BellHybrid/services/db/databases/migration/settings_bell/current/b6dd0dff_Add_quote_interval_setting/up.sql => products/BellHybrid/services/db/databases/migration/settings_bell/current/b6dd0dff_Add_quote_interval_setting/up.sql +11 -0
@@ 0,0 1,11 @@
-- Copyright (c) 2017-2025, Mudita Sp. z.o.o. All rights reserved.
-- For licensing, see https://github.com/mudita/MuditaOS/blob/master/LICENSE.md

-- Message: Add quote interval setting
-- Revision: b6dd0dff-d717-4bf7-97e8-cc3e6359d9ff
-- Create Date: 2025-01-30 13:47:07

-- Insert SQL here

INSERT OR IGNORE INTO settings_tab (path, value) VALUES
       ('quotes_interval', 'AtMidnight');

M products/BellHybrid/services/desktop/endpoints/quotes/QuotesHelper.cpp => products/BellHybrid/services/desktop/endpoints/quotes/QuotesHelper.cpp +1 -1
@@ 82,7 82,7 @@ namespace sdesktop::endpoints
            DBServiceAPI::QuotesGroupChanged(owner, group.c_str());
        }
        else if (const auto &interval = body[json::quotes::interval].string_value(); !interval.empty()) {
            // TODO: https://appnroll.atlassian.net/browse/BH-2095
            DBServiceAPI::QuotesIntervalChanged(owner, interval.c_str());
        }
        else {
            return {Sent::No, ResponseContext{.status = http::Code::BadRequest}};

M test/custom_quotes.py => test/custom_quotes.py +1 -1
@@ 214,7 214,7 @@ def main():
                        help='string with type of group of displayed quotes [Predefined or Custom]')
    parser.add_argument('-i', '--interval',
                        metavar='quotes_display_interval',
                        help='quotes display interval [\'x\' minutes or \'at midnight\']')
                        help='quotes display interval [\'x\' minutes or \'AtMidnight\']')

    args = parser.parse_args()
    if not args.port: