// 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 "ActiveNotificationsListPresenter.hpp" #include "ApplicationDesktop.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace gui; namespace { using Notification = const notifications::NotificationWithContact *; void setSMSFocusChangedCallback(NotificationListItem *item, ActiveNotificationsListPresenter *presenter) { item->focusChangedCallback = [presenter](gui::Item &_item) { if (_item.focus) { presenter->setParentNavBar( {}, utils::translate("app_desktop_show"), utils::translate("app_desktop_clear")); return true; } return false; }; } auto createSMSActivatedCallback(app::ApplicationCommon *app) { return [app]([[maybe_unused]] gui::Item &_item) { return app::manager::Controller::sendAction( app, app::manager::actions::Launch, std::make_unique(app::name_messages)); }; } auto createSMSActivatedCallback(app::ApplicationCommon *app, const ContactRecord &record) { Expects(not record.numbers.empty()); return [app, number = record.numbers[0].number]([[maybe_unused]] gui::Item &_item) { auto query = std::make_unique(number); auto task = app::AsyncQuery::createFromQuery(std::move(query), db::Interface::Name::SMSThread); auto queryCallback = [app](db::QueryResult *msg) -> bool { Expects(typeid(*msg) == typeid(db::query::ThreadGetByNumberResult)); auto result = static_cast(msg); auto data = std::make_unique(std::make_shared(result->getThread())); auto request = std::make_shared( app->GetName(), app::name_messages, gui::name::window::thread_view, std::move(data)); return app->bus.sendUnicast(std::move(request), service::name::appmgr); }; task->setCallback(std::move(queryCallback)); task->execute(app, static_cast(app)); return true; }; } void setSMSActivatedCallback(NotificationListItem *item, Notification provider, app::ApplicationCommon *app) { if (provider->hasRecord() && not provider->getRecord().numbers.empty()) { item->activatedCallback = createSMSActivatedCallback(app, provider->getRecord()); } else { item->activatedCallback = createSMSActivatedCallback(app); } } void clearSMSNotifications(app::ApplicationCommon *app) { DBServiceAPI::GetQuery(app, db::Interface::Name::Notifications, std::make_unique(NotificationsRecord::Key::Sms)); } void setSMSOnInputCallback(NotificationListItem *item, app::ApplicationCommon *app) { item->inputCallback = [app]([[maybe_unused]] Item &item, const InputEvent &inputEvent) { if (inputEvent.isShortRelease(KeyCode::KEY_RF)) { clearSMSNotifications(app); return true; } return false; }; } void setSMSDismissCallback(NotificationListItem *item, app::ApplicationCommon *app) { item->dismissCallback = [app]() { clearSMSNotifications(app); }; } void setCallFocusChangedCallback(NotificationListItem *item, Notification provider, ActiveNotificationsListPresenter *presenter) { item->focusChangedCallback = [presenter, canCall = provider->hasRecord()](gui::Item &_item) { if (_item.focus) { UTF8 navBarLeftText = canCall ? UTF8{utils::translate("common_call")} : UTF8{}; presenter->setParentNavBar( navBarLeftText, utils::translate("app_desktop_show"), utils::translate("app_desktop_clear")); } return true; }; } void setCallActivatedCallback(NotificationListItem *item, app::ApplicationCommon *app) { item->activatedCallback = [app]([[maybe_unused]] gui::Item &_item) { return app::manager::Controller::sendAction(app, app::manager::actions::ShowCallLog); }; } auto createCallOnRightFunctionalCallback(app::ApplicationCommon *app) -> std::function { return [app]() { DBServiceAPI::GetQuery(app, db::Interface::Name::Notifications, std::make_unique(NotificationsRecord::Key::Calls)); }; } auto createCallOnLeftFunctionalCallback(app::ApplicationCommon *app, Notification provider) -> std::function { if (!provider->hasRecord()) { return nullptr; } if (const auto &record = provider->getRecord(); !record.numbers.empty()) { return [app, number = record.numbers[0].number]() { app::manager::Controller::sendAction( app, app::manager::actions::Call, std::make_unique(number)); }; } return nullptr; } void setCallOnInputCallback(NotificationListItem *item, Notification provider, app::ApplicationCommon *app) { auto onRightFunctionalKeyCallback = createCallOnRightFunctionalCallback(app); auto onLeftFunctionalKeyCallback = createCallOnLeftFunctionalCallback(app, provider); item->inputCallback = [keyRightFunctionalCb = std::move(onRightFunctionalKeyCallback), keyLeftFunctionalCb = std::move(onLeftFunctionalKeyCallback)]( [[maybe_unused]] Item &item, const InputEvent &inputEvent) { if (inputEvent.isShortRelease()) { if (inputEvent.is(KeyCode::KEY_RF) && keyRightFunctionalCb != nullptr) { keyRightFunctionalCb(); return true; } else if (inputEvent.is(KeyCode::KEY_LF) && keyLeftFunctionalCb != nullptr) { keyLeftFunctionalCb(); return true; } } return false; }; } void setCallDismissCallback(NotificationListItem *item, app::ApplicationCommon *app) { item->dismissCallback = createCallOnRightFunctionalCallback(app); } void setTetheringActivatedCallback(NotificationListItem *item, app::ApplicationCommon *app) { item->activatedCallback = [app]([[maybe_unused]] gui::Item &_item) { app->switchWindow(gui::popup::window::tethering_off_window); return true; }; } void setTetheringFocusChangedCallback(NotificationListItem *item, ActiveNotificationsListPresenter *presenter) { item->focusChangedCallback = [presenter](gui::Item &_item) { if (_item.focus) { presenter->setParentNavBar({}, utils::translate("common_disconnect"), {}); return true; } return false; }; } void setSnoozeFocusChangedCallback(NotificationListItem *item, ActiveNotificationsListPresenter *presenter) { item->focusChangedCallback = [presenter](gui::Item &_item) { if (_item.focus) { presenter->setParentNavBar({}, utils::translate("app_desktop_show"), utils::translate("common_stop")); } return true; }; } void setSnoozeActivatedCallback(NotificationListItem *item, ActiveNotificationsListPresenter *presenter, app::ApplicationCommon *app) { item->activatedCallback = [presenter, app]([[maybe_unused]] gui::Item &_item) { auto request = std::make_unique(); auto task = app::AsyncRequest::createFromMessage(std::move(request), service::name::service_time); auto cb = [&](auto response) { auto result = dynamic_cast(response); assert(result); if (!result || result->snoozedAlarms.empty()) { return false; } app::manager::Controller::sendAction( app, app::manager::actions::ShowPopup, std::make_unique(AlarmPopupType::SnoozeCheck, std::move(result->snoozedAlarms))); return true; }; task->execute(app, presenter, cb); return true; }; } void setSnoozeOnInputCallback(NotificationListItem *item, app::ApplicationCommon *app) { item->inputCallback = [app]([[maybe_unused]] Item &item, const InputEvent &inputEvent) { if (inputEvent.isShortRelease() && inputEvent.is(KeyCode::KEY_RF)) { alarms::AlarmServiceAPI::requestStopAllSnoozedAlarms(app); return true; } return false; }; } void setSnoozeDismissCallback(NotificationListItem *item, app::ApplicationCommon *app) { item->dismissCallback = [app]() { alarms::AlarmServiceAPI::requestStopAllSnoozedAlarms(app); }; } } // namespace ActiveNotificationsListPresenter::ActiveNotificationsListPresenter(AppWindow *parent) : AsyncCallbackReceiver(parent->getApplication()), parent(parent) {} void ActiveNotificationsListPresenter::setParentNavBar(const UTF8 &left, const UTF8 ¢er, const UTF8 &right) { parent->setNavBarText(left, nav_bar::Side::Left); parent->setNavBarText(center, nav_bar::Side::Center); parent->setNavBarText(right, nav_bar::Side::Right); } auto ActiveNotificationsListPresenter::create(const notifications::NotSeenSMSNotification *notification) -> NotificationListItem * { auto item = NotificationsListPresenter::create(notification); setSMSFocusChangedCallback(item, this); setSMSActivatedCallback(item, notification, parent->getApplication()); setSMSOnInputCallback(item, parent->getApplication()); setSMSDismissCallback(item, parent->getApplication()); item->setDismissible(true); return item; } auto ActiveNotificationsListPresenter::create(const notifications::NotSeenCallNotification *notification) -> NotificationListItem * { auto item = NotificationsListPresenter::create(notification); setCallFocusChangedCallback(item, notification, this); setCallActivatedCallback(item, parent->getApplication()); setCallOnInputCallback(item, notification, parent->getApplication()); setCallDismissCallback(item, parent->getApplication()); item->setDismissible(true); return item; } auto ActiveNotificationsListPresenter::create(const notifications::TetheringNotification *notification) -> NotificationListItem * { auto item = NotificationsListPresenter::create(notification); setTetheringActivatedCallback(item, parent->getApplication()); setTetheringFocusChangedCallback(item, this); return item; } auto ActiveNotificationsListPresenter::create(const notifications::AlarmSnoozeNotification *notification) -> NotificationListItem * { auto item = NotificationsListPresenter::create(notification); setSnoozeFocusChangedCallback(item, this); setSnoozeActivatedCallback(item, this, parent->getApplication()); setSnoozeOnInputCallback(item, parent->getApplication()); setSnoozeDismissCallback(item, parent->getApplication()); item->setDismissible(false); return item; }