~aleteoryx/muditaos

375d269d4a9a171b25a9c180aa8b89a1c3f2ca49 — Maciej Gibowicz 1 year, 11 months ago 790c643
[BH-1637] Add low battery screen before using the application

If the battery is discharged below 10%, the user gets a
notification before using the meditation and relaxation application.
33 files changed, 379 insertions(+), 299 deletions(-)

M harmony_changelog.md
M products/BellHybrid/apps/application-bell-main/ApplicationBellMain.cpp
M products/BellHybrid/apps/application-bell-main/CMakeLists.txt
M products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp
M products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.cpp
M products/BellHybrid/apps/application-bell-meditation-timer/MeditationTimer.cpp
M products/BellHybrid/apps/application-bell-meditation-timer/data/MeditationCommon.hpp
M products/BellHybrid/apps/application-bell-meditation-timer/include/application-bell-meditation-timer/MeditationTimer.hpp
M products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationTimerPresenter.cpp
M products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationTimerPresenter.hpp
M products/BellHybrid/apps/application-bell-relaxation/ApplicationBellRelaxation.cpp
M products/BellHybrid/apps/application-bell-relaxation/CMakeLists.txt
M products/BellHybrid/apps/application-bell-relaxation/data/RelaxationSwitchData.hpp
M products/BellHybrid/apps/application-bell-relaxation/include/application-bell-relaxation/ApplicationBellRelaxation.hpp
D products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationLowBatteryPresenter.cpp
D products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationLowBatteryPresenter.hpp
M products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationRunningLoopPresenter.cpp
M products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationRunningLoopPresenter.hpp
M products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationTimerSelectPresenter.cpp
M products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationTimerSelectPresenter.hpp
D products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationLowBatteryWindow.cpp
D products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationLowBatteryWindow.hpp
M products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationRunningLoopWindow.cpp
M products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationRunningLoopWindow.hpp
M products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationTimerSelectWindow.cpp
M products/BellHybrid/apps/common/CMakeLists.txt
A products/BellHybrid/apps/common/include/common/data/BatteryStatusSwitchData.hpp
A products/BellHybrid/apps/common/include/common/models/LowBatteryInfoModel.hpp
A products/BellHybrid/apps/common/include/common/windows/AppsBatteryStatusWindow.hpp
R products/BellHybrid/apps/{application-bell-main => common/include/common}/windows/BellBatteryStatusWindow.hpp
A products/BellHybrid/apps/common/src/models/LowBatteryInfoModel.cpp
A products/BellHybrid/apps/common/src/windows/AppsBatteryStatusWindow.cpp
R products/BellHybrid/apps/{application-bell-main => common/src}/windows/BellBatteryStatusWindow.cpp
M harmony_changelog.md => harmony_changelog.md +1 -0
@@ 8,6 8,7 @@
### Added
* Added setting onboarding year to build date year
* Added low battery notification on the home screen
* Added low battery notification before using the application

### Changed / Improved


M products/BellHybrid/apps/application-bell-main/ApplicationBellMain.cpp => products/BellHybrid/apps/application-bell-main/ApplicationBellMain.cpp +6 -5
@@ 7,7 7,6 @@
#include "windows/BellBatteryShutdownWindow.hpp"
#include "windows/BellHomeScreenWindow.hpp"
#include "windows/BellMainMenuWindow.hpp"
#include "windows/BellBatteryStatusWindow.hpp"

#include <apps-common/messages/AppMessage.hpp>
#include <common/BellPowerOffPresenter.hpp>


@@ 17,6 16,7 @@
#include <common/models/LayoutModel.hpp>
#include <common/windows/BellWelcomeWindow.hpp>
#include <common/windows/BellFactoryReset.hpp>
#include <common/windows/BellBatteryStatusWindow.hpp>
#include <common/BellFactoryResetPresenter.hpp>
#include <service-db/DBNotificationMessage.hpp>
#include <windows/Dialog.hpp>


@@ 155,9 155,10 @@ namespace app
            return std::make_unique<gui::BellFactoryReset>(app, std::make_unique<gui::BellFactoryResetPresenter>(app));
        });

        windowsFactory.attach(gui::BellBatteryStatusWindow::name, [](ApplicationCommon *app, const std::string &name) {
            return std::make_unique<gui::BellBatteryStatusWindow>(app);
        });
        windowsFactory.attach(gui::BellBatteryStatusWindow::windowName,
                              [](ApplicationCommon *app, const std::string &name) {
                                  return std::make_unique<gui::BellBatteryStatusWindow>(app);
                              });

        windowsFactory.attach(
            gui::window::name::bell_main_menu_dialog,


@@ 202,7 203,7 @@ namespace app
            }
            else if (newWindowName == gui::window::name::bell_main_menu ||
                     newWindowName == gui::window::name::bell_main_menu_dialog ||
                     newWindowName == gui::BellBatteryStatusWindow::name) {
                     newWindowName == gui::BellBatteryStatusWindow::windowName) {
                startIdleTimer();
                clearPendingPopups();
            }

