~aleteoryx/muditaos

097267d8602c5a8bd6cb2e763f8daf0d51cc327b — Wojciech Rzepecki 4 years ago f1465ed
[EGD-6824] Simplified notifications on quote wallpaper

simplified home screen notifications as tiles on phone
locked wallpaper
27 files changed, 658 insertions(+), 317 deletions(-)

M module-apps/application-desktop/CMakeLists.txt
R module-apps/application-desktop/models/{ActiveNotificationsModel => ActiveNotificationsListPresenter}.cpp
R module-apps/application-desktop/models/{ActiveNotificationsModel => ActiveNotificationsListPresenter}.hpp
M module-apps/application-desktop/windows/DesktopMainWindow.cpp
M module-apps/application-desktop/windows/DesktopMainWindow.hpp
M module-apps/apps-common/CMakeLists.txt
A module-apps/apps-common/notifications/NotificationTilesBox.cpp
A module-apps/apps-common/notifications/NotificationTilesBox.hpp
A module-apps/apps-common/notifications/NotificationTilesPresenter.cpp
A module-apps/apps-common/notifications/NotificationTilesPresenter.hpp
A module-apps/apps-common/notifications/NotificationsListPresenter.cpp
A module-apps/apps-common/notifications/NotificationsListPresenter.hpp
M module-apps/apps-common/notifications/NotificationsModel.cpp
M module-apps/apps-common/notifications/NotificationsModel.hpp
A module-apps/apps-common/notifications/NotificationsPresenter.hpp
M module-apps/apps-common/popups/lock-popups/PhoneLockedWindow.cpp
M module-apps/apps-common/popups/lock-popups/PhoneLockedWindow.hpp
M module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperBase.hpp
M module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperClock.cpp
M module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperClock.hpp
M module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperLogo.cpp
M module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperLogo.hpp
M module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperQuote.cpp
M module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperQuote.hpp
M module-apps/apps-common/popups/presenter/WallpaperPresenter.cpp
M module-apps/apps-common/popups/presenter/WallpaperPresenter.hpp
M module-gui/gui/widgets/Style.hpp
M module-apps/application-desktop/CMakeLists.txt => module-apps/application-desktop/CMakeLists.txt +2 -2
@@ 21,8 21,8 @@ target_sources(application-desktop
		ApplicationDesktop.cpp
		data/DesktopData.hpp
		data/Mmi.hpp
		models/ActiveNotificationsModel.cpp
		models/ActiveNotificationsModel.hpp
		models/ActiveNotificationsListPresenter.cpp
		models/ActiveNotificationsListPresenter.hpp
		widgets/DBNotificationsHandler.cpp
		widgets/DesktopInputWidget.cpp
		widgets/DesktopInputWidget.hpp

R module-apps/application-desktop/models/ActiveNotificationsModel.cpp => module-apps/application-desktop/models/ActiveNotificationsListPresenter.cpp +29 -26
@@ 1,7 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 "ActiveNotificationsModel.hpp"
#include "ActiveNotificationsListPresenter.hpp"
#include "ApplicationDesktop.hpp"

#include <application-call/data/CallSwitchData.hpp>


@@ 23,11 23,12 @@ using namespace gui;
namespace
{
    using Notification = const notifications::NotificationWithContact *;
    void setSMSFocusChangedCallback(NotificationListItem *item, ActiveNotificationsModel *model)
    void setSMSFocusChangedCallback(NotificationListItem *item, ActiveNotificationsListPresenter *presenter)
    {
        item->focusChangedCallback = [model](gui::Item &_item) {
        item->focusChangedCallback = [presenter](gui::Item &_item) {
            if (_item.focus) {
                model->setParentNavBar({}, utils::translate("app_desktop_show"), utils::translate("app_desktop_clear"));
                presenter->setParentNavBar(
                    {}, utils::translate("app_desktop_show"), utils::translate("app_desktop_clear"));
                return true;
            }
            return false;


@@ 96,12 97,14 @@ namespace
        item->dismissCallback = [app]() { clearSMSNotifications(app); };
    }

    void setCallFocusChangedCallback(NotificationListItem *item, Notification provider, ActiveNotificationsModel *model)
    void setCallFocusChangedCallback(NotificationListItem *item,
                                     Notification provider,
                                     ActiveNotificationsListPresenter *presenter)
    {
        item->focusChangedCallback = [model, canCall = provider->hasRecord()](gui::Item &_item) {
        item->focusChangedCallback = [presenter, canCall = provider->hasRecord()](gui::Item &_item) {
            if (_item.focus) {
                UTF8 navBarLeftText = canCall ? UTF8{utils::translate("common_call")} : UTF8{};
                model->setParentNavBar(
                presenter->setParentNavBar(
                    navBarLeftText, utils::translate("app_desktop_show"), utils::translate("app_desktop_clear"));
            }
            return true;


@@ 172,32 175,32 @@ namespace
        };
    }

    void setTetheringFocusChangedCallback(NotificationListItem *item, ActiveNotificationsModel *model)
    void setTetheringFocusChangedCallback(NotificationListItem *item, ActiveNotificationsListPresenter *presenter)
    {
        item->focusChangedCallback = [model](gui::Item &_item) {
        item->focusChangedCallback = [presenter](gui::Item &_item) {
            if (_item.focus) {
                model->setParentNavBar({}, utils::translate("common_disconnect"), {});
                presenter->setParentNavBar({}, utils::translate("common_disconnect"), {});
                return true;
            }
            return false;
        };
    }

    void setSnoozeFocusChangedCallback(NotificationListItem *item, ActiveNotificationsModel *model)
    void setSnoozeFocusChangedCallback(NotificationListItem *item, ActiveNotificationsListPresenter *presenter)
    {
        item->focusChangedCallback = [model](gui::Item &_item) {
        item->focusChangedCallback = [presenter](gui::Item &_item) {
            if (_item.focus) {
                model->setParentNavBar({}, utils::translate("app_desktop_show"), utils::translate("common_stop"));
                presenter->setParentNavBar({}, utils::translate("app_desktop_show"), utils::translate("common_stop"));
            }
            return true;
        };
    }

    void setSnoozeActivatedCallback(NotificationListItem *item,
                                    ActiveNotificationsModel *model,
                                    ActiveNotificationsListPresenter *presenter,
                                    app::ApplicationCommon *app)
    {
        item->activatedCallback = [model, app]([[maybe_unused]] gui::Item &_item) {
        item->activatedCallback = [presenter, app]([[maybe_unused]] gui::Item &_item) {
            auto request = std::make_unique<alarms::GetSnoozedAlarmsRequestMessage>();
            auto task    = app::AsyncRequest::createFromMessage(std::move(request), service::name::service_time);
            auto cb      = [&](auto response) {


@@ 213,7 216,7 @@ namespace
                                                                   std::move(result->snoozedAlarms)));
                return true;
            };
            task->execute(app, model, cb);
            task->execute(app, presenter, cb);
            return true;
        };
    }


@@ 235,21 238,21 @@ namespace
    }
} // namespace

ActiveNotificationsModel::ActiveNotificationsModel(AppWindow *parent)
ActiveNotificationsListPresenter::ActiveNotificationsListPresenter(AppWindow *parent)
    : AsyncCallbackReceiver(parent->getApplication()), parent(parent)
{}

void ActiveNotificationsModel::setParentNavBar(const UTF8 &left, const UTF8 &center, const UTF8 &right)
void ActiveNotificationsListPresenter::setParentNavBar(const UTF8 &left, const UTF8 &center, 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 ActiveNotificationsModel::create(const notifications::NotSeenSMSNotification *notification)
auto ActiveNotificationsListPresenter::create(const notifications::NotSeenSMSNotification *notification)
    -> NotificationListItem *
{
    auto item                  = NotificationsModel::create(notification);
    auto item = NotificationsListPresenter::create(notification);
    setSMSFocusChangedCallback(item, this);
    setSMSActivatedCallback(item, notification, parent->getApplication());
    setSMSOnInputCallback(item, parent->getApplication());


@@ 257,10 260,10 @@ auto ActiveNotificationsModel::create(const notifications::NotSeenSMSNotificatio
    item->setDismissible(true);
    return item;
}
auto ActiveNotificationsModel::create(const notifications::NotSeenCallNotification *notification)
auto ActiveNotificationsListPresenter::create(const notifications::NotSeenCallNotification *notification)
    -> NotificationListItem *
{
    auto item = NotificationsModel::create(notification);
    auto item = NotificationsListPresenter::create(notification);
    setCallFocusChangedCallback(item, notification, this);
    setCallActivatedCallback(item, parent->getApplication());
    setCallOnInputCallback(item, notification, parent->getApplication());


@@ 269,19 272,19 @@ auto ActiveNotificationsModel::create(const notifications::NotSeenCallNotificati
    return item;
}

auto ActiveNotificationsModel::create(const notifications::TetheringNotification *notification)
auto ActiveNotificationsListPresenter::create(const notifications::TetheringNotification *notification)
    -> NotificationListItem *
{
    auto item               = NotificationsModel::create(notification);
    auto item = NotificationsListPresenter::create(notification);
    setTetheringActivatedCallback(item, parent->getApplication());
    setTetheringFocusChangedCallback(item, this);
    return item;
}

auto ActiveNotificationsModel::create(const notifications::AlarmSnoozeNotification *notification)
auto ActiveNotificationsListPresenter::create(const notifications::AlarmSnoozeNotification *notification)
    -> NotificationListItem *
{
    auto item = NotificationsModel::create(notification);
    auto item = NotificationsListPresenter::create(notification);
    setSnoozeFocusChangedCallback(item, this);
    setSnoozeActivatedCallback(item, this, parent->getApplication());
    setSnoozeOnInputCallback(item, parent->getApplication());

R module-apps/application-desktop/models/ActiveNotificationsModel.hpp => module-apps/application-desktop/models/ActiveNotificationsListPresenter.hpp +4 -3
@@ 3,16 3,17 @@

#pragma once

#include <notifications/NotificationsModel.hpp>
#include <notifications/NotificationsListPresenter.hpp>

namespace gui
{
    class ActiveNotificationsModel : public gui::NotificationsModel, public app::AsyncCallbackReceiver
    class ActiveNotificationsListPresenter : public gui::NotificationsListPresenter, public app::AsyncCallbackReceiver
    {
      private:
        AppWindow *parent = nullptr;

      public:
        explicit ActiveNotificationsModel(AppWindow *parent);
        explicit ActiveNotificationsListPresenter(AppWindow *parent);
        void setParentNavBar(const UTF8 &left, const UTF8 &center, const UTF8 &right);
        auto create(const notifications::NotSeenSMSNotification *notification) -> NotificationListItem * override;
        auto create(const notifications::NotSeenCallNotification *notification) -> NotificationListItem * override;

M module-apps/application-desktop/windows/DesktopMainWindow.cpp => module-apps/application-desktop/windows/DesktopMainWindow.cpp +4 -3
@@ 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 "ApplicationDesktop.hpp"


@@ 49,7 49,7 @@ namespace gui
                                         style::notifications::model::y,
                                         style::notifications::model::w,
                                         style::notifications::model::h,
                                         notificationsModel,
                                         notificationsListPresenter,
                                         listview::ScrollBarType::Fixed);
        notificationsList->emptyListCallback = [this]() {
            setFocusItem(nullptr);


@@ 79,7 79,8 @@ namespace gui

    DesktopMainWindow::DesktopMainWindow(app::ApplicationCommon *app)
        : AppWindow(app, app::window::name::desktop_main_window),
          notificationsModel(std::make_shared<ActiveNotificationsModel>(this))
          notificationsListPresenter(std::make_shared<ActiveNotificationsListPresenter>(this)),
          notificationsModel(std::make_shared<NotificationsModel>(notificationsListPresenter))
    {
        buildInterface();


M module-apps/application-desktop/windows/DesktopMainWindow.hpp => module-apps/application-desktop/windows/DesktopMainWindow.hpp +5 -3
@@ 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

#pragma once

#include <application-desktop/models/ActiveNotificationsModel.hpp>
#include <notifications/NotificationsModel.hpp>
#include <application-desktop/models/ActiveNotificationsListPresenter.hpp>

#include <AppWindow.hpp>
#include <ListView.hpp>


@@ 23,7 24,8 @@ namespace gui
      protected:
        gui::ClockDateWidget *clockDate                                   = nullptr;
        gui::ListView *notificationsList                                  = nullptr;
        std::shared_ptr<gui::ActiveNotificationsModel> notificationsModel = nullptr;
        std::shared_ptr<gui::ActiveNotificationsListPresenter> notificationsListPresenter;
        std::shared_ptr<gui::NotificationsModel> notificationsModel;

        // method hides or show widgets and sets bars according to provided state
        void setVisibleState();

M module-apps/apps-common/CMakeLists.txt => module-apps/apps-common/CMakeLists.txt +3 -0
@@ 24,8 24,11 @@ target_sources(apps-common
        notifications/NotificationListItem.cpp
        notifications/NotificationProvider.cpp
        notifications/NotificationsModel.cpp
        notifications/NotificationsListPresenter.cpp
        notifications/NotificationTilesPresenter.cpp
        notifications/NotificationsHandler.cpp
        notifications/NotificationsConfiguration.cpp
        notifications/NotificationTilesBox.cpp
        notifications/policies/CallNotificationPolicy.cpp
        notifications/policies/SMSNotificationPolicy.cpp
        notifications/policies/NotificationsListPolicy.cpp

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

#include "NotificationTilesBox.hpp"

#include <widgets/Style.hpp>
#include <Image.hpp>
#include <Style.hpp>

namespace gui
{
    NotificationTilesBox::NotificationTilesBox(Item *parent,
                                               std::shared_ptr<NotificationTilesPresenter> notificationsPresenter)
        : HBox(
              parent, 0, 0, ::style::window::default_body_width, ::style::wallpaper::notificationTiles::tileIconHeight),
          notificationsPresenter(notificationsPresenter)
    {
        setEdges(RectangleEdge::None);
        setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        notificationsPresenter->attach(this);
    }
} // namespace gui

A module-apps/apps-common/notifications/NotificationTilesBox.hpp => module-apps/apps-common/notifications/NotificationTilesBox.hpp +22 -0
@@ 0,0 1,22 @@
// 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 <BoxLayout.hpp>

#include "NotificationData.hpp"
#include <notifications/NotificationTilesPresenter.hpp>

namespace gui
{
    class NotificationTilesBox : public HBox
    {
      public:
        explicit NotificationTilesBox(Item *parent, std::shared_ptr<NotificationTilesPresenter> notificationsPresenter);

      private:
        std::shared_ptr<NotificationTilesPresenter> notificationsPresenter;
    };

} // namespace gui

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

#include "NotificationTilesPresenter.hpp"
#include <Image.hpp>
#include <Style.hpp>

using namespace gui;

namespace
{
    constexpr auto messagesIcon  = "messages_notification_icon_W_G";
    constexpr auto callsIcon     = "calls_notification_icon_W_G";
    constexpr auto tetheringIcon = "tethering_notification_icon_W_G";
    constexpr auto alarmIcon     = "alarm_notification_icon_W_G";
    constexpr auto lockIcon      = "lock_notification_icon_W_G";

    auto buildNotificationIcon(const UTF8 &imageName) -> gui::Image *
    {
        auto icon = new gui::Image(imageName);
        icon->setMinimumWidth(::style::wallpaper::notificationTiles::tileIconHeight);
        icon->setMargins(gui::Margins(::style::wallpaper::notificationTiles::tileIconMarigin,
                                      0,
                                      ::style::wallpaper::notificationTiles::tileIconMarigin,
                                      0));
        return icon;
    }
} // namespace

NotificationTilesPresenter::NotificationTilesPresenter()
{}

void NotificationTilesPresenter::attach(HBox *tilesBox)
{
    this->tilesBox = tilesBox;
}

void NotificationTilesPresenter::updateData(app::manager::actions::NotificationsChangedParams *params,
                                            bool callAndSMSVisibility)
{
    if (tilesBox == nullptr) {
        LOG_ERROR("TilesBox not attached");
        return;
    }

    tilesBox->erase();

    for (const auto &notification : params->getNotifications()) {
        if (typeid(*notification) == typeid(notifications::NotSeenSMSNotification) && callAndSMSVisibility) {
            tilesBox->addWidget(buildNotificationIcon(messagesIcon));
        }
        else if (typeid(*notification) == typeid(notifications::NotSeenCallNotification) && callAndSMSVisibility) {
            tilesBox->addWidget(buildNotificationIcon(callsIcon));
        }
        else if (typeid(*notification) == typeid(notifications::TetheringNotification)) {
            tilesBox->addWidget(buildNotificationIcon(tetheringIcon));
        }
        else if (typeid(*notification) == typeid(notifications::PhoneLockNotification)) {
            tilesBox->addWidget(buildNotificationIcon(lockIcon));
        }
        else if (typeid(*notification) == typeid(notifications::AlarmSnoozeNotification)) {
            tilesBox->addWidget(buildNotificationIcon(alarmIcon));
        }
    }
    tilesBox->resizeItems();
}

bool NotificationTilesPresenter::hasDismissibleNotification() const noexcept
{
    return false;
}

void NotificationTilesPresenter::dismissAll()
{}

bool NotificationTilesPresenter::isEmpty() const noexcept
{
    return false;
}

A module-apps/apps-common/notifications/NotificationTilesPresenter.hpp => module-apps/apps-common/notifications/NotificationTilesPresenter.hpp +27 -0
@@ 0,0 1,27 @@
// 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 "NotificationsPresenter.hpp"

#include <BoxLayout.hpp>

namespace gui
{
    class NotificationTilesPresenter : public NotificationsPresenter
    {
      public:
        NotificationTilesPresenter();
        void attach(HBox *tilesBox);
        [[nodiscard]] bool isEmpty() const noexcept final;
        [[nodiscard]] bool hasDismissibleNotification() const noexcept final;

        void updateData(app::manager::actions::NotificationsChangedParams *params, bool callAndSMSVisibility) final;
        void dismissAll() final;

      private:
        HBox *tilesBox = nullptr;
    };

} // namespace gui

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

#include "NotificationsListPresenter.hpp"
#include <ListView.hpp>

using namespace gui;

namespace
{
    void setNotificationText(NotificationListItem *item,
                             const notifications::NotificationWithContact *notification,
                             const std::string &text)
    {
        if (notification->hasRecord()) {
            const auto &record = notification->getRecord();
            item->setName(record.getFormattedName());
        }
        else {
            item->setName(utils::translate(text), true);
        }
    }
} // namespace

NotificationsListPresenter::NotificationsListPresenter()
    : app::InternalModel<gui::NotificationListItem *>{}, gui::ListItemProvider{}
{}

unsigned int NotificationsListPresenter::requestRecordsCount()
{
    return internalData.size();
}

gui::ListItem *NotificationsListPresenter::getItem(gui::Order order)
{
    return getRecord(order);
}

void NotificationsListPresenter::requestRecords(uint32_t offset, uint32_t limit)
{
    setupModel(offset, limit);
    list->onProviderDataUpdate();
}

unsigned int NotificationsListPresenter::getMinimalItemSpaceRequired() const
{
    return style::notifications::itemHeight;
}

bool NotificationsListPresenter::hasDismissibleNotification() const noexcept
{
    for (const auto notification : internalData) {
        if (notification->isDismissible()) {
            return true;
        }
    }
    return false;
}

void NotificationsListPresenter::dismissAll()
{
    for (auto it = std::begin(internalData); it != std::end(internalData); it++) {
        if (auto item = *it; item->isDismissible()) {
            if (item->dismissCallback) {
                item->dismissCallback();
            }
        }
    }
}

bool NotificationsListPresenter::isEmpty() const noexcept
{
    return internalData.empty();
}

auto NotificationsListPresenter::create(const notifications::NotSeenSMSNotification *notification)
    -> NotificationListItem *
{
    auto item = new NotificationWithEventCounter(notifications::NotificationType::NotSeenSms,
                                                 utils::to_string(notification->getValue()));
    setNotificationText(item, notification, "app_desktop_unread_messages");
    item->deleteByList = false;
    return item;
}
auto NotificationsListPresenter::create(const notifications::NotSeenCallNotification *notification)
    -> NotificationListItem *
{
    auto item = new NotificationWithEventCounter(notifications::NotificationType::NotSeenCall,
                                                 utils::to_string(notification->getValue()));
    setNotificationText(item, notification, "app_desktop_missed_calls");
    item->deleteByList = false;
    return item;
}

auto NotificationsListPresenter::create(const notifications::TetheringNotification *notification)
    -> NotificationListItem *
{
    auto item = new NotificationWithOnOffButton(notifications::NotificationType::Tethering, gui::ButtonState::On);
    item->setName(utils::translate("Tethering"), false);
    item->deleteByList = false;
    return item;
}

auto NotificationsListPresenter::create(const notifications::AlarmSnoozeNotification *notification)
    -> NotificationListItem *
{
    auto item = new NotificationWithEventCounter(notifications::NotificationType::AlarmSnooze,
                                                 utils::to_string(notification->getValue()));
    item->setName(utils::translate("app_desktop_alarm_snooze"), true);
    item->deleteByList = false;
    return item;
}

auto NotificationsListPresenter::create(const notifications::PhoneLockNotification *notification)
    -> NotificationListItem *
{
    auto item = new NotificationListItem(notifications::NotificationType::PhoneLock);

    item->setName(utils::translate("phone_lock_notification"), true, {{"$TIME", notification->getTime()}});
    item->deleteByList = false;
    return item;
}

void NotificationsListPresenter::updateData(app::manager::actions::NotificationsChangedParams *params,
                                            bool callAndSMSVisibility)
{
    if (list == nullptr) {
        LOG_ERROR("ListView object not provided");
    }

    list->prepareRebuildCallback = [this, toRemove = std::move(internalData)] {
        list->clear();
        for (auto item : toRemove) {
            delete item;
        }
    };

    for (const auto &notification : params->getNotifications()) {
        if (typeid(*notification) == typeid(notifications::NotSeenSMSNotification) && callAndSMSVisibility) {
            auto sms = static_cast<const notifications::NotSeenSMSNotification *>(notification.get());
            internalData.push_back(create(sms));
        }
        else if (typeid(*notification) == typeid(notifications::NotSeenCallNotification) && callAndSMSVisibility) {
            auto call = static_cast<const notifications::NotSeenCallNotification *>(notification.get());
            internalData.push_back(create(call));
        }
        else if (typeid(*notification) == typeid(notifications::TetheringNotification)) {
            auto tethering = static_cast<const notifications::TetheringNotification *>(notification.get());
            internalData.push_back(create(tethering));
        }
        else if (typeid(*notification) == typeid(notifications::PhoneLockNotification)) {
            auto phoneLock = static_cast<const notifications::PhoneLockNotification *>(notification.get());
            internalData.push_back(create(phoneLock));
        }
        else if (typeid(*notification) == typeid(notifications::AlarmSnoozeNotification)) {
            auto snooze = static_cast<const notifications::AlarmSnoozeNotification *>(notification.get());
            internalData.push_back(create(snooze));
        }
    }

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

A module-apps/apps-common/notifications/NotificationsListPresenter.hpp => module-apps/apps-common/notifications/NotificationsListPresenter.hpp +47 -0
@@ 0,0 1,47 @@
// 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 "NotificationsPresenter.hpp"
#include "NotificationListItem.hpp"
#include "NotificationData.hpp"
#include "ListItemProvider.hpp"

#include <apps-common/ApplicationCommon.hpp>
#include "InternalModel.hpp"
#include <service-appmgr/data/NotificationsChangedActionsParams.hpp>

namespace gui
{
    class NotificationsListPresenter : public NotificationsPresenter,
                                       public app::InternalModel<gui::NotificationListItem *>,
                                       public gui::ListItemProvider
    {
        [[nodiscard]] unsigned int requestRecordsCount() final;
        [[nodiscard]] unsigned int getMinimalItemSpaceRequired() const final;
        ListItem *getItem(Order order) final;
        void requestRecords(uint32_t offset, uint32_t limit) final;

      protected:
        [[nodiscard]] virtual auto create(const notifications::NotSeenSMSNotification *notification)
            -> NotificationListItem *;
        [[nodiscard]] virtual auto create(const notifications::NotSeenCallNotification *notification)
            -> NotificationListItem *;
        [[nodiscard]] virtual auto create(const notifications::TetheringNotification *notification)
            -> NotificationListItem *;
        [[nodiscard]] virtual auto create(const notifications::AlarmSnoozeNotification *notification)
            -> NotificationListItem *;
        [[nodiscard]] virtual auto create(const notifications::PhoneLockNotification *notification)
            -> NotificationListItem *;

      public:
        NotificationsListPresenter();
        [[nodiscard]] bool isEmpty() const noexcept final;
        [[nodiscard]] bool hasDismissibleNotification() const noexcept final;

        void updateData(app::manager::actions::NotificationsChangedParams *params, bool callAndSMSVisibility) final;
        void dismissAll() final;
    };

} // namespace gui

M module-apps/apps-common/notifications/NotificationsModel.cpp => module-apps/apps-common/notifications/NotificationsModel.cpp +25 -126
@@ 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 "NotificationsModel.hpp"


@@ 8,18 8,6 @@ using namespace gui;

namespace
{
    void setNotificationText(NotificationListItem *item,
                             const notifications::NotificationWithContact *notification,
                             const std::string &text)
    {
        if (notification->hasRecord()) {
            const auto &record = notification->getRecord();
            item->setName(record.getFormattedName());
        }
        else {
            item->setName(utils::translate(text), true);
        }
    }

    bool hasTetheringNotification(app::manager::actions::NotificationsChangedParams *params)
    {


@@ 40,113 28,53 @@ namespace
    }
} // namespace

NotificationsModel::NotificationsModel(NotificationsListPlacement listPlacement)
    : app::InternalModel<gui::NotificationListItem *>{}, gui::ListItemProvider{}, listPlacement{listPlacement}
NotificationsModel::NotificationsModel(std::shared_ptr<NotificationsPresenter> notificationsPresenter,
                                       NotificationsListPlacement listPlacement)
    : notificationsPresenter{std::move(notificationsPresenter)}, listPlacement{listPlacement}
{}

unsigned int NotificationsModel::requestRecordsCount()
{
    return internalData.size();
}

gui::ListItem *NotificationsModel::getItem(gui::Order order)
{
    return getRecord(order);
}

void NotificationsModel::requestRecords(uint32_t offset, uint32_t limit)
{
    setupModel(offset, limit);
    list->onProviderDataUpdate();
}
NotificationsModel::NotificationsModel(NotificationsListPlacement listPlacement) : listPlacement{listPlacement}
{}

unsigned int NotificationsModel::getMinimalItemSpaceRequired() const
void NotificationsModel::attachPresenter(std::shared_ptr<NotificationsPresenter> notificationsPresenter)
{
    return style::notifications::itemHeight;
    this->notificationsPresenter = notificationsPresenter;
}

bool NotificationsModel::hasDismissibleNotification() const noexcept
{
    for (const auto notification : internalData) {
        if (notification->isDismissible()) {
            return true;
        }
    if (notificationsPresenter == nullptr) {
        LOG_ERROR("Presenter not attached!");
        return false;
    }
    return false;
    return notificationsPresenter->hasDismissibleNotification();
}

void NotificationsModel::dismissAll()
{
    for (auto it = std::begin(internalData); it != std::end(internalData); it++) {
        if (auto item = *it; item->isDismissible()) {
            if (item->dismissCallback) {
                item->dismissCallback();
            }
        }
    if (notificationsPresenter == nullptr) {
        LOG_ERROR("Presenter not attached!");
        return;
    }
    notificationsPresenter->dismissAll();
}

bool NotificationsModel::isEmpty() const noexcept
{
    return internalData.empty();
}

auto NotificationsModel::create(const notifications::NotSeenSMSNotification *notification) -> NotificationListItem *
{
    auto item = new NotificationWithEventCounter(notifications::NotificationType::NotSeenSms,
                                                 utils::to_string(notification->getValue()));
    setNotificationText(item, notification, "app_desktop_unread_messages");
    item->deleteByList = false;
    return item;
}
auto NotificationsModel::create(const notifications::NotSeenCallNotification *notification) -> NotificationListItem *
{
    auto item = new NotificationWithEventCounter(notifications::NotificationType::NotSeenCall,
                                                 utils::to_string(notification->getValue()));
    setNotificationText(item, notification, "app_desktop_missed_calls");
    item->deleteByList = false;
    return item;
}

auto NotificationsModel::create(const notifications::TetheringNotification *notification) -> NotificationListItem *
{
    auto item = new NotificationWithOnOffButton(notifications::NotificationType::Tethering, gui::ButtonState::On);
    item->setName(utils::translate("Tethering"), false);
    item->deleteByList = false;
    return item;
}

auto NotificationsModel::create(const notifications::AlarmSnoozeNotification *notification) -> NotificationListItem *
{
    auto item = new NotificationWithEventCounter(notifications::NotificationType::AlarmSnooze,
                                                 utils::to_string(notification->getValue()));
    item->setName(utils::translate("app_desktop_alarm_snooze"), true);
    item->deleteByList = false;
    return item;
}

auto NotificationsModel::create(const notifications::PhoneLockNotification *notification) -> NotificationListItem *
{
    auto item = new NotificationListItem(notifications::NotificationType::PhoneLock);

    item->setName(utils::translate("phone_lock_notification"), true, {{"$TIME", notification->getTime()}});
    item->deleteByList = false;
    return item;
    if (notificationsPresenter == nullptr) {
        LOG_ERROR("Presenter not attached!");
        return false;
    }
    return notificationsPresenter->isEmpty();
}

void NotificationsModel::updateData(app::manager::actions::NotificationsChangedParams *params)
{
    if (list == nullptr) {
        LOG_ERROR("ListView object not provided");
    if (notificationsPresenter == nullptr) {
        LOG_ERROR("Presenter not attached!");
        return;
    }

    list->prepareRebuildCallback = [this, toRemove = std::move(internalData)] {
        list->clear();
        for (auto item : toRemove) {
            delete item;
        }
    };

    const auto showOnLocked =
        (listPlacement == NotificationsListPlacement::LockedScreen) && params->showNotificationsWhenLocked();
    phoneTimeLock = hasPhoneLockTime(params);


@@ 154,38 82,9 @@ void NotificationsModel::updateData(app::manager::actions::NotificationsChangedP
    const auto callAndSMSVisibility =
        ((listPlacement == NotificationsListPlacement::Desktop) || showOnLocked) && not tetheringOn;

    for (const auto &notification : params->getNotifications()) {
        if (typeid(*notification) == typeid(notifications::NotSeenSMSNotification) && callAndSMSVisibility) {
            auto sms = static_cast<const notifications::NotSeenSMSNotification *>(notification.get());
            internalData.push_back(create(sms));
        }
        else if (typeid(*notification) == typeid(notifications::NotSeenCallNotification) && callAndSMSVisibility) {
            auto call = static_cast<const notifications::NotSeenCallNotification *>(notification.get());
            internalData.push_back(create(call));
        }
        else if (typeid(*notification) == typeid(notifications::TetheringNotification)) {
            auto tethering = static_cast<const notifications::TetheringNotification *>(notification.get());
            internalData.push_back(create(tethering));
        }
        else if (typeid(*notification) == typeid(notifications::PhoneLockNotification)) {
            auto phoneLock = static_cast<const notifications::PhoneLockNotification *>(notification.get());
            internalData.push_back(create(phoneLock));
        }
        else if (typeid(*notification) == typeid(notifications::AlarmSnoozeNotification)) {
            auto snooze = static_cast<const notifications::AlarmSnoozeNotification *>(notification.get());
            internalData.push_back(create(snooze));
        }
    }

    list->rebuildList(listview::RebuildType::InPlace);
    list->prepareRebuildCallback = nullptr;
    notificationsPresenter->updateData(params, callAndSMSVisibility);
}

void NotificationsModel::clearAll()
{
    list->reset();
    eraseInternalData();
}

bool NotificationsModel::isTetheringOn() const noexcept
{

M module-apps/apps-common/notifications/NotificationsModel.hpp => module-apps/apps-common/notifications/NotificationsModel.hpp +8 -24
@@ 1,14 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

#pragma once

#include "NotificationListItem.hpp"
#include "NotificationData.hpp"
#include "ListItemProvider.hpp"

#include "NotificationsPresenter.hpp"
#include <apps-common/ApplicationCommon.hpp>
#include "InternalModel.hpp"
#include <service-appmgr/data/NotificationsChangedActionsParams.hpp>

namespace gui


@@ 18,30 14,19 @@ namespace gui
        Desktop,
        LockedScreen
    };
    class NotificationsModel : public app::InternalModel<gui::NotificationListItem *>, public gui::ListItemProvider
    class NotificationsModel
    {
        [[nodiscard]] unsigned int requestRecordsCount() final;
        [[nodiscard]] unsigned int getMinimalItemSpaceRequired() const final;
        ListItem *getItem(Order order) final;
        void requestRecords(uint32_t offset, uint32_t limit) final;

      protected:
      private:
        std::shared_ptr<NotificationsPresenter> notificationsPresenter;
        bool tetheringOn = false;
        bool phoneTimeLock = false;
        const NotificationsListPlacement listPlacement;
        [[nodiscard]] virtual auto create(const notifications::NotSeenSMSNotification *notification)
            -> NotificationListItem *;
        [[nodiscard]] virtual auto create(const notifications::NotSeenCallNotification *notification)
            -> NotificationListItem *;
        [[nodiscard]] virtual auto create(const notifications::TetheringNotification *notification)
            -> NotificationListItem *;
        [[nodiscard]] virtual auto create(const notifications::AlarmSnoozeNotification *notification)
            -> NotificationListItem *;
        [[nodiscard]] virtual auto create(const notifications::PhoneLockNotification *notification)
            -> NotificationListItem *;

      public:
        explicit NotificationsModel(std::shared_ptr<NotificationsPresenter> notificationsPresenter,
                                    NotificationsListPlacement listPlacement = NotificationsListPlacement::Desktop);
        explicit NotificationsModel(NotificationsListPlacement listPlacement = NotificationsListPlacement::Desktop);
        void attachPresenter(std::shared_ptr<NotificationsPresenter> notificationsPresenter);
        [[nodiscard]] bool isEmpty() const noexcept;
        [[nodiscard]] bool hasDismissibleNotification() const noexcept;
        [[nodiscard]] bool isTetheringOn() const noexcept;


@@ 49,7 34,6 @@ namespace gui

        void updateData(app::manager::actions::NotificationsChangedParams *params);
        void dismissAll();
        void clearAll();
    };

} // namespace gui

A module-apps/apps-common/notifications/NotificationsPresenter.hpp => module-apps/apps-common/notifications/NotificationsPresenter.hpp +22 -0
@@ 0,0 1,22 @@
// 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 "NotificationData.hpp"
#include <service-appmgr/data/NotificationsChangedActionsParams.hpp>

namespace gui
{
    class NotificationsPresenter
    {
      public:
        NotificationsPresenter()                                                       = default;
        [[nodiscard]] virtual auto isEmpty() const noexcept -> bool                    = 0;
        [[nodiscard]] virtual auto hasDismissibleNotification() const noexcept -> bool = 0;
        virtual void updateData(app::manager::actions::NotificationsChangedParams *params,
                                bool callAndSMSVisibility)                             = 0;
        virtual void dismissAll()                                                      = 0;
    };

} // namespace gui

M module-apps/apps-common/popups/lock-popups/PhoneLockedWindow.cpp => module-apps/apps-common/popups/lock-popups/PhoneLockedWindow.cpp +11 -9
@@ 8,20 8,15 @@
#include <locks/input/PhoneLockedKeysWhitelist.hpp>
#include <service-appmgr/Controller.hpp>
#include <popups/data/PopupData.hpp>
#include <notifications/NotificationsModel.hpp>

namespace gui
{
    PhoneLockedWindow::PhoneLockedWindow(app::ApplicationCommon *app,
                                         const std::string &name,
                                         std::unique_ptr<WallpaperPresenter> &&presenter)
        : AppWindow(app, name),
          notificationsModel(std::make_shared<NotificationsModel>(NotificationsListPlacement::LockedScreen)),
          clockWallpaper(std::make_shared<WallpaperClock>(this, notificationsModel)),
          wallpaperPresenter(std::move(presenter))
        : AppWindow(app, name), wallpaperPresenter(std::move(presenter))
    {
        wallpaperPresenter->attachWallpapers(
            clockWallpaper, std::make_shared<WallpaperQuote>(app, this), std::make_shared<WallpaperLogo>(this));

        buildInterface();

        preBuildDrawListHook = [this](std::list<Command> &cmd) { updateTime(); };


@@ 36,11 31,12 @@ namespace gui
    void PhoneLockedWindow::buildInterface()
    {
        AppWindow::buildInterface();
        wallpaperPresenter->setupWallpaper();
        wallpaperPresenter->setupWallpaper(this);
    }

    void PhoneLockedWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        auto notificationsModel = wallpaperPresenter->getNotificationsModel();
        auto notificationData = dynamic_cast<app::manager::actions::NotificationsChangedParams *>(data);
        if (notificationData) {
            notificationsModel->updateData(notificationData);


@@ 54,6 50,9 @@ namespace gui
        }

        if (notificationsModel->isPhoneTimeLock()) {
            wallpaperPresenter->forceClockWallpaper();
            notificationsModel->updateData(notificationData);

            if (!refreshedOnPhoneLockTimeLock) {
                application->refreshWindow(RefreshModes::GUI_REFRESH_DEEP);
                refreshedOnPhoneLockTimeLock = true;


@@ 64,6 63,9 @@ namespace gui
            navBar->setActive(nav_bar::Side::Right, false);
        }
        else {
            if (wallpaperPresenter->switchBackWallpaper()) {
                notificationsModel->updateData(notificationData);
            }
            navBar->setActive(nav_bar::Side::Left, false);
            navBar->setText(nav_bar::Side::Center, utils::translate("app_desktop_unlock"));
            navBar->setActive(nav_bar::Side::Right, false);


@@ 74,7 76,7 @@ namespace gui
    bool PhoneLockedWindow::updateTime()
    {
        auto ret = AppWindow::updateTime();
        clockWallpaper->updateTime();
        wallpaperPresenter->updateTime();
        return ret;
    }


M module-apps/apps-common/popups/lock-popups/PhoneLockedWindow.hpp => module-apps/apps-common/popups/lock-popups/PhoneLockedWindow.hpp +2 -13
@@ 3,10 3,6 @@

#pragma once

#include "phone-lock-wallpapers/WallpaperClock.hpp"
#include "phone-lock-wallpapers/WallpaperQuote.hpp"
#include "phone-lock-wallpapers/WallpaperLogo.hpp"

#include <apps-common/popups/presenter/WallpaperPresenter.hpp>
#include <AppWindow.hpp>



@@ 32,21 28,14 @@ namespace gui

        bool updateTime() override;

      protected:
        gui::ClockDateWidget *clockDate                             = nullptr;
        gui::ListView *notificationsList                            = nullptr;
        std::shared_ptr<gui::NotificationsModel> notificationsModel = nullptr;
        bool refreshedOnPhoneLockTimeLock                           = false;

        bool processLongReleaseEvent(const InputEvent &inputEvent);

      private:
        bool processLongReleaseEvent(const InputEvent &inputEvent);
        static constexpr auto refreshTimerName = "PhoneLockRefreshTimer";
        static constexpr auto refreshTimeout   = std::chrono::hours(4);
        sys::TimerHandle screenRefreshTimer;

        std::shared_ptr<WallpaperClock> clockWallpaper;
        std::unique_ptr<WallpaperPresenter> wallpaperPresenter;
        bool refreshedOnPhoneLockTimeLock = false;
    };

} /* namespace gui */

M module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperBase.hpp => module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperBase.hpp +2 -1
@@ 4,6 4,7 @@
#pragma once

#include <AppWindow.hpp>
#include <notifications/NotificationsPresenter.hpp>

namespace gui
{


@@ 14,9 15,9 @@ namespace gui

      public:
        explicit WallpaperBase(Item *parent);
        virtual void build() = 0;
        virtual void show()  = 0;
        virtual void hide()  = 0;
        virtual std::shared_ptr<NotificationsPresenter> getNotificationsPresenter() = 0;
    };

} /* namespace gui */

M module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperClock.cpp => module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperClock.cpp +8 -6
@@ 6,11 6,8 @@

namespace gui
{
    WallpaperClock::WallpaperClock(Item *parent, std::shared_ptr<NotificationsModel> notificationsModel)
        : WallpaperBase(parent), notificationsModel(notificationsModel)
    {}

    void WallpaperClock::build()
    WallpaperClock::WallpaperClock(Item *parent)
        : WallpaperBase(parent), notificationsListPresenter(std::make_shared<NotificationsListPresenter>())
    {
        clockDate = new ClockDateWidget(
            parent, 0, style::window::default_vertical_pos, style::window_width, clock_date_widget::h);


@@ 20,7 17,7 @@ namespace gui
                                         style::notifications::model::y,
                                         style::notifications::model::w,
                                         style::notifications::model::h,
                                         notificationsModel,
                                         notificationsListPresenter,
                                         listview::ScrollBarType::None);
        hide();
    }


@@ 37,6 34,11 @@ namespace gui
        notificationsList->setVisible(false);
    }

    std::shared_ptr<NotificationsPresenter> WallpaperClock::getNotificationsPresenter()
    {
        return notificationsListPresenter;
    }

    void WallpaperClock::updateTime()
    {
        clockDate->setTime(std::time(nullptr));

M module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperClock.hpp => module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperClock.hpp +5 -5
@@ 1,11 1,11 @@
// 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

#include "WallpaperBase.hpp"
#include <widgets/ClockDateWidget.hpp>
#include <notifications/NotificationsModel.hpp>
#include <notifications/NotificationsListPresenter.hpp>
#include <ListView.hpp>

namespace gui


@@ 15,13 15,13 @@ namespace gui
      private:
        gui::ClockDateWidget *clockDate                             = nullptr;
        gui::ListView *notificationsList                            = nullptr;
        std::shared_ptr<gui::NotificationsModel> notificationsModel = nullptr;
        std::shared_ptr<gui::NotificationsListPresenter> notificationsListPresenter;

      public:
        WallpaperClock(gui::Item *parent, std::shared_ptr<gui::NotificationsModel> notificationsModel);
        void build() override;
        WallpaperClock(gui::Item *parent);
        void show() override;
        void hide() override;
        std::shared_ptr<NotificationsPresenter> getNotificationsPresenter() override;

        void updateTime();
    };

M module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperLogo.cpp => module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperLogo.cpp +24 -14
@@ 4,36 4,46 @@
#include "WallpaperLogo.hpp"
#include <service-appmgr/Controller.hpp>
#include <Style.hpp>
#include <ImageBox.hpp>
#include <Image.hpp>

namespace gui
{
    WallpaperLogo::WallpaperLogo(Item *parent) : WallpaperBase(parent)
    {}

    void WallpaperLogo::build()
    WallpaperLogo::WallpaperLogo(Item *parent)
        : WallpaperBase(parent), notificationsPresenter(std::make_shared<NotificationTilesPresenter>())
    {
        logoImage = new ImageBox(parent,
                                 0,
                                 style::logo::y,
                                 ::style::window_width,
                                 ::style::window::default_body_height - style::logo::y,
                                 new Image("logo", ImageTypeSpecifier::W_G));
        wallpaperBox = new VBox(parent,
                                ::style::window::default_left_margin,
                                ::style::wallpaper::wallpaperBox::y,
                                ::style::window::default_body_width,
                                ::style::wallpaper::wallpaperBox::h);
        wallpaperBox->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        wallpaperBox->setEdges(RectangleEdge::None);

        auto logoImage = new ImageBox(wallpaperBox, new Image("logo", ImageTypeSpecifier::W_G));
        logoImage->setMinimumSizeToFitImage();
        logoImage->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        logoImage->setMargins(Margins(0, style::logo::logoTopMarigin, 0, style::logo::logoBottomMarigin));

        new NotificationTilesBox(wallpaperBox, notificationsPresenter);
        hide();
    }

    void WallpaperLogo::show()
    {
        logoImage->setVisible(true);
        logoImage->resizeItems();
        wallpaperBox->setVisible(true);
        wallpaperBox->resizeItems();
    }

    void WallpaperLogo::hide()
    {
        logoImage->setVisible(false);
        logoImage->resizeItems();
        wallpaperBox->setVisible(false);
        wallpaperBox->resizeItems();
    }

    std::shared_ptr<NotificationsPresenter> WallpaperLogo::getNotificationsPresenter()
    {
        return notificationsPresenter;
    }

} /* namespace gui */

M module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperLogo.hpp => module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperLogo.hpp +8 -5
@@ 1,11 1,12 @@
// 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

#include "WallpaperBase.hpp"

#include <ImageBox.hpp>
#include <BoxLayout.hpp>
#include <notifications/NotificationTilesBox.hpp>

namespace gui
{


@@ 13,20 14,22 @@ namespace gui
    {
        namespace logo
        {
            constexpr auto y = 163;
            constexpr inline auto logoTopMarigin    = 53;
            constexpr inline auto logoBottomMarigin = 70;
        } // namespace logo

    } // namespace style
    class WallpaperLogo : public WallpaperBase
    {
      private:
        ImageBox *logoImage = nullptr;
        std::shared_ptr<NotificationTilesPresenter> notificationsPresenter;
        VBox *wallpaperBox = nullptr;

      public:
        WallpaperLogo(gui::Item *parent);
        void build() override;
        void show() override;
        void hide() override;
        std::shared_ptr<NotificationsPresenter> getNotificationsPresenter() override;
    };

} /* namespace gui */

M module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperQuote.cpp => module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperQuote.cpp +25 -21
@@ 6,11 6,12 @@
#include <ImageBox.hpp>
#include <Text.hpp>
#include <Style.hpp>

#include <notifications/NotificationTilesBox.hpp>
namespace gui
{
    WallpaperQuote::WallpaperQuote(app::ApplicationCommon *app, Item *parent)
        : WallpaperBase(parent), quotesPresenter{std::make_unique<QuotesPresenter>(app)}
        : WallpaperBase(parent), quotesPresenter{std::make_unique<QuotesPresenter>(app)},
          notificationsPresenter(std::make_shared<NotificationTilesPresenter>())
    {
        quotesPresenter->setQuoteDisplayCallback([&](std::string quote, std::string author) {
            quoteText->setText(quote);


@@ 19,26 20,23 @@ namespace gui
            authorText->setText(std::string("- ") + author);
            authorText->setMinimumWidthToFitText();
            authorText->setMinimumHeightToFitText();
            textBox->resizeItems();
            wallpaperBox->resizeItems();
        });
    }

    void WallpaperQuote::build()
    {
        textBox = new VBox(parent,
                           ::style::window::default_left_margin,
                           style::textBox::y,
                           ::style::window::default_body_width,
                           style::textBox::h);
        textBox->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        textBox->setEdges(RectangleEdge::None);
        wallpaperBox = new VBox(parent,
                                ::style::window::default_left_margin,
                                ::style::wallpaper::wallpaperBox::y,
                                ::style::window::default_body_width,
                                ::style::wallpaper::wallpaperBox::h);
        wallpaperBox->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        wallpaperBox->setEdges(RectangleEdge::None);

        auto quoteImage = new ImageBox(textBox, new Image("quote", ImageTypeSpecifier::W_G));
        auto quoteImage = new ImageBox(wallpaperBox, new Image("quote", ImageTypeSpecifier::W_G));
        quoteImage->setMinimumSizeToFitImage();
        quoteImage->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        quoteImage->setMargins(Margins(0, 0, 0, 0));

        quoteText = new TextFixedSize(textBox, 0, 0, 0, 0);
        quoteText = new TextFixedSize(wallpaperBox, 0, 0, 0, 0);
        quoteText->setMaximumSize(::style::window::default_body_width, style::text::h);
        quoteText->setMargins(Margins(0, style::text::topMarigin, 0, style::text::bottomMarigin));
        quoteText->setFont(::style::window::font::biglight);


@@ 47,25 45,31 @@ namespace gui
        quoteText->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        quoteText->drawUnderline(false);

        authorText = new Text(textBox, 0, 0, 0, 0);
        authorText->setMargins(Margins(0, 0, 0, 0));
        authorText = new Text(wallpaperBox, 0, 0, 0, 0);
        authorText->setMargins(Margins(0, 0, 0, style::text::authorBottomMarigin));
        authorText->setFont(::style::window::font::small);
        authorText->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));

        new NotificationTilesBox(wallpaperBox, notificationsPresenter);

        hide();
    }

    void WallpaperQuote::show()
    {
        quotesPresenter->requestQuote();
        textBox->setVisible(true);
        textBox->resizeItems();
        wallpaperBox->setVisible(true);
        wallpaperBox->resizeItems();
    }

    void WallpaperQuote::hide()
    {
        textBox->setVisible(false);
        textBox->resizeItems();
        wallpaperBox->setVisible(false);
        wallpaperBox->resizeItems();
    }

    std::shared_ptr<NotificationsPresenter> WallpaperQuote::getNotificationsPresenter()
    {
        return notificationsPresenter;
    }
} /* namespace gui */

M module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperQuote.hpp => module-apps/apps-common/popups/lock-popups/phone-lock-wallpapers/WallpaperQuote.hpp +10 -13
@@ 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


@@ 6,23 6,19 @@
#include "WallpaperBase.hpp"
#include <apps-common/popups/presenter/QuotesPresenter.hpp>
#include <TextFixedSize.hpp>
#include <notifications/NotificationTilesBox.hpp>

namespace gui
{
    namespace style
    {
        namespace textBox
        {
            constexpr auto y = 110;
            constexpr auto h = 340;
        } // namespace textBox

        namespace text
        {
            constexpr auto h             = 225;
            constexpr auto topMarigin    = 20;
            constexpr auto bottomMarigin = 30;
            constexpr auto interline     = 12;
            constexpr inline auto h                   = 225;
            constexpr inline auto topMarigin          = 20;
            constexpr inline auto bottomMarigin       = 30;
            constexpr inline auto interline           = 12;
            constexpr inline auto authorBottomMarigin = 42;

        } // namespace text



@@ 32,15 28,16 @@ namespace gui
    {
      private:
        std::unique_ptr<QuotesPresenter> quotesPresenter;
        VBox *textBox            = nullptr;
        std::shared_ptr<NotificationTilesPresenter> notificationsPresenter;
        VBox *wallpaperBox       = nullptr;
        TextFixedSize *quoteText = nullptr;
        Text *authorText         = nullptr;

      public:
        WallpaperQuote(app::ApplicationCommon *app, Item *parent);
        void build() override;
        void show() override;
        void hide() override;
        std::shared_ptr<NotificationsPresenter> getNotificationsPresenter() override;
    };

} /* namespace gui */

M module-apps/apps-common/popups/presenter/WallpaperPresenter.cpp => module-apps/apps-common/popups/presenter/WallpaperPresenter.cpp +66 -33
@@ 2,58 2,91 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "WallpaperPresenter.hpp"
#include <service-appmgr/messages/GetWallpaperOptionRequest.hpp>
#include <service-appmgr/Constants.hpp>

namespace gui
{
    WallpaperPresenter::WallpaperPresenter(app::ApplicationCommon *app) : AsyncCallbackReceiver(app), application(app)
    WallpaperPresenter::WallpaperPresenter(app::ApplicationCommon *app)
        : AsyncCallbackReceiver(app), application(app),
          notificationsModel(std::make_shared<NotificationsModel>(NotificationsListPlacement::LockedScreen))
    {}

    void WallpaperPresenter::attachWallpapers(std::shared_ptr<WallpaperBase> clockWallpaper,
                                              std::shared_ptr<WallpaperBase> quoteWallpaper,
                                              std::shared_ptr<WallpaperBase> logoWallpaper)
    void WallpaperPresenter::setupWallpaper(Item *parent)
    {
        this->clockWallpaper = clockWallpaper;
        this->quoteWallpaper = quoteWallpaper;
        this->logoWallpaper  = logoWallpaper;
    }

    void WallpaperPresenter::setupWallpaper()
    {
        buildWallpapers();
        buildWallpapers(parent);

        auto request = std::make_unique<app::manager::GetWallpaperOptionRequest>();
        auto task    = app::AsyncRequest::createFromMessage(std::move(request), service::name::appmgr);
        auto cb      = [&](auto response) {
            auto result = dynamic_cast<app::manager::GetWallpaperOptionResponse *>(response);
            switch (result->getWallpaperOption()) {
            case WallpaperOption::Clock:
                clockWallpaper->show();
                quoteWallpaper->hide();
                logoWallpaper->hide();
                break;
            case WallpaperOption::Quote:
                clockWallpaper->hide();
                quoteWallpaper->show();
                logoWallpaper->hide();
                break;
            case WallpaperOption::Logo:
                clockWallpaper->hide();
                quoteWallpaper->hide();
                logoWallpaper->show();
                break;
            if (!clockWallpaperForced) {
                switchWallpaper(result->getWallpaperOption());
            }
            selectedOption = result->getWallpaperOption();
            return true;
        };
        task->execute(application, this, cb);
    }

    void WallpaperPresenter::buildWallpapers()
    void WallpaperPresenter::switchWallpaper(WallpaperOption option)
    {
        switch (option) {
        case WallpaperOption::Clock:
            notificationsModel->attachPresenter(clockWallpaper->getNotificationsPresenter());
            clockWallpaper->show();
            quoteWallpaper->hide();
            logoWallpaper->hide();
            break;
        case WallpaperOption::Quote:
            notificationsModel->attachPresenter(quoteWallpaper->getNotificationsPresenter());
            clockWallpaper->hide();
            quoteWallpaper->show();
            logoWallpaper->hide();
            break;
        case WallpaperOption::Logo:
            notificationsModel->attachPresenter(logoWallpaper->getNotificationsPresenter());
            clockWallpaper->hide();
            quoteWallpaper->hide();
            logoWallpaper->show();
            break;
        }
    }

    void WallpaperPresenter::buildWallpapers(Item *parent)
    {
        clockWallpaper->build();
        quoteWallpaper->build();
        logoWallpaper->build();
        clockWallpaper = std::make_shared<WallpaperClock>(parent);
        quoteWallpaper = std::make_shared<WallpaperQuote>(application, parent);
        logoWallpaper  = std::make_shared<WallpaperLogo>(parent);
    }

    std::shared_ptr<gui::NotificationsModel> WallpaperPresenter::getNotificationsModel()
    {
        return notificationsModel;
    }

    void WallpaperPresenter::updateTime()
    {
        if (clockWallpaper) {
            clockWallpaper->updateTime();
        }
    }

    void WallpaperPresenter::forceClockWallpaper()
    {
        switchWallpaper(WallpaperOption::Clock);
        clockWallpaperForced = true;
    }

    bool WallpaperPresenter::switchBackWallpaper()
    {
        if (clockWallpaperForced) {
            clockWallpaperForced = false;
            switchWallpaper(selectedOption);
            return true;
        }
        else {
            return false;
        }
    }

} // namespace gui

M module-apps/apps-common/popups/presenter/WallpaperPresenter.hpp => module-apps/apps-common/popups/presenter/WallpaperPresenter.hpp +19 -9
@@ 4,7 4,11 @@
#pragma once

#include <ApplicationCommon.hpp>
#include <popups/lock-popups/phone-lock-wallpapers/WallpaperBase.hpp>
#include <service-appmgr/messages/GetWallpaperOptionRequest.hpp>
#include <popups/lock-popups/phone-lock-wallpapers/WallpaperClock.hpp>
#include <popups/lock-popups/phone-lock-wallpapers/WallpaperQuote.hpp>
#include <popups/lock-popups/phone-lock-wallpapers/WallpaperLogo.hpp>
#include <notifications/NotificationsModel.hpp>

namespace gui
{


@@ 12,17 16,23 @@ namespace gui
    {
      public:
        WallpaperPresenter(app::ApplicationCommon *app);
        void attachWallpapers(std::shared_ptr<WallpaperBase> clockWallpaper,
                              std::shared_ptr<WallpaperBase> quoteWallpaper,
                              std::shared_ptr<WallpaperBase> logoWallpaper);
        void setupWallpaper();
        void setupWallpaper(Item *parent);
        std::shared_ptr<gui::NotificationsModel> getNotificationsModel();
        void updateTime();
        void forceClockWallpaper();
        /// returns true if actual switch back occured
        bool switchBackWallpaper();

      private:
        void buildWallpapers();
        void buildWallpapers(Item *parent);
        void switchWallpaper(WallpaperOption option);
        app::ApplicationCommon *application;
        std::shared_ptr<WallpaperBase> clockWallpaper = nullptr;
        std::shared_ptr<WallpaperBase> quoteWallpaper = nullptr;
        std::shared_ptr<WallpaperBase> logoWallpaper  = nullptr;
        std::shared_ptr<gui::NotificationsModel> notificationsModel;
        std::shared_ptr<WallpaperClock> clockWallpaper = nullptr;
        std::shared_ptr<WallpaperQuote> quoteWallpaper = nullptr;
        std::shared_ptr<WallpaperLogo> logoWallpaper   = nullptr;
        bool clockWallpaperForced                      = false;
        WallpaperOption selectedOption                 = WallpaperOption::Clock;
    };

} // namespace gui

M module-gui/gui/widgets/Style.hpp => module-gui/gui/widgets/Style.hpp +16 -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

#pragma once


@@ 311,4 311,19 @@ namespace style
        } // namespace model
    }     // namespace notifications

    namespace wallpaper
    {
        namespace wallpaperBox
        {
            constexpr auto y = 110;
            constexpr auto h = 534;
        } // namespace wallpaperBox

        namespace notificationTiles
        {
            constexpr inline auto tileIconHeight  = 45;
            constexpr inline auto tileIconMarigin = 15;
        } // namespace notificationTiles
    }     // namespace wallpaper

}; // namespace style