M products/BellHybrid/apps/Application.cpp => products/BellHybrid/apps/Application.cpp +2 -4
@@ 61,16 61,14 @@ namespace app
case ID::AlarmActivated:
windowsFactory.attach(
window::alarm_activated_window, [this](app::ApplicationCommon *app, const std::string &name) {
- auto presenter =
- std::make_unique<app::popup::AlarmActivatedPresenter>(*alarmModel, *batteryModel);
+ auto presenter = std::make_unique<app::popup::AlarmActivatedPresenter>(*alarmModel);
return std::make_unique<gui::AlarmActivatedWindow>(app, std::move(presenter));
});
break;
case ID::AlarmDeactivated:
windowsFactory.attach(
window::alarm_deactivated_window, [this](app::ApplicationCommon *app, const std::string &name) {
- auto presenter =
- std::make_unique<app::popup::AlarmActivatedPresenter>(*alarmModel, *batteryModel);
+ auto presenter = std::make_unique<app::popup::AlarmActivatedPresenter>(*alarmModel);
return std::make_unique<gui::AlarmDeactivatedWindow>(app, std::move(presenter));
});
break;
M products/BellHybrid/apps/application-bell-powernap/ApplicationBellPowerNap.cpp => products/BellHybrid/apps/application-bell-powernap/ApplicationBellPowerNap.cpp +14 -6
@@ 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 "ApplicationBellPowerNap.hpp"
@@ 6,6 6,7 @@
#include "windows/PowerNapMainWindow.hpp"
#include "windows/PowerNapProgressWindow.hpp"
#include "windows/PowerNapSessionEndedWindow.hpp"
+#include "windows/PowerNapWarningWindow.hpp"
#include <common/models/TimeModel.hpp>
#include <Paths.hpp>
#include <common/windows/SessionPausedWindow.hpp>
@@ 36,6 37,7 @@ namespace app
return ret;
}
+ lowBatteryInfoModel = std::make_unique<app::LowBatteryInfoModel>();
cpuSentinel = std::make_shared<sys::CpuSentinel>(applicationBellPowerNapName, this);
auto sentinelRegistrationMsg = std::make_shared<sys::SentinelRegistrationMessage>(cpuSentinel);
bus.sendUnicast(std::move(sentinelRegistrationMsg), service::name::system_manager);
@@ 48,11 50,12 @@ namespace app
void ApplicationBellPowerNap::createUserInterface()
{
- windowsFactory.attach(
- gui::name::window::main_window, [this](ApplicationCommon *app, [[maybe_unused]] const std::string &name) {
- auto presenter = std::make_unique<powernap::PowerNapMainWindowPresenter>(app, settings.get());
- return std::make_unique<gui::PowerNapMainWindow>(app, std::move(presenter));
- });
+ windowsFactory.attach(gui::name::window::main_window,
+ [this](ApplicationCommon *app, [[maybe_unused]] const std::string &name) {
+ auto presenter = std::make_unique<powernap::PowerNapMainWindowPresenter>(
+ app, settings.get(), *batteryModel, *lowBatteryInfoModel);
+ return std::make_unique<gui::PowerNapMainWindow>(app, std::move(presenter));
+ });
windowsFactory.attach(
gui::window::name::powerNapProgress,
[this](ApplicationCommon *app, [[maybe_unused]] const std::string &name) {
@@ 78,6 81,11 @@ namespace app
auto presenter = std::make_unique<powernap::PowerNapSessionEndPresenter>(app);
return std::make_unique<gui::PowerNapSessionEndedWindow>(app, std::move(presenter));
});
+ windowsFactory.attach(gui::window::name::powerNapWarning,
+ [](ApplicationCommon *app, [[maybe_unused]] const std::string &name) {
+ auto presenter = std::make_unique<powernap::PowerNapWarningPresenter>(app);
+ return std::make_unique<gui::PowerNapWarningWindow>(app, std::move(presenter));
+ });
attachPopups({gui::popup::ID::AlarmActivated,
gui::popup::ID::AlarmDeactivated,
M products/BellHybrid/apps/application-bell-powernap/CMakeLists.txt => products/BellHybrid/apps/application-bell-powernap/CMakeLists.txt +4 -0
@@ 19,9 19,11 @@ target_sources(application-bell-powernap
presenter/PowerNapMainWindowPresenter.cpp
presenter/PowerNapProgressPresenter.cpp
presenter/PowerNapSessionEndedPresenter.cpp
+ presenter/PowerNapWarningPresenter.cpp
windows/PowerNapMainWindow.cpp
windows/PowerNapProgressWindow.cpp
windows/PowerNapSessionEndedWindow.cpp
+ windows/PowerNapWarningWindow.cpp
data/PowerNapListItem.cpp
models/PowerNapModel.cpp
models/PowerNapFrontlightModel.cpp
@@ 29,9 31,11 @@ target_sources(application-bell-powernap
presenter/PowerNapMainWindowPresenter.hpp
presenter/PowerNapProgressPresenter.hpp
presenter/PowerNapSessionEndedPresenter.hpp
+ presenter/PowerNapWarningPresenter.hpp
windows/PowerNapMainWindow.hpp
windows/PowerNapProgressWindow.hpp
windows/PowerNapSessionEndedWindow.hpp
+ windows/PowerNapWarningWindow.hpp
data/PowerNapListItem.hpp
data/PowerNapStyle.hpp
data/PowerNapCommon.hpp
M products/BellHybrid/apps/application-bell-powernap/include/application-bell-powernap/ApplicationBellPowerNap.hpp => products/BellHybrid/apps/application-bell-powernap/include/application-bell-powernap/ApplicationBellPowerNap.hpp +4 -1
@@ 1,15 1,17 @@
-// 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 <common/models/AbstractAudioModel.hpp>
#include <Application.hpp>
+#include <common/models/LowBatteryInfoModel.hpp>
namespace gui::window::name
{
inline constexpr auto powerNapProgress = "PowerNapProgressWindow";
inline constexpr auto powerNapSessionEnded = "PowerNapSessionEndedWindow";
+ inline constexpr auto powerNapWarning = "PowerNapWarningWindow";
} // namespace gui::window::name
namespace app
@@ 22,6 24,7 @@ namespace app
{
private:
std::unique_ptr<AbstractAudioModel> audioModel;
+ std::unique_ptr<AbstractLowBatteryInfoModel> lowBatteryInfoModel;
std::shared_ptr<sys::CpuSentinel> cpuSentinel;
void onStop() override;
M products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapMainWindowPresenter.cpp => products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapMainWindowPresenter.cpp +31 -4
@@ 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 "PowerNapMainWindowPresenter.hpp"
@@ 8,8 8,12 @@
namespace app::powernap
{
- PowerNapMainWindowPresenter::PowerNapMainWindowPresenter(app::ApplicationCommon *app, settings::Settings *settings)
- : app{app}, settings{settings}, model{std::make_shared<PowerNapModel>()}
+ PowerNapMainWindowPresenter::PowerNapMainWindowPresenter(app::ApplicationCommon *app,
+ settings::Settings *settings,
+ AbstractBatteryModel &batteryModel,
+ AbstractLowBatteryInfoModel &lowBatteryInfoModel)
+ : app{app}, settings{settings}, model{std::make_shared<PowerNapModel>()}, batteryModel{batteryModel},
+ lowBatteryInfoModel{lowBatteryInfoModel}
{}
auto PowerNapMainWindowPresenter::getNapTimeProvider() -> std::shared_ptr<gui::ListItemProvider>
@@ 30,6 34,29 @@ namespace app::powernap
settings->setValue(
powernapDBRecordName, utils::to_string(currentValue.count()), settings::SettingsScope::AppLocal);
static_cast<app::Application *>(app)->suspendIdleTimer();
- app->switchWindow(gui::window::name::powerNapProgress);
+ conditionalSwitchScreen();
+ }
+
+ void PowerNapMainWindowPresenter::conditionalSwitchScreen()
+ {
+ const auto batteryState = batteryModel.getLevelState();
+ if (not lowBatteryInfoModel.isInfoHandled() && not isBatteryCharging(batteryState.state) &&
+ isBatteryBelowLowLevelThreshold(batteryState.level)) {
+ app->switchWindow(gui::window::name::powerNapWarning);
+ lowBatteryInfoModel.handleInfo();
+ }
+ else {
+ app->switchWindow(gui::window::name::powerNapProgress);
+ }
+ }
+
+ bool PowerNapMainWindowPresenter::isBatteryCharging(Store::Battery::State state) const
+ {
+ return batteryModel.isBatteryCharging(state);
+ }
+
+ bool PowerNapMainWindowPresenter::isBatteryBelowLowLevelThreshold(units::SOC soc) const
+ {
+ return soc < constants::lowBatteryInfoThreshold;
}
} // namespace app::powernap
M products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapMainWindowPresenter.hpp => products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapMainWindowPresenter.hpp +18 -6
@@ 1,9 1,11 @@
-// 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 <apps-common/BasePresenter.hpp>
+#include <common/models/BatteryModel.hpp>
+#include <common/models/LowBatteryInfoModel.hpp>
#include <memory>
namespace gui
@@ 45,15 47,25 @@ namespace app::powernap
class PowerNapMainWindowPresenter : public PowerNapMainWindowContract::Presenter
{
- app::ApplicationCommon *app = nullptr;
- settings::Settings *settings = nullptr;
- std::shared_ptr<PowerNapModel> model;
-
public:
- PowerNapMainWindowPresenter(app::ApplicationCommon *app, settings::Settings *settings);
+ PowerNapMainWindowPresenter(app::ApplicationCommon *app,
+ settings::Settings *settings,
+ AbstractBatteryModel &batteryModel,
+ AbstractLowBatteryInfoModel &lowBatteryInfoModel);
auto getNapTimeProvider() -> std::shared_ptr<gui::ListItemProvider> override;
void loadNapTimeList() override;
void activate() override;
+
+ private:
+ bool isBatteryCharging(Store::Battery::State state) const;
+ bool isBatteryBelowLowLevelThreshold(units::SOC soc) const;
+ void conditionalSwitchScreen();
+
+ app::ApplicationCommon *app{nullptr};
+ settings::Settings *settings{nullptr};
+ std::shared_ptr<PowerNapModel> model;
+ AbstractBatteryModel &batteryModel;
+ AbstractLowBatteryInfoModel &lowBatteryInfoModel;
};
} // namespace app::powernap
A products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapWarningPresenter.cpp => products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapWarningPresenter.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 "PowerNapWarningPresenter.hpp"
+#include <ApplicationBellPowerNap.hpp>
+
+namespace app::powernap
+{
+ PowerNapWarningPresenter::PowerNapWarningPresenter(app::ApplicationCommon *app) : app{app}
+ {}
+
+ void PowerNapWarningPresenter::activate()
+ {
+ auto data = std::make_unique<gui::SwitchData>();
+ data->ignoreCurrentWindowOnStack = true;
+ app->switchWindow(gui::window::name::powerNapProgress, std::move(data));
+ }
+} // namespace app::powernap
A products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapWarningPresenter.hpp => products/BellHybrid/apps/application-bell-powernap/presenter/PowerNapWarningPresenter.hpp +38 -0
@@ 0,0 1,38 @@
+// 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>
+
+namespace app
+{
+ class ApplicationCommon;
+}
+
+namespace app::powernap
+{
+ class PowerNapWarningContract
+ {
+ public:
+ class View
+ {
+ public:
+ virtual ~View() = default;
+ };
+ class Presenter : public BasePresenter<PowerNapWarningContract::View>
+ {
+ public:
+ virtual void activate() = 0;
+ };
+ };
+
+ class PowerNapWarningPresenter : public PowerNapWarningContract::Presenter
+ {
+ app::ApplicationCommon *app{nullptr};
+ void activate() override;
+
+ public:
+ explicit PowerNapWarningPresenter(app::ApplicationCommon *app);
+ };
+} // namespace app::powernap
A products/BellHybrid/apps/application-bell-powernap/windows/PowerNapWarningWindow.cpp => products/BellHybrid/apps/application-bell-powernap/windows/PowerNapWarningWindow.cpp +71 -0
@@ 0,0 1,71 @@
+// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "PowerNapWarningWindow.hpp"
+#include <application-bell-powernap/ApplicationBellPowerNap.hpp>
+
+#include <gui/input/InputEvent.hpp>
+#include <gui/widgets/Icon.hpp>
+#include <common/data/StyleCommon.hpp>
+
+namespace
+{
+ constexpr std::chrono::seconds screenTimeout{5};
+} // namespace
+
+namespace gui
+{
+ PowerNapWarningWindow::PowerNapWarningWindow(
+ app::ApplicationCommon *app, std::shared_ptr<app::powernap::PowerNapWarningContract::Presenter> presenter)
+ : WindowWithTimer(app, window::name::powerNapWarning, screenTimeout), presenter{std::move(presenter)}
+ {
+ buildInterface();
+ }
+
+ void PowerNapWarningWindow::buildInterface()
+ {
+ AppWindow::buildInterface();
+ buildLayout();
+ registerCallbacks();
+ resetTimer(screenTimeout);
+ }
+
+ void PowerNapWarningWindow::buildLayout()
+ {
+ statusBar->setVisible(false);
+ header->setTitleVisibility(false);
+ navBar->setVisible(false);
+
+ icon = new Icon(this,
+ 0,
+ 0,
+ style::window_width,
+ style::window_height,
+ "bell_status_battery_lvl0",
+ {},
+ gui::ImageTypeSpecifier::W_G);
+ icon->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));
+ icon->image->setMargins({0, gui::bell_style::warning_icon_top_margin, 0, 0});
+ icon->text->setMaximumWidth(gui::bell_style::warning_text_width);
+ icon->text->setFont(style::window::font::verybiglight);
+ icon->text->setRichText(utils::translate("app_bell_alarm_lowBattery_info"));
+ }
+
+ bool PowerNapWarningWindow::onInput(const InputEvent &inputEvent)
+ {
+ if (inputEvent.isShortRelease(KeyCode::KEY_ENTER) || inputEvent.isShortRelease(KeyCode::KEY_RF)) {
+ detachTimerIfExists();
+ presenter->activate();
+ return true;
+ }
+ return false;
+ }
+
+ void PowerNapWarningWindow::registerCallbacks()
+ {
+ timerCallback = [this](Item &, sys::Timer &timer) {
+ presenter->activate();
+ return true;
+ };
+ }
+} // namespace gui
A products/BellHybrid/apps/application-bell-powernap/windows/PowerNapWarningWindow.hpp => products/BellHybrid/apps/application-bell-powernap/windows/PowerNapWarningWindow.hpp +29 -0
@@ 0,0 1,29 @@
+// 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 "presenter/PowerNapWarningPresenter.hpp"
+#include <apps-common/popups/WindowWithTimer.hpp>
+
+namespace gui
+{
+ class Icon;
+
+ class PowerNapWarningWindow : public WindowWithTimer, public app::powernap::PowerNapWarningContract::View
+ {
+ public:
+ PowerNapWarningWindow(app::ApplicationCommon *app,
+ std::shared_ptr<app::powernap::PowerNapWarningContract::Presenter> presenter);
+
+ protected:
+ void buildInterface() override;
+ bool onInput(const InputEvent &inputEvent) override;
+ void buildLayout();
+ void registerCallbacks();
+
+ private:
+ std::shared_ptr<app::powernap::PowerNapWarningContract::Presenter> presenter;
+ Icon *icon{};
+ };
+} // namespace gui
M => +1 -4
@@ 18,16 18,13 @@ namespace gui
public:
AlarmActivatedWindow(app::ApplicationCommon *app,
std::shared_ptr<app::popup::AlarmActivatedPresenter> presenter);
void rebuild() override;
private:
bool onInput(const InputEvent &inputEvent) override;
void buildInterface() override;
void onBeforeShow(ShowMode mode, SwitchData *data) override;
void returnToPreviousWindow();
void setAlarmTime(time_t alarmTime);
void buildLowBatteryLayout();
void buildAlarmInfoLayout();
void lowBatteryInfoHandled();
Icon *icon{};
};
M => +1 -15
@@ 5,19 5,11 @@
#include <apps-common/BasePresenter.hpp>
#include <common/models/AbstractAlarmModel.hpp>
#include <common/models/BatteryModel.hpp>
#include <memory>
namespace app::popup
{
enum class Layout
{
Undefined,
LowBatteryInfo,
AlarmInfo
};
class AlarmActivatedContract
{
public:
@@ 46,24 38,18 @@ namespace app::popup
virtual ~Presenter() noexcept = default;
virtual time_t getAlarmTime() const noexcept = 0;
virtual bool isAlarmActive() const noexcept = 0;
virtual Layout getLayout() = 0;
virtual void lowBatteryInfoHandled() = 0;
};
};
class AlarmActivatedPresenter : public AlarmActivatedContract::Presenter
{
public:
AlarmActivatedPresenter(AbstractAlarmModel &alarmModel, AbstractBatteryModel &batteryModel);
AlarmActivatedPresenter(AbstractAlarmModel &alarmModel);
time_t getAlarmTime() const noexcept;
bool isAlarmActive() const noexcept;
Layout getLayout();
void lowBatteryInfoHandled();
private:
AbstractAlarmModel &alarmModel;
AbstractBatteryModel &batteryModel;
Layout layout{Layout::Undefined};
};
} // namespace app::popup
M => +9 -52
@@ 18,7 18,6 @@
namespace
{
constexpr unsigned int y_position = 22U;
constexpr std::chrono::seconds screenTimeout{5};
} // namespace
namespace gui
@@ 30,6 29,11 @@ namespace gui
{
getPresenter()->attach(this);
buildInterface();
timerCallback = [this](Item &, sys::Timer &) {
returnToPreviousWindow();
return true;
};
}
void AlarmActivatedWindow::buildInterface()
@@ 40,60 44,18 @@ namespace gui
header->setTitleVisibility(false);
navBar->setVisible(false);
getPresenter()->getLayout() == app::popup::Layout::LowBatteryInfo ? buildLowBatteryLayout()
: buildAlarmInfoLayout();
}
void AlarmActivatedWindow::buildLowBatteryLayout()
{
icon = new Icon(this,
0,
0,
style::window_width,
style::window_height,
"bell_status_battery_lvl0",
{},
gui::ImageTypeSpecifier::W_G);
icon->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));
icon->image->setMargins({0, bell_style::warning_icon_top_margin, 0, 0});
icon->text->setMaximumWidth(bell_style::warning_text_width);
icon->text->setFont(style::window::font::verybiglight);
icon->text->setRichText(utils::translate("app_bell_alarm_lowBattery_info"));
timerCallback = [this](Item &, sys::Timer &timer) {
lowBatteryInfoHandled();
return true;
};
resetTimer(screenTimeout);
}
void AlarmActivatedWindow::buildAlarmInfoLayout()
{
icon = new Icon(this, 0, 0, style::window_width, style::window_height, "big_alarm_W_G", {});
icon->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));
icon->image->setMargins({0, bell_style::popup_icon_top_margin, 0, bell_style::popup_icon_bottom_margin});
icon->text->setFont(style::window::font::verybiglight);
setAlarmTime(getPresenter()->getAlarmTime());
timerCallback = [this](Item &, sys::Timer &) {
returnToPreviousWindow();
return true;
};
resetTimer(screenTimeout);
}
void AlarmActivatedWindow::rebuild()
void AlarmActivatedWindow::onBeforeShow(ShowMode mode, SwitchData *data)
{
erase();
buildInterface();
setAlarmTime(getPresenter()->getAlarmTime());
WindowWithTimer::onBeforeShow(mode, data);
}
void AlarmActivatedWindow::lowBatteryInfoHandled()
{
getPresenter()->lowBatteryInfoHandled();
rebuild();
application->refreshWindow(gui::RefreshModes::GUI_REFRESH_FAST);
}
void AlarmActivatedWindow::returnToPreviousWindow()
{
@@ 114,12 76,7 @@ namespace gui
{
if (inputEvent.isShortRelease(KeyCode::KEY_ENTER) || inputEvent.isShortRelease(KeyCode::KEY_RF)) {
detachTimerIfExists();
if (getPresenter()->getLayout() == app::popup::Layout::LowBatteryInfo) {
lowBatteryInfoHandled();
}
else {
returnToPreviousWindow();
}
returnToPreviousWindow();
return true;
}
return false;
M => +1 -23
@@ 8,8 8,7 @@
namespace app::popup
{
AlarmActivatedPresenter::AlarmActivatedPresenter(AbstractAlarmModel &alarmModel, AbstractBatteryModel &batteryModel)
: alarmModel{alarmModel}, batteryModel{batteryModel}
AlarmActivatedPresenter::AlarmActivatedPresenter(AbstractAlarmModel &alarmModel) : alarmModel{alarmModel}
{}
bool AlarmActivatedPresenter::isAlarmActive() const noexcept
@@ 22,25 21,4 @@ namespace app::popup
return alarmModel.getAlarmTime();
}
Layout AlarmActivatedPresenter::getLayout()
{
if (layout == Layout::Undefined) {
const auto batteryStatus = batteryModel.getLevelState();
const units::SOC soc = batteryStatus.level;
const auto state = batteryStatus.state;
if (not batteryModel.isBatteryCharging(state) && soc < constants::lowBatteryInfoThreshold) {
layout = Layout::LowBatteryInfo;
}
else {
layout = Layout::AlarmInfo;
}
}
return layout;
}
void AlarmActivatedPresenter::lowBatteryInfoHandled()
{
layout = Layout::AlarmInfo;
}
} // namespace app::popup