M products/BellHybrid/apps/application-bell-main/CMakeLists.txt => products/BellHybrid/apps/application-bell-main/CMakeLists.txt +0 -2
@@ 8,7 8,6 @@ target_sources(application-bell-main
        windows/BellBatteryShutdownWindow.cpp
        windows/BellHomeScreenWindow.cpp
        windows/BellMainMenuWindow.cpp
        windows/BellBatteryStatusWindow.cpp

        models/TemperatureModel.cpp



@@ 18,7 17,6 @@ target_sources(application-bell-main
        windows/BellBatteryShutdownWindow.hpp
        windows/BellHomeScreenWindow.hpp
        windows/BellMainMenuWindow.hpp
        windows/BellBatteryStatusWindow.hpp

        models/TemperatureModel.hpp


M products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp => products/BellHybrid/apps/application-bell-main/presenters/HomeScreenPresenter.cpp +6 -6
@@ 6,13 6,14 @@
#include "models/TemperatureModel.hpp"

#include <windows/BellHomeScreenWindow.hpp>
#include <windows/BellBatteryStatusWindow.hpp>
#include <application-bell-main/ApplicationBellMain.hpp>
#include <apps-common/ApplicationCommon.hpp>
#include <common/layouts/BaseHomeScreenLayoutProvider.hpp>
#include <common/models/TimeModel.hpp>
#include <common/models/BatteryModel.hpp>
#include <common/widgets/ProgressTimerWithSnoozeTimer.hpp>
#include <common/windows/BellBatteryStatusWindow.hpp>
#include <common/data/BatteryStatusSwitchData.hpp>
#include <Timers/SystemTimer.hpp>
#include <Timers/TimerFactory.hpp>
#include <service-db/DBNotificationMessage.hpp>


@@ 250,15 251,14 @@ namespace app::home_screen

    void HomeScreenPresenter::switchToBatteryStatus()
    {
        app->switchWindow(gui::BellBatteryStatusWindow::name,
                          std::make_unique<gui::BellBatteryStatusWindow::Data>(getBatteryLvl(), isBatteryCharging()));
        app->switchWindow(gui::BellBatteryStatusWindow::windowName,
                          std::make_unique<gui::BatteryStatusSwitchData>(getBatteryLvl(), isBatteryCharging()));
    }

    void HomeScreenPresenter::switchToLowBatteryWarning()
    {
        app->switchWindow(
            gui::BellBatteryStatusWindow::name,
            std::make_unique<gui::BellBatteryStatusWindow::Data>(getBatteryLvl(), isBatteryCharging(), true));
        app->switchWindow(gui::BellBatteryStatusWindow::windowName,
                          std::make_unique<gui::BatteryStatusSwitchData>(getBatteryLvl(), isBatteryCharging(), true));
    }

    UTF8 HomeScreenPresenter::getGreeting()

M products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.cpp => products/BellHybrid/apps/application-bell-main/windows/BellHomeScreenWindow.cpp +0 -1
@@ 2,7 2,6 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "BellHomeScreenWindow.hpp"
#include "BellBatteryStatusWindow.hpp"

#include <application-bell-main/ApplicationBellMain.hpp>
#include <apps-common/actions/AlarmRingingData.hpp>

M products/BellHybrid/apps/application-bell-meditation-timer/MeditationTimer.cpp => products/BellHybrid/apps/application-bell-meditation-timer/MeditationTimer.cpp +18 -11
@@ 1,4 1,4 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "MeditationTimer.hpp"


@@ 23,6 23,7 @@
#include <common/models/AudioModel.hpp>
#include <common/windows/BellFinishedWindow.hpp>
#include <common/windows/SessionPausedWindow.hpp>
#include <common/windows/AppsBatteryStatusWindow.hpp>

namespace app
{


@@ 59,6 60,8 @@ namespace app
        chimeVolumeModel   = std::make_unique<meditation::models::ChimeVolume>(*audioModel);
        startDelayModel    = std::make_unique<meditation::models::StartDelay>(this);
        statisticsModel    = std::make_unique<meditation::models::Statistics>(this);
        batteryModel        = std::make_unique<app::BatteryModel>(this);
        lowBatteryInfoModel = std::make_unique<app::LowBatteryInfoModel>();

        createUserInterface();



@@ 67,11 70,10 @@ namespace app

    void MeditationTimer::createUserInterface()
    {
        windowsFactory.attach(
            meditation::MeditationMainWindow::defaultName, [this](ApplicationCommon *app, const std::string &name) {
                auto presenter = std::make_unique<app::meditation::MeditationTimerPresenter>(app, settings.get());
                return std::make_unique<meditation::MeditationMainWindow>(app);
            });
        windowsFactory.attach(meditation::MeditationMainWindow::defaultName,
                              [this](ApplicationCommon *app, const std::string &name) {
                                  return std::make_unique<meditation::MeditationMainWindow>(app);
                              });

        windowsFactory.attach(meditation::SettingsWindow::name,
                              [this](ApplicationCommon *app, const std::string &name) {


@@ 86,11 88,12 @@ namespace app
                return std::make_unique<meditation::StatisticsWindow>(app, std::move(presenter));
            });

        windowsFactory.attach(
            meditation::MeditationTimerWindow::name, [this](ApplicationCommon *app, const std::string &name) {
                auto presenter = std::make_unique<app::meditation::MeditationTimerPresenter>(app, settings.get());
                return std::make_unique<meditation::MeditationTimerWindow>(app, std::move(presenter));
            });
        windowsFactory.attach(meditation::MeditationTimerWindow::name,
                              [this](ApplicationCommon *app, const std::string &name) {
                                  auto presenter = std::make_unique<app::meditation::MeditationTimerPresenter>(
                                      app, settings.get(), *batteryModel, *lowBatteryInfoModel);
                                  return std::make_unique<meditation::MeditationTimerWindow>(app, std::move(presenter));
                              });

        windowsFactory.attach(
            meditation::windows::meditationCountdown, [this](ApplicationCommon *app, const std::string &name) {


@@ 112,6 115,10 @@ namespace app
                              [](ApplicationCommon *app, const std::string &name) {
                                  return std::make_unique<gui::BellFinishedWindow>(app, name);
                              });
        windowsFactory.attach(meditation::windows::meditationLowBattery,
                              [](ApplicationCommon *app, const std::string &name) {
                                  return std::make_unique<gui::AppsBatteryStatusWindow>(app, name);
                              });

        attachPopups({gui::popup::ID::AlarmActivated,
                      gui::popup::ID::AlarmDeactivated,

M products/BellHybrid/apps/application-bell-meditation-timer/data/MeditationCommon.hpp => products/BellHybrid/apps/application-bell-meditation-timer/data/MeditationCommon.hpp +4 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 11,8 11,9 @@ namespace app::meditation
{
    namespace windows
    {
        static constexpr auto meditationCountdown = "MeditationCountdown";
        static constexpr auto meditationProgress  = "MeditationProgress";
        inline constexpr auto meditationCountdown  = "MeditationCountdown";
        inline constexpr auto meditationProgress   = "MeditationProgress";
        inline constexpr auto meditationLowBattery = "MeditationLowBatteryWindow";
    }; // namespace windows

    constexpr auto meditationDBRecordName = "MeditationTimer";

M products/BellHybrid/apps/application-bell-meditation-timer/include/application-bell-meditation-timer/MeditationTimer.hpp => products/BellHybrid/apps/application-bell-meditation-timer/include/application-bell-meditation-timer/MeditationTimer.hpp +5 -1
@@ 1,10 1,12 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <Application.hpp>
#include <common/models/AbstractAudioModel.hpp>
#include <common/models/BatteryModel.hpp>
#include <common/models/LowBatteryInfoModel.hpp>

namespace app::meditation::models
{


@@ 47,6 49,8 @@ namespace app
        std::unique_ptr<app::meditation::models::StartDelay> startDelayModel;
        std::unique_ptr<AbstractAudioModel> audioModel;
        std::unique_ptr<app::meditation::models::Statistics> statisticsModel;
        std::unique_ptr<AbstractBatteryModel> batteryModel;
        std::unique_ptr<AbstractLowBatteryInfoModel> lowBatteryInfoModel;
    };

    template <>

M products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationTimerPresenter.cpp => products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationTimerPresenter.cpp +30 -4
@@ 1,25 1,37 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "MeditationCommon.hpp"
#include "MeditationTimerPresenter.hpp"

#include <common/LanguageUtils.hpp>
#include <common/data/BatteryStatusSwitchData.hpp>
#include <service-db/Settings.hpp>
#include <Units.hpp>

namespace
{
    using State                 = Store::Battery::State;
    constexpr auto spinnerMax   = 180U;
    constexpr auto spinnerMin   = 1U;
    constexpr auto spinnerStep  = 1U;
    constexpr auto emptyValue   = 0U;
    constexpr auto defaultValue = 15U;
    constexpr units::SOC lowBatteryThreshold{10};

    bool isBatteryCharging(const State state)
    {
        return state == State::Charging or state == State::ChargingDone;
    }
} // namespace

namespace app::meditation
{
    MeditationTimerPresenter::MeditationTimerPresenter(app::ApplicationCommon *app, settings::Settings *settings)
        : app{app}, settings{settings}
    MeditationTimerPresenter::MeditationTimerPresenter(app::ApplicationCommon *app,
                                                       settings::Settings *settings,
                                                       AbstractBatteryModel &batteryModel,
                                                       AbstractLowBatteryInfoModel &lowBatteryInfoModel)
        : app{app}, settings{settings}, batteryModel{batteryModel}, lowBatteryInfoModel{lowBatteryInfoModel}
    {}

    std::uint8_t MeditationTimerPresenter::getMinValue()


@@ 55,6 67,20 @@ namespace app::meditation
    void MeditationTimerPresenter::activate(std::uint32_t value)
    {
        settings->setValue(meditationDBRecordName, utils::to_string(value), settings::SettingsScope::AppLocal);
        app->switchWindow(windows::meditationCountdown);

        auto switchToNextScreen = [this]() { app->switchWindow(windows::meditationCountdown); };

        const auto batteryState = batteryModel.getLevelState();
        const units::SOC soc    = batteryState.level;
        const bool isCharging   = isBatteryCharging(batteryState.state);
        if (not lowBatteryInfoModel.isInfoHandled() && not isCharging && soc < lowBatteryThreshold) {
            auto lowBatterySwitchData =
                std::make_unique<gui::AppsBatteryStatusSwitchData>(soc, isCharging, switchToNextScreen);
            app->switchWindow(windows::meditationLowBattery, std::move(lowBatterySwitchData));
            lowBatteryInfoModel.handleInfo();
        }
        else {
            switchToNextScreen();
        }
    }
} // namespace app::meditation

M products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationTimerPresenter.hpp => products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationTimerPresenter.hpp +11 -4
@@ 1,10 1,12 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <apps-common/ApplicationCommon.hpp>
#include <apps-common/BasePresenter.hpp>
#include <common/models/BatteryModel.hpp>
#include <common/models/LowBatteryInfoModel.hpp>

namespace app
{


@@ 43,7 45,10 @@ namespace app::meditation
    class MeditationTimerPresenter : public MeditationTimerContract::Presenter
    {
      public:
        MeditationTimerPresenter(app::ApplicationCommon *app, settings::Settings *settings);
        MeditationTimerPresenter(app::ApplicationCommon *app,
                                 settings::Settings *settings,
                                 AbstractBatteryModel &batteryModel,
                                 AbstractLowBatteryInfoModel &lowBatteryInfoModel);

        std::uint8_t getMinValue() override;
        std::uint8_t getMaxValue() override;


@@ 53,7 58,9 @@ namespace app::meditation
        void activate(std::uint32_t value) override;

      private:
        app::ApplicationCommon *app  = nullptr;
        settings::Settings *settings = nullptr;
        app::ApplicationCommon *app{nullptr};
        settings::Settings *settings{nullptr};
        AbstractBatteryModel &batteryModel;
        AbstractLowBatteryInfoModel &lowBatteryInfoModel;
    };
} // namespace app::meditation

M products/BellHybrid/apps/application-bell-relaxation/ApplicationBellRelaxation.cpp => products/BellHybrid/apps/application-bell-relaxation/ApplicationBellRelaxation.cpp +10 -10
@@ 1,4 1,4 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ApplicationBellRelaxation.hpp"


@@ 9,7 9,6 @@
#include "presenter/RelaxationVolumePresenter.hpp"
#include "presenter/RelaxationPausedPresenter.hpp"
#include "presenter/RelaxationEndedPresenter.hpp"
#include "presenter/RelaxationLowBatteryPresenter.hpp"
#include "presenter/RelaxationErrorPresenter.hpp"
#include "windows/RelaxationMainWindow.hpp"
#include "windows/RelaxationPausedWindow.hpp"


@@ 18,7 17,6 @@
#include "windows/RelaxationTimerSelectWindow.hpp"
#include "windows/RelaxationVolumeWindow.hpp"
#include "windows/RelaxationEndedWindow.hpp"
#include "windows/RelaxationLowBatteryWindow.hpp"
#include "windows/RelaxationErrorWindow.hpp"
#include "widgets/RelaxationPlayer.hpp"
#include <Paths.hpp>


@@ 27,6 25,7 @@
#include <common/models/TimeModel.hpp>
#include <common/models/BatteryModel.hpp>
#include <common/models/AudioModel.hpp>
#include <common/windows/AppsBatteryStatusWindow.hpp>
#include <audio/AudioMessage.hpp>
#include <service-db/DBNotificationMessage.hpp>



@@ 61,6 60,7 @@ namespace app
        }

        batteryModel                 = std::make_unique<app::BatteryModel>(this);
        lowBatteryInfoModel          = std::make_unique<app::LowBatteryInfoModel>();
        player                       = std::make_unique<relaxation::RelaxationPlayer>(*audioModel);
        relaxationRebuildTimerHandle = sys::TimerFactory::createSingleShotTimer(
            this, relaxationRebuildTimer, relaxationRebuildTimerInterval, [this](sys::Timer &) {


@@ 88,11 88,12 @@ namespace app
            auto presenter  = std::make_unique<relaxation::RelaxationMainWindowPresenter>(std::move(songsModel));
            return std::make_unique<gui::RelaxationMainWindow>(app, std::move(presenter));
        });
        windowsFactory.attach(
            gui::window::name::relaxationTimerSelect, [this](ApplicationCommon *app, const std::string &name) {
                auto presenter = std::make_unique<relaxation::RelaxationTimerSelectPresenter>(settings.get());
                return std::make_unique<gui::RelaxationTimerSelectWindow>(app, std::move(presenter));
            });
        windowsFactory.attach(gui::window::name::relaxationTimerSelect,
                              [this](ApplicationCommon *app, const std::string &name) {
                                  auto presenter = std::make_unique<relaxation::RelaxationTimerSelectPresenter>(
                                      settings.get(), *batteryModel, *lowBatteryInfoModel);
                                  return std::make_unique<gui::RelaxationTimerSelectWindow>(app, std::move(presenter));
                              });

        windowsFactory.attach(
            gui::window::name::relaxationRunningProgress, [this](ApplicationCommon *app, const std::string &name) {


@@ 130,8 131,7 @@ namespace app

        windowsFactory.attach(gui::window::name::relaxationLowBattery,
                              [](ApplicationCommon *app, const std::string &name) {
                                  auto presenter = std::make_unique<relaxation::RelaxationLowBatteryPresenter>(app);
                                  return std::make_unique<gui::RelaxationLowBatteryWindow>(app, std::move(presenter));
                                  return std::make_unique<gui::AppsBatteryStatusWindow>(app, name);
                              });

        windowsFactory.attach(gui::window::name::relaxationError, [](ApplicationCommon *app, const std::string &name) {

M products/BellHybrid/apps/application-bell-relaxation/CMakeLists.txt => products/BellHybrid/apps/application-bell-relaxation/CMakeLists.txt +0 -4
@@ 20,7 20,6 @@ target_sources(application-bell-relaxation
        presenter/RelaxationVolumePresenter.cpp
        presenter/RelaxationPausedPresenter.cpp
        presenter/RelaxationEndedPresenter.cpp
        presenter/RelaxationLowBatteryPresenter.cpp
        presenter/RelaxationErrorPresenter.cpp
        widgets/RelaxationPlayer.cpp
        widgets/RelaxationListView.cpp


@@ 33,7 32,6 @@ target_sources(application-bell-relaxation
        windows/RelaxationTimerSelectWindow.cpp
        windows/RelaxationVolumeWindow.cpp
        windows/RelaxationEndedWindow.cpp
        windows/RelaxationLowBatteryWindow.cpp
        windows/RelaxationErrorWindow.cpp

        data/RelaxationCommon.hpp


@@ 53,7 51,6 @@ target_sources(application-bell-relaxation
        presenter/RelaxationVolumePresenter.hpp
        presenter/RelaxationPausedPresenter.hpp
        presenter/RelaxationEndedPresenter.hpp
        presenter/RelaxationLowBatteryPresenter.hpp
        presenter/RelaxationErrorPresenter.cpp
        windows/RelaxationMainWindow.hpp
        windows/RelaxationPausedWindow.hpp


@@ 62,7 59,6 @@ target_sources(application-bell-relaxation
        windows/RelaxationTimerSelectWindow.hpp
        windows/RelaxationVolumeWindow.hpp
        windows/RelaxationEndedWindow.hpp
        windows/RelaxationLowBatteryWindow.hpp
        windows/RelaxationErrorWindow.hpp
        model/RelaxationSongsModel.hpp
        model/RelaxationSongsModel.cpp

M products/BellHybrid/apps/application-bell-relaxation/data/RelaxationSwitchData.hpp => products/BellHybrid/apps/application-bell-relaxation/data/RelaxationSwitchData.hpp +1 -19
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 16,22 16,4 @@ namespace gui
            ignoreCurrentWindowOnStack = true;
        }
    };

    class RelaxationLowBatterySwitchData : public SwitchData
    {
      public:
        explicit RelaxationLowBatterySwitchData(const units::SOC soc) : batteryLevel{soc}
        {
            ignoreCurrentWindowOnStack = true;
        }

        [[nodiscard]] auto getBatteryLevel() const noexcept -> units::SOC
        {
            return batteryLevel;
        }

      private:
        const units::SOC batteryLevel;
    };

} // namespace gui

M products/BellHybrid/apps/application-bell-relaxation/include/application-bell-relaxation/ApplicationBellRelaxation.hpp => products/BellHybrid/apps/application-bell-relaxation/include/application-bell-relaxation/ApplicationBellRelaxation.hpp +3 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 6,6 6,7 @@
#include <Application.hpp>
#include <common/models/AbstractAudioModel.hpp>
#include <common/models/BatteryModel.hpp>
#include <common/models/LowBatteryInfoModel.hpp>
#include <purefs/filesystem_paths.hpp>

namespace gui::window::name


@@ 32,6 33,7 @@ namespace app
      private:
        std::unique_ptr<AbstractAudioModel> audioModel;
        std::unique_ptr<AbstractBatteryModel> batteryModel;
        std::unique_ptr<AbstractLowBatteryInfoModel> lowBatteryInfoModel;
        std::unique_ptr<relaxation::RelaxationPlayer> player;
        sys::TimerHandle relaxationRebuildTimerHandle{};


D products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationLowBatteryPresenter.cpp => products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationLowBatteryPresenter.cpp +0 -20
@@ 1,20 0,0 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "presenter/RelaxationLowBatteryPresenter.hpp"

#include <Application.hpp>
#include <service-appmgr/Controller.hpp>
#include <application-bell-main/ApplicationBellMain.hpp>

namespace app::relaxation
{
    RelaxationLowBatteryPresenter::RelaxationLowBatteryPresenter(app::ApplicationCommon *app) : app{app}
    {}

    void RelaxationLowBatteryPresenter::activate()
    {
        app::manager::Controller::sendAction(
            app, app::manager::actions::Launch, std::make_unique<app::ApplicationLaunchData>(app::applicationBellName));
    }
} // namespace app::relaxation

D products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationLowBatteryPresenter.hpp => products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationLowBatteryPresenter.hpp +0 -38
@@ 1,38 0,0 @@
// 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 <apps-common/BasePresenter.hpp>

namespace app
{
    class ApplicationCommon;
}

namespace app::relaxation
{
    class RelaxationLowBatteryContract
    {
      public:
        class View
        {
          public:
            virtual ~View() = default;
        };
        class Presenter : public BasePresenter<RelaxationLowBatteryContract::View>
        {
          public:
            virtual void activate() = 0;
        };
    };

    class RelaxationLowBatteryPresenter : public RelaxationLowBatteryContract::Presenter
    {
        app::ApplicationCommon *app{};
        void activate() override;

      public:
        explicit RelaxationLowBatteryPresenter(app::ApplicationCommon *app);
    };
} // namespace app::relaxation

M products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationRunningLoopPresenter.cpp => products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationRunningLoopPresenter.cpp +2 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "RelaxationRunningLoopPresenter.hpp"


@@ 120,7 120,7 @@ namespace app::relaxation
        return timer->isStopped();
    }

    Store::Battery RelaxationRunningLoopPresenter::handleBatteryStatus()
    Store::Battery RelaxationRunningLoopPresenter::getBatteryState()
    {
        return batteryModel.getLevelState();
    }

M products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationRunningLoopPresenter.hpp => products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationRunningLoopPresenter.hpp +3 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 56,7 56,7 @@ namespace app::relaxation
            virtual void handleUpdateTimeEvent()                                           = 0;
            virtual bool isPaused()                                                        = 0;
            virtual void onBeforeShow()                                                    = 0;
            virtual Store::Battery handleBatteryStatus()                                   = 0;
            virtual Store::Battery getBatteryState()                                       = 0;
        };
    };



@@ 79,7 79,7 @@ namespace app::relaxation
        void handleUpdateTimeEvent() override;
        bool isPaused() override;
        void onBeforeShow() override;
        Store::Battery handleBatteryStatus() override;
        Store::Battery getBatteryState() override;

        void onFinished();


M products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationTimerSelectPresenter.cpp => products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationTimerSelectPresenter.cpp +21 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "RelaxationTimerSelectPresenter.hpp"


@@ 17,7 17,10 @@ namespace

namespace app::relaxation
{
    RelaxationTimerSelectPresenter::RelaxationTimerSelectPresenter(settings::Settings *settings) : settings{settings}
    RelaxationTimerSelectPresenter::RelaxationTimerSelectPresenter(settings::Settings *settings,
                                                                   AbstractBatteryModel &batteryModel,
                                                                   AbstractLowBatteryInfoModel &lowBatteryInfoModel)
        : settings{settings}, batteryModel{batteryModel}, lowBatteryInfoModel{lowBatteryInfoModel}
    {}

    const RelaxationTimerSelectContract::Range &RelaxationTimerSelectPresenter::getTimerValuesRange() const noexcept


@@ 38,4 41,20 @@ namespace app::relaxation
    {
        settings->setValue(timerValueDBRecordName, utils::to_string(value.count()), settings::SettingsScope::AppLocal);
    }

    Store::Battery RelaxationTimerSelectPresenter::getBatteryState()
    {
        return batteryModel.getLevelState();
    }

    bool RelaxationTimerSelectPresenter::isLowBatteryWindowHandled() const
    {
        return lowBatteryInfoModel.isInfoHandled();
    }

    void RelaxationTimerSelectPresenter::handleLowBatteryWindow()
    {
        lowBatteryInfoModel.handleInfo();
    }

} // namespace app::relaxation

M products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationTimerSelectPresenter.hpp => products/BellHybrid/apps/application-bell-relaxation/presenter/RelaxationTimerSelectPresenter.hpp +15 -3
@@ 1,9 1,11 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <apps-common/BasePresenter.hpp>
#include <common/models/BatteryModel.hpp>
#include <common/models/LowBatteryInfoModel.hpp>
#include <chrono>
#include <vector>



@@ 40,18 42,28 @@ namespace app::relaxation
            virtual const Range &getTimerValuesRange() const noexcept = 0;
            virtual std::chrono::minutes getCurrentTimerValue() const = 0;
            virtual void setTimerValue(std::chrono::minutes)          = 0;
            virtual Store::Battery getBatteryState()                     = 0;
            [[nodiscard]] virtual bool isLowBatteryWindowHandled() const = 0;
            virtual void handleLowBatteryWindow()                        = 0;
        };
    };

    class RelaxationTimerSelectPresenter : public RelaxationTimerSelectContract::Presenter
    {
        settings::Settings *settings = nullptr;
        settings::Settings *settings{nullptr};
        AbstractBatteryModel &batteryModel;
        AbstractLowBatteryInfoModel &lowBatteryInfoModel;

        const RelaxationTimerSelectContract::Range &getTimerValuesRange() const noexcept override;
        std::chrono::minutes getCurrentTimerValue() const override;
        void setTimerValue(std::chrono::minutes) override;
        Store::Battery getBatteryState() override;
        [[nodiscard]] bool isLowBatteryWindowHandled() const override;
        void handleLowBatteryWindow() override;

      public:
        explicit RelaxationTimerSelectPresenter(settings::Settings *settings);
        RelaxationTimerSelectPresenter(settings::Settings *settings,
                                       AbstractBatteryModel &batteryModel,
                                       AbstractLowBatteryInfoModel &lowBatteryInfoModel);
    };
} // namespace app::relaxation

D products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationLowBatteryWindow.cpp => products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationLowBatteryWindow.cpp +0 -77
@@ 1,77 0,0 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "RelaxationLowBatteryWindow.hpp"
#include <data/RelaxationSwitchData.hpp>
#include <data/RelaxationStyle.hpp>
#include <ApplicationBellRelaxation.hpp>

#include <apps-common/widgets/BellBaseLayout.hpp>

namespace
{
    gui::TextFixedSize *createBatteryLevelText(gui::VBox *parent)
    {
        auto text = new gui::TextFixedSize(parent);
        text->setFont(gui::relaxationStyle::descriptionFont);
        text->setMinimumWidth(gui::relaxationStyle::text::minWidth);
        text->setMinimumHeightToFitText(gui::relaxationStyle::text::maxLines);
        text->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
        text->drawUnderline(false);
        return text;
    }
} // namespace

namespace gui
{
    RelaxationLowBatteryWindow::RelaxationLowBatteryWindow(
        app::ApplicationCommon *app,
        std::unique_ptr<app::relaxation::RelaxationLowBatteryContract::Presenter> &&presenter)
        : WindowWithTimer(app, window::name::relaxationLowBattery), presenter{std::move(presenter)}
    {
        buildInterface();
    }

    void RelaxationLowBatteryWindow::buildInterface()
    {
        AppWindow::buildInterface();
        buildLayout();
        registerCallbacks();
    }

    void RelaxationLowBatteryWindow::buildLayout()
    {
        statusBar->setVisible(false);
        auto body = new BellBaseLayout(this, 0, 0, style::bell_base_layout::w, style::bell_base_layout::h, false);
        new gui::Image(body->centerBox, "bell_status_battery_lvl0_W_G");
        batteryText = createBatteryLevelText(body->lastBox);
        body->lastBox->resizeItems();
        body->resizeItems();
    }

    bool RelaxationLowBatteryWindow::handleSwitchData(SwitchData *data)
    {
        if (data == nullptr) {
            LOG_ERROR("Received nullptr");
            return false;
        }

        const auto batteryData = dynamic_cast<RelaxationLowBatterySwitchData *>(data);
        if (batteryData == nullptr) {
            LOG_ERROR("Received data nullptr");
            return false;
        }

        const auto soc = batteryData->getBatteryLevel();
        batteryText->setText(std::to_string(soc) + "%");
        return true;
    }

    void RelaxationLowBatteryWindow::registerCallbacks()
    {
        timerCallback = [this](Item &, sys::Timer &timer) {
            presenter->activate();
            return true;
        };
    }
} // namespace gui

D products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationLowBatteryWindow.hpp => products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationLowBatteryWindow.hpp +0 -30
@@ 1,30 0,0 @@
// 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 "presenter/RelaxationLowBatteryPresenter.hpp"

#include <apps-common/popups/WindowWithTimer.hpp>

namespace gui
{
    class RelaxationLowBatteryWindow : public WindowWithTimer,
                                       public app::relaxation::RelaxationLowBatteryContract::View
    {
      public:
        explicit RelaxationLowBatteryWindow(
            app::ApplicationCommon *app,
            std::unique_ptr<app::relaxation::RelaxationLowBatteryContract::Presenter> &&presenter);

      private:
        std::unique_ptr<app::relaxation::RelaxationLowBatteryContract::Presenter> presenter;
        gui::TextFixedSize *batteryText = nullptr;

        void buildInterface() override;
        bool handleSwitchData(SwitchData *data) override;

        void buildLayout();
        void registerCallbacks();
    };
} // namespace gui

M products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationRunningLoopWindow.cpp => products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationRunningLoopWindow.cpp +5 -19
@@ 1,4 1,4 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "RelaxationRunningLoopWindow.hpp"


@@ 13,18 13,17 @@

namespace
{
    using State = Store::Battery::State;
    constexpr auto relaxationLoopTimerName{"RelaxationLoopTimer"};
    constexpr std::chrono::seconds relaxationLoopTimerPeriod{1};
    constexpr units::SOC dischargingLevelShowTop{20};
    constexpr units::SOC dischargingLowBattery{10};
    constexpr auto ellipsisSpace{2U};
    constexpr auto ellipsis{"..."};
    /* charsMultiplier is set a little bit less than max lines which is 2, because of final text formatting */
    constexpr auto charsMultiplier{1.8f};

    bool isBatteryCharging(const Store::Battery::State state)
    bool isBatteryCharging(const State state)
    {
        using State = Store::Battery::State;
        return state == State::Charging or state == State::ChargingDone;
    }



@@ 111,15 110,12 @@ namespace gui
        }

        if (data && typeid(*data) == typeid(RelaxationSwitchData)) {
            const auto batteryStatus  = presenter->handleBatteryStatus();
            auto *audioSwitchData     = static_cast<RelaxationSwitchData *>(data);
            audioContext              = audioSwitchData->getAudioContext();
            const auto maxCharsInLine = title->getTextFormat().getFont()->getCharCountInSpace(
                audioContext->getSound().tags.title, title->getWidth());
            title->setText(adjustDisplayedTitle(audioContext->getSound().tags.title, maxCharsInLine));
            if (batteryStatus.level > dischargingLowBattery) {
                presenter->activate(audioContext->getSound());
            }
            presenter->activate(audioContext->getSound());
        }
    }



@@ 215,13 211,11 @@ namespace gui

    bool RelaxationRunningLoopWindow::updateBatteryStatus()
    {
        auto batteryStatus = presenter->handleBatteryStatus();
        auto batteryStatus = presenter->getBatteryState();

        units::SOC soc = batteryStatus.level;
        auto state     = batteryStatus.state;

        checkLowBatteryLevel(soc);

        if (soc < dischargingLevelShowTop) {
            battery->update(soc, isBatteryCharging(state));
            bottomText->setVisible(false);


@@ 237,14 231,6 @@ namespace gui
        return true;
    }

    void RelaxationRunningLoopWindow::checkLowBatteryLevel(units::SOC soc)
    {
        if (soc <= dischargingLowBattery) {
            presenter->stop();
            application->switchWindow(gui::window::name::relaxationLowBattery,
                                      std::make_unique<gui::RelaxationLowBatterySwitchData>(soc));
        }
    }
    void RelaxationRunningLoopWindow::handleError()
    {
        auto switchData = std::make_unique<RelaxationErrorData>(RelaxationErrorType::UnsupportedMediaType);

M products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationRunningLoopWindow.hpp => products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationRunningLoopWindow.hpp +1 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 45,6 45,5 @@ namespace gui

        void buildLayout();
        void configureTimer();
        void checkLowBatteryLevel(units::SOC soc);
    };
} // namespace gui

M products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationTimerSelectWindow.cpp => products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationTimerSelectWindow.cpp +28 -6
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "RelaxationTimerSelectWindow.hpp"


@@ 6,16 6,20 @@
#include <ApplicationBellRelaxation.hpp>

#include <apps-common/widgets/BellBaseLayout.hpp>
#include <common/data/BatteryStatusSwitchData.hpp>
#include <common/LanguageUtils.hpp>
#include <i18n/i18n.hpp>
#include <Utils.hpp>
#include <Units.hpp>

namespace
{
    using State   = Store::Battery::State;
    using minutes = std::chrono::minutes;
    using namespace std::chrono_literals;
    constexpr minutes onceValue{minutes::zero()};
    constexpr minutes loopValue{8760h};
    constexpr units::SOC lowBatteryThreshold{10};

    const std::string getOnceValueText()
    {


@@ 58,6 62,11 @@ namespace
        }
        return range;
    }

    bool isBatteryCharging(const State state)
    {
        return state == State::Charging or state == State::ChargingDone;
    }
} // namespace
namespace gui
{


@@ 183,13 192,26 @@ namespace gui
            auto currentValue = UTF8ToTimerValue(spinner->value());
            presenter->setTimerValue(currentValue);

            auto audioSwitchData = std::make_unique<RelaxationSwitchData>(std::move(audioContext));
            audioSwitchData->ignoreCurrentWindowOnStack = true;
            if (currentValue == loopValue) {
                application->switchWindow(gui::window::name::relaxationRunningLoop, std::move(audioSwitchData));
            auto switchToNextScreen = [this, currentValue]() {
                auto switchWindowName = (currentValue == loopValue) ? gui::window::name::relaxationRunningLoop
                                                                    : gui::window::name::relaxationRunningProgress;
                auto audioSwitchData  = std::make_unique<RelaxationSwitchData>(std::move(audioContext));
                audioSwitchData->ignoreCurrentWindowOnStack = true;
                application->switchWindow(std::move(switchWindowName), std::move(audioSwitchData));
            };

            const auto batteryState = presenter->getBatteryState();
            const units::SOC soc    = batteryState.level;
            const bool isCharging   = isBatteryCharging(batteryState.state);
            if (not presenter->isLowBatteryWindowHandled() && not isCharging && soc < lowBatteryThreshold) {
                auto lowBatterySwitchData =
                    std::make_unique<AppsBatteryStatusSwitchData>(soc, isCharging, switchToNextScreen);
                lowBatterySwitchData->ignoreCurrentWindowOnStack = true;
                application->switchWindow(gui::window::name::relaxationLowBattery, std::move(lowBatterySwitchData));
                presenter->handleLowBatteryWindow();
            }
            else {
                application->switchWindow(gui::window::name::relaxationRunningProgress, std::move(audioSwitchData));
                switchToNextScreen();
            }

            return true;

M products/BellHybrid/apps/common/CMakeLists.txt => products/BellHybrid/apps/common/CMakeLists.txt +7 -0
@@ 30,11 30,14 @@ target_sources(application-bell-common
        src/windows/BellWelcomeWindow.cpp
        src/windows/SessionPausedWindow.cpp
        src/windows/ShortcutsWindow.cpp
        src/windows/BellBatteryStatusWindow.cpp
        src/windows/AppsBatteryStatusWindow.cpp
        src/BellSideListItemWithCallbacks.cpp
        src/TimeUtils.cpp
        src/TimeUtils.cpp
        src/models/SettingsModel.cpp
        src/models/BedtimeModel.cpp
        src/models/LowBatteryInfoModel.cpp
        src/popups/AlarmActivatedWindow.cpp
        src/popups/AlarmActivatedWindow.cpp
        src/popups/BedtimeNotificationWindow.cpp


@@ 86,9 89,12 @@ target_sources(application-bell-common
        include/common/windows/SessionPausedWindow.hpp
        include/common/windows/ShortcutsWindowContract.hpp
        include/common/windows/ShortcutsWindow.hpp
        include/common/windows/BellBatteryStatusWindow.hpp
        include/common/windows/AppsBatteryStatusWindow.hpp
        include/common/TimeUtils.hpp
        include/common/data/BatteryUtils.hpp
        include/common/data/FrontlightUtils.hpp
        include/common/data/BatteryStatusSwitchData.hpp
        include/common/models/AbstractAlarmModel.hpp
        include/common/models/AbstractBedtimeModel.hpp
        include/common/models/AbstractSettingsModel.hpp


@@ 105,6 111,7 @@ target_sources(application-bell-common
        include/common/models/AlarmSettingsModel.hpp
        include/common/models/AbstractAlarmSettingsModel.hpp
        include/common/models/LayoutModel.hpp
        include/common/models/LowBatteryInfoModel.hpp
        include/common/popups/presenter/AlarmActivatedPresenter.hpp
        include/common/popups/AlarmActivatedWindow.hpp
        include/common/popups/AlarmDeactivatedWindow.hpp

A products/BellHybrid/apps/common/include/common/data/BatteryStatusSwitchData.hpp => products/BellHybrid/apps/common/include/common/data/BatteryStatusSwitchData.hpp +56 -0
@@ 0,0 1,56 @@
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <SwitchData.hpp>
#include <Units.hpp>
#include <functional>

namespace gui
{
    class BatteryStatusSwitchData : public SwitchData
    {
      public:
        BatteryStatusSwitchData(const units::SOC soc, bool chargeState, bool lowBatteryWarning = false)
            : batteryLevel{soc}, chargeState{chargeState}, lowBatteryWarning{lowBatteryWarning}
        {}

        [[nodiscard]] auto getBatteryLevel() const noexcept -> units::SOC
        {
            return batteryLevel;
        }

        [[nodiscard]] auto isCharging() const noexcept -> bool
        {
            return chargeState;
        }

        [[nodiscard]] auto isLowBatteryWarning() const noexcept -> bool
        {
            return lowBatteryWarning;
        }

      private:
        const units::SOC batteryLevel;
        const bool chargeState;
        const bool lowBatteryWarning;
    };

    class AppsBatteryStatusSwitchData : public BatteryStatusSwitchData
    {
      public:
        AppsBatteryStatusSwitchData(const units::SOC soc, bool chargeState, std::function<void()> returnCallback)
            : BatteryStatusSwitchData{soc, chargeState, true}, returnCallback{returnCallback}
        {}

        [[nodiscard]] auto getReturnCallback() const noexcept -> std::function<void()>
        {
            return returnCallback;
        }

      private:
        std::function<void()> returnCallback;
    };

} // namespace gui

A products/BellHybrid/apps/common/include/common/models/LowBatteryInfoModel.hpp => products/BellHybrid/apps/common/include/common/models/LowBatteryInfoModel.hpp +26 -0
@@ 0,0 1,26 @@
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

namespace app
{
    class AbstractLowBatteryInfoModel
    {
      public:
        virtual ~AbstractLowBatteryInfoModel() noexcept = default;

        [[nodiscard]] virtual bool isInfoHandled() const = 0;
        virtual void handleInfo()                        = 0;
    };

    class LowBatteryInfoModel : public AbstractLowBatteryInfoModel
    {
      public:
        [[nodiscard]] bool isInfoHandled() const override;
        void handleInfo() override;

      private:
        bool lowBatteryInfoHandled{false};
    };
} // namespace app

A products/BellHybrid/apps/common/include/common/windows/AppsBatteryStatusWindow.hpp => products/BellHybrid/apps/common/include/common/windows/AppsBatteryStatusWindow.hpp +22 -0
@@ 0,0 1,22 @@
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "BellBatteryStatusWindow.hpp"

namespace gui
{
    class AppsBatteryStatusWindow : public BellBatteryStatusWindow
    {
      public:
        AppsBatteryStatusWindow(app::ApplicationCommon *app, const std::string &name);

      private:
        bool onInput(const InputEvent &inputEvent) override;
        bool handleSwitchData(SwitchData *data) override;

        std::function<void()> returnCallback;
    };

} // namespace gui

R products/BellHybrid/apps/application-bell-main/windows/BellBatteryStatusWindow.hpp => products/BellHybrid/apps/common/include/common/windows/BellBatteryStatusWindow.hpp +3 -16
@@ 15,24 15,11 @@ namespace gui
    class BellBatteryStatusWindow : public WindowWithTimer
    {
      public:
        struct Data : public gui::SwitchData
        {
            Data(std::uint32_t lvl, bool chargeState, bool lowBatteryWaring = false)
                : chargeLevel{lvl}, isCharging{chargeState}, isLowBatteryWarning{lowBatteryWaring}
            {}
            const std::uint32_t chargeLevel;
            const bool isCharging;
            const bool isLowBatteryWarning;
        };
        static constexpr auto name = "BellBatteryStatusWindow";
        explicit BellBatteryStatusWindow(app::ApplicationCommon *app);
        static constexpr auto windowName = "BellBatteryStatusWindow";

      private:
        static constexpr auto top_description_font          = style::window::font::largelight;
        static constexpr auto bottom_description_font       = style::window::font::verybiglight;
        static constexpr auto bottom_description_max_size_w = style::bell_base_layout::outer_layouts_w;
        static constexpr auto bottom_description_max_size_h = 85U;
        BellBatteryStatusWindow(app::ApplicationCommon *app, const std::string &name = windowName);

      private:
        void buildInterface() override;
        bool onInput(const InputEvent &inputEvent) override;
        void onBeforeShow(ShowMode mode, SwitchData *data) override;

A products/BellHybrid/apps/common/src/models/LowBatteryInfoModel.cpp => products/BellHybrid/apps/common/src/models/LowBatteryInfoModel.cpp +18 -0
@@ 0,0 1,18 @@
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "models/LowBatteryInfoModel.hpp"

namespace app
{
    bool LowBatteryInfoModel::isInfoHandled() const
    {
        return lowBatteryInfoHandled;
    }

    void LowBatteryInfoModel::handleInfo()
    {
        lowBatteryInfoHandled = true;
    }

} // namespace app

A products/BellHybrid/apps/common/src/windows/AppsBatteryStatusWindow.cpp => products/BellHybrid/apps/common/src/windows/AppsBatteryStatusWindow.cpp +55 -0
@@ 0,0 1,55 @@
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <windows/AppsBatteryStatusWindow.hpp>
#include <data/BatteryStatusSwitchData.hpp>

namespace
{
    using namespace std::chrono_literals;
    constexpr auto windowTimeout{5s};
} // namespace

namespace gui
{
    AppsBatteryStatusWindow::AppsBatteryStatusWindow(app::ApplicationCommon *app, const std::string &name)
        : BellBatteryStatusWindow{app, name}
    {}

    bool AppsBatteryStatusWindow::onInput(const InputEvent &inputEvent)
    {
        if (inputEvent.isShortRelease(KeyCode::KEY_ENTER) || inputEvent.isShortRelease(KeyCode::KEY_RF)) {
            if (returnCallback != nullptr) {
                detachTimerIfExists();
                returnCallback();
                return true;
            }
        }
        return false;
    }

    bool AppsBatteryStatusWindow::handleSwitchData(SwitchData *data)
    {
        if (data == nullptr) {
            LOG_ERROR("Received nullptr");
            return false;
        }

        const auto batteryData = dynamic_cast<AppsBatteryStatusSwitchData *>(data);
        if (batteryData == nullptr) {
            LOG_ERROR("Received data nullptr");
            return false;
        }

        returnCallback = batteryData->getReturnCallback();
        if (returnCallback != nullptr) {
            timerCallback = [this]([[maybe_unused]] Item &item, [[maybe_unused]] sys::Timer &timer) {
                returnCallback();
                return true;
            };
            resetTimer(windowTimeout);
        }

        return true;
    }
} // namespace gui

R products/BellHybrid/apps/application-bell-main/windows/BellBatteryStatusWindow.cpp => products/BellHybrid/apps/common/src/windows/BellBatteryStatusWindow.cpp +22 -10
@@ 1,8 1,8 @@
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "BellBatteryStatusWindow.hpp"

#include "windows/BellBatteryStatusWindow.hpp"
#include <data/BatteryStatusSwitchData.hpp>
#include <common/data/BatteryUtils.hpp>
#include <gui/widgets/text/TextFixedSize.hpp>
#include <gui/widgets/ImageBox.hpp>


@@ 15,7 15,11 @@ namespace
{
    using namespace std::chrono_literals;

    constexpr auto imageType = gui::ImageTypeSpecifier::W_G;
    constexpr auto top_description_font          = style::window::font::largelight;
    constexpr auto bottom_description_font       = style::window::font::verybiglight;
    constexpr auto bottom_description_max_size_w = style::bell_base_layout::outer_layouts_w;
    constexpr auto bottom_description_max_size_h = 85U;
    constexpr auto imageType                     = gui::ImageTypeSpecifier::W_G;
    constexpr auto batteryEntries =
        std::array<battery_utils::BatteryLevelEntry, 6>{{{{0, 9}, "bell_status_battery_lvl0"},
                                                         {{10, 19}, "bell_status_battery_lvl1"},


@@ 31,7 35,7 @@ namespace

namespace gui
{
    BellBatteryStatusWindow::BellBatteryStatusWindow(app::ApplicationCommon *app)
    BellBatteryStatusWindow::BellBatteryStatusWindow(app::ApplicationCommon *app, const std::string &name)
        : WindowWithTimer{app, name, windowLongTimeout}
    {
        buildInterface();


@@ 89,6 93,7 @@ namespace gui
    bool BellBatteryStatusWindow::onInput(const InputEvent &inputEvent)
    {
        if (inputEvent.isShortRelease(KeyCode::KEY_ENTER) || inputEvent.isShortRelease(KeyCode::KEY_RF)) {
            detachTimerIfExists();
            application->returnToPreviousWindow();
            return true;
        }


@@ 110,18 115,25 @@ namespace gui
    void BellBatteryStatusWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        if (data != nullptr) {
            const auto &switchData = static_cast<Data &>(*data);
            const auto image       = battery_utils::getBatteryLevelImage(batteryEntries, switchData.chargeLevel);
            if (switchData.isLowBatteryWarning) {
            const auto batteryData = dynamic_cast<BatteryStatusSwitchData *>(data);
            if (batteryData == nullptr) {
                LOG_ERROR("Received data nullptr");
                return;
            }
            const auto soc                 = batteryData->getBatteryLevel();
            const bool isCharging          = batteryData->isCharging();
            const bool isLowBatteryWarning = batteryData->isLowBatteryWarning();
            const auto image               = battery_utils::getBatteryLevelImage(batteryEntries, soc);
            if (isLowBatteryWarning) {
                topDescription->setText(utils::translate("battery_low"));
                auto tokenMap = text::RichTextParser::TokenMap({{"$BATTERY", std::to_string(switchData.chargeLevel)}});
                auto tokenMap = text::RichTextParser::TokenMap({{"$BATTERY", std::to_string(soc)}});
                bottomDescription->setRichText(utils::translate("battery_remaining"), std::move(tokenMap));
                chargingIcon->setVisible(false);
            }
            else {
                topDescription->setText(utils::translate("app_settings_tech_info_battery"));
                bottomDescription->setText(std::to_string(switchData.chargeLevel) + "%");
                chargingIcon->setVisible(switchData.isCharging);
                bottomDescription->setText(std::to_string(soc) + "%");
                chargingIcon->setVisible(isCharging);
            }
            if (image) {
                center->setImage(image->data(), imageType);