// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/blob/master/LICENSE.md #include "NotificationProvider.hpp" #include #include #include #include #include #include using namespace notifications; NotificationProvider::NotificationProvider(sys::Service *ownerService, NotificationsConfiguration ¬ificationConfig) : ownerService{ownerService}, notificationConfig{notificationConfig} {} template bool NotificationProvider::handleNotSeenWithCounter(NotificationsRecord &&record) { auto value = record.value; if (notifications.count(type) > 0) { if (value == 0) { notifications.erase(type); return true; } else { notifications[type] = std::make_shared(value, std::move(record.contactRecord)); return true; } } else if (value > 0) { notifications[type] = std::make_shared(value, std::move(record.contactRecord)); return true; } return false; } void NotificationProvider::handle(locks::PhoneLockTimeUpdate *msg) { assert(msg); auto updateOnReceive = NotificationOnReceiveUpdate::FullRebuild; if (const auto &formattedTime = msg->getTime(); !formattedTime.empty()) { updateOnReceive = msg->getIsFirstData() ? NotificationOnReceiveUpdate::FullRebuild : NotificationOnReceiveUpdate::PartialRebuild; notifications[NotificationType::PhoneLock] = std::make_shared(formattedTime); } else { notifications.erase(NotificationType::PhoneLock); } send(updateOnReceive); } void NotificationProvider::handle(db::query::notifications::GetAllResult *msg) { assert(msg); auto records = *msg->getResult(); bool notificationsChanged = false; for (auto &&record : records) { switch (record.key) { case NotificationsRecord::Key::Calls: notificationsChanged |= handleNotSeenWithCounter(std::move(record)); break; case NotificationsRecord::Key::Sms: notificationsChanged |= handleNotSeenWithCounter(std::move(record)); break; default: break; } } notificationConfig.updateCurrentList(listPolicy); if (notificationsChanged && listPolicy.updateListAllowed()) { send(); } } void NotificationProvider::handle(db::NotificationMessage *msg) { if (msg->interface == db::Interface::Name::Notifications && msg->type == db::Query::Type::Update) { requestNotSeenNotifications(); } } void NotificationProvider::handle(sys::phone_modes::Tethering tethering) { using Tethering = sys::phone_modes::Tethering; bool notificationsChanged = false; if (tethering == Tethering::On && notifications.count(NotificationType::Tethering) == 0) { notifications[NotificationType::Tethering] = std::make_shared(); notificationsChanged = true; } else if (tethering == Tethering::Off && notifications.count(NotificationType::Tethering) != 0) { notifications.erase(NotificationType::Tethering); notificationsChanged = true; } if (notificationsChanged) { send(); } } void NotificationProvider::handleSnooze(unsigned snoozeCount) { if (snoozeCount > 0) { notifications[NotificationType::AlarmSnooze] = std::make_shared(snoozeCount); } else { notifications.erase(NotificationType::AlarmSnooze); } send(); } void NotificationProvider::handleBatteryTooHot(bool isBatteryTooHot, bool allowUpdate) { auto notificationsChanged = false; const auto notificationShown = (notifications.count(NotificationType::BatteryTooHot) != 0); if (isBatteryTooHot && !notificationShown) { notifications[NotificationType::BatteryTooHot] = std::make_shared(); notificationsChanged = true; } else if (!isBatteryTooHot && notificationShown) { notifications.erase(NotificationType::BatteryTooHot); notificationsChanged = true; } if (notificationsChanged && allowUpdate) { send(); } } void NotificationProvider::requestNotSeenNotifications() { DBServiceAPI::GetQuery( ownerService, db::Interface::Name::Notifications, std::make_unique()); } namespace { using mapType = NotificationProvider::Notifications; using returnType = std::shared_ptr; struct get_second : public std::unary_function { returnType operator()(const mapType::value_type &value) const { return value.second; } }; } // namespace void NotificationProvider::send(NotificationOnReceiveUpdate updateOnReceive) { using namespace app::manager; notificationConfig.updateCurrentList(listPolicy); std::list> notificationsToSend; std::transform(notifications.begin(), notifications.end(), std::back_inserter(notificationsToSend), get_second()); notificationsToSend.sort( [](const std::shared_ptr &lhs, const std::shared_ptr &rhs) { return (lhs->getPriority() > rhs->getPriority()); }); const auto fastRefreshOnUpdate = (updateOnReceive == NotificationOnReceiveUpdate::PartialRebuild); auto data = std::make_unique( std::move(notificationsToSend), listPolicy.showListWhenLocked(), fastRefreshOnUpdate); Controller::sendAction(ownerService, actions::NotificationsChanged, std::move(data)); }