M image/assets/lang/English.json => image/assets/lang/English.json +10 -0
@@ 596,6 596,16 @@
"app_bellmain_background_sounds": "Library",
"app_bellmain_settings": "Settings",
"app_bellmain_main_window_title": "Bell Hybrid+",
+ "app_bell_meditation_timer": "Meditation",
+ "app_bell_meditation_interval_chime": "Interval chime",
+ "app_bell_meditation_progress": "Meditation timer",
+ "app_bell_meditation_interval_none": "None",
+ "app_bell_meditation_interval_every_x_minutes": "every %0",
+ "app_bell_meditation_put_down_and_wait": "<text>Put down Bell Harmony<br>and wait for the gong</text>",
+ "app_bell_meditation_thank_you_for_session": "<text>Thank you for<br>the session</text>",
+ "app_bell_meditation_minute": "minute",
+ "app_bell_meditation_minutes": "minutes",
+ "app_bell_meditation_paused": "<text>Paused</text>",
"app_bell_onboarding_welcome_message": "Mudita Harmony",
"app_bell_onboarding_info_rotate": "<text font='gt_pressura' weight='regular' size='38'>Rotate </text><text font='gt_pressura' weight='light' size='38'>to select</text>",
"app_bell_onboarding_info_light_click": "<text font='gt_pressura' weight='regular' size='38'>Light click </text><text font='gt_pressura' weight='light' size='38'>to continue</text>",
M products/BellHybrid/BellHybridMain.cpp => products/BellHybrid/BellHybridMain.cpp +3 -0
@@ 9,6 9,7 @@
#include <application-bell-background-sounds/ApplicationBellBackgroundSounds.hpp>
#include <application-bell-bedtime/ApplicationBellBedtime.hpp>
#include <application-bell-main/ApplicationBellMain.hpp>
+#include <application-bell-meditation-timer/ApplicationBellMeditationTimer.hpp>
#include <application-bell-settings/ApplicationBellSettings.hpp>
#include <application-bell-powernap/ApplicationBellPowerNap.hpp>
@@ 104,6 105,8 @@ int main()
app::CreateLauncher<app::ApplicationBellOnBoarding>(app::applicationBellOnBoardingName));
applications.push_back(
app::CreateLauncher<app::ApplicationBellBackgroundSounds>(app::applicationBellBackgroundSoundsName));
+ applications.push_back(
+ app::CreateLauncher<app::ApplicationBellMeditationTimer>(app::applicationBellMeditationTimerName));
// start application manager
return sysmgr->RunSystemService(
std::make_shared<app::manager::ApplicationManager>(
M products/BellHybrid/CMakeLists.txt => products/BellHybrid/CMakeLists.txt +1 -0
@@ 44,6 44,7 @@ target_link_libraries(BellHybrid
bell::app-bedtime
bell::app-common
bell::app-main
+ bell::app-meditation-timer
bell::app-powernap
bell::app-settings
bell::db
M products/BellHybrid/apps/CMakeLists.txt => products/BellHybrid/apps/CMakeLists.txt +1 -0
@@ 25,6 25,7 @@ add_subdirectory(application-bell-onboarding)
add_subdirectory(application-bell-background-sounds)
add_subdirectory(application-bell-alarm)
add_subdirectory(application-bell-bedtime)
+add_subdirectory(application-bell-meditation-timer)
add_subdirectory(application-bell-settings)
add_subdirectory(application-bell-powernap)
add_subdirectory(common)
M products/BellHybrid/apps/application-bell-main/CMakeLists.txt => products/BellHybrid/apps/application-bell-main/CMakeLists.txt +1 -0
@@ 58,6 58,7 @@ target_link_libraries(application-bell-main
bell::app-onboarding
bell::app-background-sounds
bell::app-bedtime
+ bell::app-meditation-timer
bell::app-settings
bell::app-powernap
bell::keymap
M products/BellHybrid/apps/application-bell-main/windows/BellMainMenuWindow.cpp => products/BellHybrid/apps/application-bell-main/windows/BellMainMenuWindow.cpp +2 -21
@@ 7,6 7,7 @@
#include <application-bell-background-sounds/ApplicationBellBackgroundSounds.hpp>
#include <application-bell-bedtime/ApplicationBellBedtime.hpp>
#include <application-bell-main/ApplicationBellMain.hpp>
+#include <application-bell-meditation-timer/ApplicationBellMeditationTimer.hpp>
#include <application-bell-settings/ApplicationBellSettings.hpp>
#include <application-bell-powernap/ApplicationBellPowerNap.hpp>
#include <data/BellMainStyle.hpp>
@@ 28,26 29,6 @@ namespace gui
{
std::list<gui::Option> menuOptionList;
- auto addWinMenu = [&](const UTF8 &name, const std::string &window) {
- menuOptionList.emplace_back(std::make_unique<gui::option::OptionBellMenu>(
- name,
- [=](gui::Item &item) {
- if (window.empty()) {
- return false;
- }
- application->switchWindow(
- window,
- gui::ShowMode::GUI_SHOW_INIT,
- std::make_unique<gui::DialogMetadataMessage>(gui::DialogMetadata{name, "search_big", " "}));
- return true;
- },
- [=](gui::Item &item) {
- // put focus change callback here
- return true;
- },
- this));
- };
-
auto addAppMenu = [&](const UTF8 &name, const std::string &appName) {
menuOptionList.emplace_back(std::make_unique<gui::option::OptionBellMenu>(
name,
@@ 70,7 51,7 @@ namespace gui
addAppMenu(utils::translate("app_bellmain_power_nap"), app::applicationBellPowerNapName);
addAppMenu(utils::translate("app_bellmain_background_sounds"), app::applicationBellBackgroundSoundsName);
// for demo only - to be replaced by call o final window
- addWinMenu(utils::translate("app_bellmain_meditation_timer"), gui::window::name::bell_main_menu_dialog);
+ addAppMenu(utils::translate("app_bellmain_meditation_timer"), app::applicationBellMeditationTimerName);
addAppMenu(utils::translate("app_bellmain_bedtime"), app::applicationBellBedtimeName);
addAppMenu(utils::translate("app_bellmain_settings"), app::applicationBellSettingsName);
A products/BellHybrid/apps/application-bell-meditation-timer/ApplicationBellMeditationTimer.cpp => products/BellHybrid/apps/application-bell-meditation-timer/ApplicationBellMeditationTimer.cpp +89 -0
@@ 0,0 1,89 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "ApplicationBellMeditationTimer.hpp"
+#include "windows/IntervalChimeWindow.hpp"
+#include "windows/MeditationRunningWindow.hpp"
+#include "windows/MeditationTimerWindow.hpp"
+#include "windows/ReadyGoingWindow.hpp"
+#include "windows/SessionEndWindow.hpp"
+#include "windows/SessionPausedWindow.hpp"
+
+#include <common/models/TimeModel.hpp>
+
+namespace app
+{
+ ApplicationBellMeditationTimer::ApplicationBellMeditationTimer(std::string name,
+ std::string parent,
+ StatusIndicators statusIndicators,
+ StartInBackground startInBackground)
+ : Application(std::move(name), std::move(parent), statusIndicators, startInBackground)
+ {}
+
+ ApplicationBellMeditationTimer::~ApplicationBellMeditationTimer() = default;
+
+ sys::ReturnCodes ApplicationBellMeditationTimer::InitHandler()
+ {
+ auto ret = Application::InitHandler();
+ if (ret != sys::ReturnCodes::Success) {
+ return ret;
+ }
+
+ createUserInterface();
+
+ return sys::ReturnCodes::Success;
+ }
+
+ void ApplicationBellMeditationTimer::createUserInterface()
+ {
+ windowsFactory.attach(gui::name::window::main_window, [this](ApplicationCommon *app, const std::string &name) {
+ auto presenter = std::make_unique<app::meditation::MeditationTimerPresenter>(app, settings.get());
+ return std::make_unique<gui::MeditationTimerWindow>(app, std::move(presenter));
+ });
+ windowsFactory.attach(
+ gui::name::window::intervalChime, [this](ApplicationCommon *app, const std::string &name) {
+ auto presenter = std::make_unique<app::meditation::IntervalChimePresenter>(app, settings.get());
+ return std::make_unique<gui::IntervalChimeWindow>(app, std::move(presenter));
+ });
+ windowsFactory.attach(gui::name::window::readyGoing, [](ApplicationCommon *app, const std::string &name) {
+ auto presenter = std::make_unique<app::meditation::ReadyGoingPresenter>(app);
+ return std::make_unique<gui::ReadyGoingWindow>(app, std::move(presenter));
+ });
+ windowsFactory.attach(gui::name::window::meditationProgress,
+ [this](ApplicationCommon *app, const std::string &name) {
+ auto timeModel = std::make_unique<app::TimeModel>();
+ auto presenter = std::make_unique<app::meditation::MeditationProgressPresenter>(
+ app, settings.get(), std::move(timeModel));
+ return std::make_unique<gui::MeditationRunningWindow>(app, std::move(presenter));
+ });
+ windowsFactory.attach(gui::name::window::sessionPaused, [](ApplicationCommon *app, const std::string &name) {
+ return std::make_unique<gui::SessionPausedWindow>(app);
+ });
+ windowsFactory.attach(gui::name::window::sessionEnded, [](ApplicationCommon *app, const std::string &name) {
+ auto presenter = std::make_unique<app::meditation::SessionEndedPresenter>(app);
+ return std::make_unique<gui::SessionEndWindow>(app, std::move(presenter));
+ });
+
+ attachPopups({gui::popup::ID::AlarmActivated,
+ gui::popup::ID::AlarmDeactivated,
+ gui::popup::ID::PowerOff,
+ gui::popup::ID::Reboot,
+ gui::popup::ID::BedtimeNotification});
+ }
+
+ sys::MessagePointer ApplicationBellMeditationTimer::DataReceivedHandler(sys::DataMessage *msgl,
+ sys::ResponseMessage *resp)
+ {
+ auto retMsg = Application::DataReceivedHandler(msgl);
+ if (auto response = dynamic_cast<sys::ResponseMessage *>(retMsg.get());
+ response != nullptr && response->retCode == sys::ReturnCodes::Success) {
+ return retMsg;
+ }
+
+ return handleAsyncResponse(resp);
+ }
+
+ // Empty: do not start idleTimer on application run
+ void ApplicationBellMeditationTimer::onStart()
+ {}
+} // namespace app
A products/BellHybrid/apps/application-bell-meditation-timer/CMakeLists.txt => products/BellHybrid/apps/application-bell-meditation-timer/CMakeLists.txt +48 -0
@@ 0,0 1,48 @@
+add_library(application-bell-meditation-timer STATIC)
+add_library(bell::app-meditation-timer ALIAS application-bell-meditation-timer)
+
+target_include_directories(application-bell-meditation-timer
+ PRIVATE
+ $<BUILD_INTERFACE:
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ data
+ include/application-bell-meditation-timer
+ models
+ presenter
+ widgets
+ windows
+ >
+ PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+)
+
+target_sources(application-bell-meditation-timer
+ PRIVATE
+ ApplicationBellMeditationTimer.cpp
+ presenter/IntervalChimePresenter.cpp
+ presenter/MeditationProgressPresenter.cpp
+ presenter/MeditationTimerPresenter.cpp
+ presenter/ReadyGoingPresenter.cpp
+ presenter/SessionEndedPresenter.cpp
+ windows/IntervalChimeWindow.cpp
+ windows/MeditationRunningWindow.cpp
+ windows/MeditationTimerWindow.cpp
+ windows/ReadyGoingWindow.cpp
+ windows/SessionEndWindow.cpp
+ windows/SessionPausedWindow.cpp
+ PUBLIC
+ include/application-bell-meditation-timer/ApplicationBellMeditationTimer.hpp
+)
+
+target_link_libraries(application-bell-meditation-timer
+ PRIVATE
+ app
+ bell::app-common
+ bell::app-main
+ bellgui
+ service-appmgr
+ service-time
+ PUBLIC
+ apps-common
+ module-gui
+)
A products/BellHybrid/apps/application-bell-meditation-timer/data/MeditationCommon.hpp => products/BellHybrid/apps/application-bell-meditation-timer/data/MeditationCommon.hpp +10 -0
@@ 0,0 1,10 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+namespace app::meditation
+{
+ constexpr auto meditationDBRecordName = "MeditationTimer";
+ constexpr auto intervalDBRecordName = "IntervalChime";
+} // namespace app::meditation
A products/BellHybrid/apps/application-bell-meditation-timer/data/MeditationStyle.hpp => products/BellHybrid/apps/application-bell-meditation-timer/data/MeditationStyle.hpp +84 -0
@@ 0,0 1,84 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <Style.hpp>
+
+namespace app::meditationStyle
+{
+ namespace itStyle
+ {
+ namespace icon
+ {
+ constexpr inline auto imageLogo = "bell_big_logo";
+ constexpr inline auto imagePause = "big_pause";
+ constexpr inline auto imageTopMargin = 112;
+ constexpr inline auto imageBottomMargin = 30;
+ } // namespace icon
+
+ namespace text
+ {
+ constexpr inline auto font = style::window::font::verybiglight;
+ } // namespace text
+ } // namespace itStyle
+
+ namespace icStyle
+ {
+ namespace text
+ {
+ constexpr inline auto font = style::window::font::supersizemelight;
+ } // namespace text
+
+ namespace minute
+ {
+ constexpr inline auto font = style::window::font::largelight;
+ } // namespace minute
+
+ namespace list
+ {
+ constexpr inline auto timeUnitSingular = "common_minute_lower";
+ constexpr inline auto timeUnitPlural = "common_minutes_lower";
+ } // namespace list
+ } // namespace icStyle
+
+ namespace mrStyle
+ {
+ namespace title
+ {
+ constexpr inline auto font = style::window::font::verybiglight;
+ } // namespace title
+
+ namespace progress
+ {
+ constexpr inline auto progressMarginTop = 40;
+ constexpr inline auto progressMarginLeft = 60;
+ constexpr inline auto boxesCount = 16;
+ } // namespace progress
+
+ namespace timer
+ {
+ constexpr inline auto timerMarginBottom = 20;
+ constexpr inline auto font = style::window::font::largelight;
+ } // namespace timer
+ } // namespace mrStyle
+
+ namespace mtStyle
+ {
+ namespace text
+ {
+ constexpr inline auto font = style::window::font::supersizemelight;
+ } // namespace text
+
+ namespace minute
+ {
+ constexpr inline auto font = style::window::font::largelight;
+ } // namespace minute
+
+ namespace list
+ {
+ constexpr inline auto timeUnitSingular = "common_minute_lower";
+ constexpr inline auto timeUnitPlural = "common_minutes_lower";
+ } // namespace list
+ } // namespace mtStyle
+} // namespace app::meditationStyle
A products/BellHybrid/apps/application-bell-meditation-timer/include/application-bell-meditation-timer/ApplicationBellMeditationTimer.hpp => products/BellHybrid/apps/application-bell-meditation-timer/include/application-bell-meditation-timer/ApplicationBellMeditationTimer.hpp +55 -0
@@ 0,0 1,55 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <Application.hpp>
+
+namespace gui::name::window
+{
+ inline constexpr auto intervalChime = "IntervalChimeWindow";
+ inline constexpr auto meditationProgress = "MeditationProgressWindow";
+ inline constexpr auto meditationTimer = "MeditationTimerWindow";
+ inline constexpr auto readyGoing = "ReadyGoingWindow";
+ inline constexpr auto sessionEnded = "SessionEndedWindow";
+ inline constexpr auto sessionPaused = "SensionPausedWindow";
+} // namespace gui::name::window
+
+namespace app
+{
+ inline constexpr auto applicationBellMeditationTimerName = "ApplicationBellMeditationTimer";
+
+ class ApplicationBellMeditationTimer : public Application
+ {
+ public:
+ ApplicationBellMeditationTimer(std::string name = applicationBellMeditationTimerName,
+ std::string parent = "",
+ StatusIndicators statusIndicators = StatusIndicators{},
+ StartInBackground startInBackground = {false});
+ ~ApplicationBellMeditationTimer();
+
+ sys::ReturnCodes InitHandler() override;
+
+ void createUserInterface() override;
+ void destroyUserInterface() override
+ {}
+
+ sys::MessagePointer DataReceivedHandler(sys::DataMessage *msgl, sys::ResponseMessage *resp) override;
+
+ sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override final
+ {
+ return sys::ReturnCodes::Success;
+ }
+
+ private:
+ void onStart() override;
+ };
+
+ template <> struct ManifestTraits<ApplicationBellMeditationTimer>
+ {
+ static auto GetManifest() -> manager::ApplicationManifest
+ {
+ return {{manager::actions::Launch}};
+ }
+ };
+} // namespace app
A products/BellHybrid/apps/application-bell-meditation-timer/presenter/IntervalChimePresenter.cpp => products/BellHybrid/apps/application-bell-meditation-timer/presenter/IntervalChimePresenter.cpp +86 -0
@@ 0,0 1,86 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "ApplicationBellMeditationTimer.hpp"
+#include "IntervalChimePresenter.hpp"
+#include "MeditationCommon.hpp"
+#include "MeditationStyle.hpp"
+
+#include <service-db/Settings.hpp>
+
+namespace app::meditation
+{
+ IntervalChimePresenter::IntervalChimePresenter(app::ApplicationCommon *app, settings::Settings *settings)
+ : app{app}, settings{settings}
+ {
+ initIntervalOptions();
+ }
+
+ std::vector<std::string> IntervalChimePresenter::getIntervals() const
+ {
+ std::vector<std::string> intervalNames;
+ for (auto const &option : intervalOptions) {
+ intervalNames.push_back(option.second);
+ }
+ return intervalNames;
+ }
+
+ std::string IntervalChimePresenter::getCurrentInterval() const
+ {
+ // Always set interval as none
+ for (auto const &option : intervalOptions) {
+ if (option.first == std::chrono::minutes{0}) {
+ return option.second;
+ }
+ }
+ return intervalOptions.at(0).second;
+ }
+
+ std::string IntervalChimePresenter::getTimeUnitName(std::string value)
+ {
+ using namespace app::meditationStyle::mtStyle::list;
+ for (auto const &option : intervalOptions) {
+ if (option.second == value) {
+ if (option.first == std::chrono::minutes{0}) {
+ return "";
+ }
+ if (option.first == std::chrono::minutes{1}) {
+ return utils::translate(timeUnitSingular);
+ }
+ return utils::translate(timeUnitPlural);
+ }
+ }
+ return "";
+ }
+
+ void IntervalChimePresenter::activate(std::string value)
+ {
+ for (auto const &option : intervalOptions) {
+ if (option.second == value) {
+ settings->setValue(
+ intervalDBRecordName, utils::to_string(option.first.count()), settings::SettingsScope::AppLocal);
+ app->switchWindow(gui::name::window::readyGoing);
+ break;
+ }
+ }
+ }
+
+ void IntervalChimePresenter::initIntervalOptions()
+ {
+ intervalOptions.push_back({std::chrono::minutes{0}, utils::translate("app_bell_meditation_interval_none")});
+ intervalOptions.push_back({std::chrono::minutes{1}, getIntervalString(1)});
+ intervalOptions.push_back({std::chrono::minutes{2}, getIntervalString(2)});
+ intervalOptions.push_back({std::chrono::minutes{5}, getIntervalString(5)});
+ intervalOptions.push_back({std::chrono::minutes{10}, getIntervalString(10)});
+ intervalOptions.push_back({std::chrono::minutes{15}, getIntervalString(15)});
+ intervalOptions.push_back({std::chrono::minutes{30}, getIntervalString(30)});
+ }
+
+ std::string IntervalChimePresenter::getIntervalString(std::uint32_t value)
+ {
+ const std::string toReplace = "%0";
+ std::string temp = utils::translate("app_bell_meditation_interval_every_x_minutes");
+ temp.replace(temp.find(toReplace), toReplace.size(), std::to_string(value));
+ return temp;
+ }
+} // namespace app::meditation
A products/BellHybrid/apps/application-bell-meditation-timer/presenter/IntervalChimePresenter.hpp => products/BellHybrid/apps/application-bell-meditation-timer/presenter/IntervalChimePresenter.hpp +54 -0
@@ 0,0 1,54 @@
+// Copyright (c) 2017-2021, 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>
+
+namespace app
+{
+ class ApplicationCommon;
+}
+
+namespace app::meditation
+{
+ class IntervalChimeContract
+ {
+ public:
+ class View
+ {
+ public:
+ virtual ~View() = default;
+ };
+
+ class Presenter : public BasePresenter<IntervalChimeContract::View>
+ {
+ public:
+ virtual ~Presenter() noexcept = default;
+ virtual std::vector<std::string> getIntervals() const = 0;
+ virtual std::string getCurrentInterval() const = 0;
+ virtual std::string getTimeUnitName(std::string value) = 0;
+ virtual void activate(std::string value) = 0;
+ };
+ };
+
+ class IntervalChimePresenter : public IntervalChimeContract::Presenter
+ {
+ public:
+ IntervalChimePresenter(app::ApplicationCommon *app, settings::Settings *settings);
+
+ std::vector<std::string> getIntervals() const override;
+ std::string getCurrentInterval() const override;
+ std::string getTimeUnitName(std::string value) override;
+ void activate(std::string value) override;
+
+ private:
+ app::ApplicationCommon *app = nullptr;
+ settings::Settings *settings = nullptr;
+ std::vector<std::pair<std::chrono::minutes, const std::string>> intervalOptions;
+
+ void initIntervalOptions();
+ std::string getIntervalString(std::uint32_t value);
+ };
+} // namespace app::meditation
A products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationProgressPresenter.cpp => products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationProgressPresenter.cpp +92 -0
@@ 0,0 1,92 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "ApplicationBellMeditationTimer.hpp"
+#include "MeditationCommon.hpp"
+#include "MeditationProgressPresenter.hpp"
+
+#include <common/models/TimeModel.hpp>
+#include <service-appmgr/Controller.hpp>
+#include <service-db/Settings.hpp>
+
+namespace
+{
+ constexpr std::chrono::minutes emptyValue{0};
+} // namespace
+
+namespace app::meditation
+{
+ MeditationProgressPresenter ::MeditationProgressPresenter(app::ApplicationCommon *app,
+ settings::Settings *settings,
+ std::unique_ptr<AbstractTimeModel> timeModel)
+ : app{app}, settings{settings}, timeModel{std::move(timeModel)}
+ {
+ duration = std::chrono::minutes{
+ utils::getNumericValue<int>(settings->getValue(meditationDBRecordName, settings::SettingsScope::AppLocal))};
+ interval = std::chrono::minutes{
+ utils::getNumericValue<int>(settings->getValue(intervalDBRecordName, settings::SettingsScope::AppLocal))};
+ }
+
+ void MeditationProgressPresenter::setTimer(std::unique_ptr<app::TimerWithCallbacks> &&_timer)
+ {
+ timer = std::move(_timer);
+ timer->registerOnFinishedCallback([this]() { onProgressFinished(); });
+ if (interval != emptyValue) {
+ timer->registerOnIntervalCallback([this]() { onIntervalReached(); });
+ }
+ }
+
+ void MeditationProgressPresenter::handleUpdateTimeEvent()
+ {
+ getView()->setTime(timeModel->getCurrentTime());
+ }
+
+ void MeditationProgressPresenter::start()
+ {
+ timer->reset(std::chrono::seconds(duration), std::chrono::seconds(interval));
+ timer->start();
+ }
+
+ void MeditationProgressPresenter::stop()
+ {
+ timer->stop();
+ }
+
+ void MeditationProgressPresenter::pause()
+ {
+ timer->stop();
+ app->switchWindow(gui::name::window::sessionPaused);
+ }
+
+ void MeditationProgressPresenter::resume()
+ {
+ timer->start();
+ }
+
+ void MeditationProgressPresenter::abandon()
+ {
+ timer->stop();
+ app::manager::Controller::sendAction(
+ app,
+ app::manager::actions::Launch,
+ std::make_unique<app::ApplicationLaunchData>(app::applicationBellMeditationTimerName));
+ }
+
+ void MeditationProgressPresenter::finish()
+ {
+ timer->stop();
+ app->switchWindow(gui::name::window::sessionEnded);
+ }
+
+ void MeditationProgressPresenter::onProgressFinished()
+ {
+ getView()->progressFinished();
+ }
+
+ void MeditationProgressPresenter::onIntervalReached()
+ {
+ if (interval != emptyValue) {
+ getView()->intervalReached();
+ }
+ }
+} // namespace app::meditation
A products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationProgressPresenter.hpp => products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationProgressPresenter.hpp +84 -0
@@ 0,0 1,84 @@
+// Copyright (c) 2017-2021, 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 <apps-common/widgets/TimerWithCallbacks.hpp>
+#include <time/time_locale.hpp>
+
+#include <memory>
+
+namespace app
+{
+ class AbstractTimeModel;
+ class ApplicationCommon;
+} // namespace app
+
+namespace gui
+{
+ class Item;
+}
+
+namespace settings
+{
+ class Settings;
+}
+
+namespace app::meditation
+{
+ class MeditationProgressContract
+ {
+ public:
+ class View
+ {
+ public:
+ virtual ~View() = default;
+ virtual void progressFinished() = 0;
+ virtual void intervalReached() = 0;
+ virtual void setTime(std::time_t newTime) = 0;
+ virtual void setTimeFormat(utils::time::Locale::TimeFormat fmt) = 0;
+ };
+ class Presenter : public BasePresenter<MeditationProgressContract::View>
+ {
+ public:
+ virtual void setTimer(std::unique_ptr<app::TimerWithCallbacks> &&timer) = 0;
+ virtual void handleUpdateTimeEvent() = 0;
+ virtual void start() = 0;
+ virtual void stop() = 0;
+ virtual void pause() = 0;
+ virtual void resume() = 0;
+ virtual void abandon() = 0;
+ virtual void finish() = 0;
+ };
+ };
+
+ class MeditationProgressPresenter : public MeditationProgressContract::Presenter
+ {
+ private:
+ app::ApplicationCommon *app = nullptr;
+ settings::Settings *settings = nullptr;
+ std::unique_ptr<app::TimerWithCallbacks> timer;
+ std::unique_ptr<AbstractTimeModel> timeModel;
+ std::chrono::minutes duration;
+ std::chrono::minutes interval;
+
+ void onProgressFinished();
+ void onIntervalReached();
+
+ public:
+ MeditationProgressPresenter(app::ApplicationCommon *app,
+ settings::Settings *settings,
+ std::unique_ptr<AbstractTimeModel> timeModel);
+
+ void setTimer(std::unique_ptr<app::TimerWithCallbacks> &&_timer) override;
+ void handleUpdateTimeEvent() override;
+ void start() override;
+ void stop() override;
+ void pause() override;
+ void resume() override;
+ void abandon() override;
+ void finish() override;
+ };
+} // namespace app::meditation
A products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationTimerPresenter.cpp => products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationTimerPresenter.cpp +62 -0
@@ 0,0 1,62 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "ApplicationBellMeditationTimer.hpp"
+#include "MeditationCommon.hpp"
+#include "MeditationStyle.hpp"
+#include "MeditationTimerPresenter.hpp"
+
+#include <service-db/Settings.hpp>
+
+namespace
+{
+ constexpr inline auto spinnerMax = 180U;
+ constexpr inline auto spinnerMin = 1U;
+ constexpr inline auto spinnerStep = 1U;
+ constexpr inline auto emptyValue = 0U;
+ constexpr inline auto defaultValue = 15U;
+} // namespace
+
+namespace app::meditation
+{
+ MeditationTimerPresenter ::MeditationTimerPresenter(app::ApplicationCommon *app, settings::Settings *settings)
+ : app{app}, settings{settings}
+ {}
+
+ std::uint32_t MeditationTimerPresenter::getMinValue()
+ {
+ return spinnerMin;
+ }
+
+ std::uint32_t MeditationTimerPresenter::getMaxValue()
+ {
+ return spinnerMax;
+ }
+
+ std::uint32_t MeditationTimerPresenter::getStepValue()
+ {
+ return spinnerStep;
+ }
+
+ std::uint32_t MeditationTimerPresenter::getCurrentValue()
+ {
+ const auto value = settings->getValue(meditationDBRecordName, settings::SettingsScope::AppLocal);
+ auto defTimer = utils::getNumericValue<std::uint32_t>(value);
+ if (defTimer == emptyValue) {
+ defTimer = defaultValue;
+ }
+ return defTimer;
+ }
+
+ std::string MeditationTimerPresenter::getTimeUnitName(std::uint32_t value)
+ {
+ using namespace app::meditationStyle::mtStyle::list;
+ return utils::translate(value == 1 ? timeUnitSingular : timeUnitPlural);
+ }
+
+ void MeditationTimerPresenter::activate(std::uint32_t value)
+ {
+ settings->setValue(meditationDBRecordName, utils::to_string(value), settings::SettingsScope::AppLocal);
+ app->switchWindow(gui::name::window::intervalChime);
+ }
+} // namespace app::meditation
A products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationTimerPresenter.hpp => products/BellHybrid/apps/application-bell-meditation-timer/presenter/MeditationTimerPresenter.hpp +59 -0
@@ 0,0 1,59 @@
+// Copyright (c) 2017-2021, 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>
+
+namespace app
+{
+ class ApplicationCommon;
+}
+
+namespace settings
+{
+ class Settings;
+}
+
+namespace app::meditation
+{
+ class MeditationTimerContract
+ {
+ public:
+ class View
+ {
+ public:
+ virtual ~View() = default;
+ };
+
+ class Presenter : public BasePresenter<MeditationTimerContract::View>
+ {
+ public:
+ virtual ~Presenter() noexcept = default;
+ virtual std::uint32_t getMinValue() = 0;
+ virtual std::uint32_t getMaxValue() = 0;
+ virtual std::uint32_t getStepValue() = 0;
+ virtual std::uint32_t getCurrentValue() = 0;
+ virtual std::string getTimeUnitName(std::uint32_t value) = 0;
+ virtual void activate(std::uint32_t value) = 0;
+ };
+ };
+
+ class MeditationTimerPresenter : public MeditationTimerContract::Presenter
+ {
+ public:
+ MeditationTimerPresenter(app::ApplicationCommon *app, settings::Settings *settings);
+
+ std::uint32_t getMinValue() override;
+ std::uint32_t getMaxValue() override;
+ std::uint32_t getStepValue() override;
+ std::uint32_t getCurrentValue() override;
+ std::string getTimeUnitName(std::uint32_t value) override;
+ void activate(std::uint32_t value) override;
+
+ private:
+ app::ApplicationCommon *app = nullptr;
+ settings::Settings *settings = nullptr;
+ };
+} // namespace app::meditation
A products/BellHybrid/apps/application-bell-meditation-timer/presenter/ReadyGoingPresenter.cpp => products/BellHybrid/apps/application-bell-meditation-timer/presenter/ReadyGoingPresenter.cpp +16 -0
@@ 0,0 1,16 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "ApplicationBellMeditationTimer.hpp"
+#include "ReadyGoingPresenter.hpp"
+
+namespace app::meditation
+{
+ ReadyGoingPresenter::ReadyGoingPresenter(app::ApplicationCommon *app) : app{app}
+ {}
+
+ void ReadyGoingPresenter::activate()
+ {
+ app->switchWindow(gui::name::window::meditationProgress);
+ }
+} // namespace app::meditation
A products/BellHybrid/apps/application-bell-meditation-timer/presenter/ReadyGoingPresenter.hpp => products/BellHybrid/apps/application-bell-meditation-timer/presenter/ReadyGoingPresenter.hpp +39 -0
@@ 0,0 1,39 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <Application.hpp>
+#include <apps-common/BasePresenter.hpp>
+
+namespace app
+{
+ class ApplicationCommon;
+}
+
+namespace app::meditation
+{
+ class ReadyGoingPresenterContract
+ {
+ public:
+ class View
+ {
+ public:
+ virtual ~View() = default;
+ };
+ class Presenter : public BasePresenter<ReadyGoingPresenterContract::View>
+ {
+ public:
+ virtual void activate() = 0;
+ };
+ };
+
+ class ReadyGoingPresenter : public ReadyGoingPresenterContract::Presenter
+ {
+ app::ApplicationCommon *app{};
+ void activate() override;
+
+ public:
+ explicit ReadyGoingPresenter(app::ApplicationCommon *app);
+ };
+} // namespace app::meditation
A products/BellHybrid/apps/application-bell-meditation-timer/presenter/SessionEndedPresenter.cpp => products/BellHybrid/apps/application-bell-meditation-timer/presenter/SessionEndedPresenter.cpp +17 -0
@@ 0,0 1,17 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "SessionEndedPresenter.hpp"
+
+#include <service-appmgr/Controller.hpp>
+
+namespace app::meditation
+{
+ SessionEndedPresenter::SessionEndedPresenter(app::ApplicationCommon *app) : app{app}
+ {}
+
+ void SessionEndedPresenter::activate()
+ {
+ app::manager::Controller::sendAction(app, app::manager::actions::Home);
+ }
+} // namespace app::meditation
A products/BellHybrid/apps/application-bell-meditation-timer/presenter/SessionEndedPresenter.hpp => products/BellHybrid/apps/application-bell-meditation-timer/presenter/SessionEndedPresenter.hpp +39 -0
@@ 0,0 1,39 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <Application.hpp>
+#include <apps-common/BasePresenter.hpp>
+
+namespace app
+{
+ class ApplicationCommon;
+}
+
+namespace app::meditation
+{
+ class SessionEndedPresenterContract
+ {
+ public:
+ class View
+ {
+ public:
+ virtual ~View() = default;
+ };
+ class Presenter : public BasePresenter<SessionEndedPresenterContract::View>
+ {
+ public:
+ virtual void activate() = 0;
+ };
+ };
+
+ class SessionEndedPresenter : public SessionEndedPresenterContract::Presenter
+ {
+ app::ApplicationCommon *app{};
+ void activate() override;
+
+ public:
+ explicit SessionEndedPresenter(app::ApplicationCommon *app);
+ };
+} // namespace app::meditation
A products/BellHybrid/apps/application-bell-meditation-timer/windows/IntervalChimeWindow.cpp => products/BellHybrid/apps/application-bell-meditation-timer/windows/IntervalChimeWindow.cpp +83 -0
@@ 0,0 1,83 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "ApplicationBellMeditationTimer.hpp"
+#include "IntervalChimeWindow.hpp"
+#include "MeditationStyle.hpp"
+
+namespace gui
+{
+ IntervalChimeWindow::IntervalChimeWindow(
+ app::ApplicationCommon *app,
+ std::unique_ptr<app::meditation::IntervalChimeContract::Presenter> &&windowPresenter)
+ : AppWindow(app, gui::name::window::intervalChime), presenter{std::move(windowPresenter)}
+ {
+ presenter->attach(this);
+ buildInterface();
+ }
+
+ void IntervalChimeWindow::buildInterface()
+ {
+ AppWindow::buildInterface();
+
+ statusBar->setVisible(false);
+ header->setTitleVisibility(false);
+ navBar->setVisible(false);
+
+ body = new BellBaseLayout(this, 0, 0, style::window_width, style::window_height, true);
+
+ auto topMessage = new TextFixedSize(body->firstBox);
+ topMessage->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::outer_layouts_h);
+ topMessage->setFont(style::window::font::largelight);
+ topMessage->setEdges(gui::RectangleEdge::None);
+ topMessage->activeItem = false;
+ topMessage->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
+ topMessage->setText(utils::translate("app_bell_meditation_interval_chime"));
+ topMessage->drawUnderline(false);
+
+ auto titles = presenter->getIntervals();
+ spinner = new UTF8Spinner({titles.begin(), titles.end()}, Boundaries::Fixed);
+ spinner->onValueChanged = [this](const auto val) { this->onValueChanged(val); };
+ spinner->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::h);
+ spinner->setFont(app::meditationStyle::icStyle::text::font);
+ spinner->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
+ spinner->setFocusEdges(RectangleEdge::None);
+ body->getCenterBox()->addWidget(spinner);
+
+ auto currentValue = presenter->getCurrentInterval();
+ spinner->setCurrentValue(currentValue);
+ body->setMinMaxArrowsVisibility(currentValue == titles.front(), currentValue == titles.back());
+
+ bottomDescription = new Label(body->lastBox);
+ bottomDescription->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::outer_layouts_h);
+ bottomDescription->setFont(app::meditationStyle::icStyle::minute::font);
+ bottomDescription->setEdges(RectangleEdge::None);
+ bottomDescription->activeItem = false;
+ bottomDescription->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
+ bottomDescription->setText(presenter->getTimeUnitName(spinner->getCurrentValue()));
+
+ setFocusItem(spinner);
+ body->resize();
+ }
+
+ bool IntervalChimeWindow::onInput(const gui::InputEvent &inputEvent)
+ {
+ if (spinner->onInput(inputEvent)) {
+ return true;
+ }
+
+ if (inputEvent.isShortRelease(gui::KeyCode::KEY_ENTER)) {
+ presenter->activate(spinner->getCurrentValue());
+ return true;
+ }
+
+ return AppWindow::onInput(inputEvent);
+ }
+
+ void IntervalChimeWindow::onValueChanged(const std::string currentValue)
+ {
+ auto titles = presenter->getIntervals();
+ body->setMinMaxArrowsVisibility(currentValue == titles.front(), currentValue == titles.back());
+ bottomDescription->setText(presenter->getTimeUnitName(spinner->getCurrentValue()));
+ }
+} // namespace gui
A products/BellHybrid/apps/application-bell-meditation-timer/windows/IntervalChimeWindow.hpp => products/BellHybrid/apps/application-bell-meditation-timer/windows/IntervalChimeWindow.hpp +36 -0
@@ 0,0 1,36 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <apps-common/widgets/spinners/Spinners.hpp>
+#include <widgets/BellBaseLayout.hpp>
+
+#include <Application.hpp>
+#include <AppWindow.hpp>
+#include <InputEvent.hpp>
+
+#include "IntervalChimePresenter.hpp"
+
+namespace gui
+{
+ class IntervalChimeWindow : public AppWindow, public app::meditation::IntervalChimeContract::View
+ {
+ public:
+ explicit IntervalChimeWindow(
+ app::ApplicationCommon *app,
+ std::unique_ptr<app::meditation::IntervalChimeContract::Presenter> &&windowPresenter);
+
+ // virtual methods
+ void buildInterface() override;
+ bool onInput(const gui::InputEvent &inputEvent) override;
+
+ void onValueChanged(const std::string currentValue);
+
+ private:
+ std::unique_ptr<app::meditation::IntervalChimeContract::Presenter> presenter;
+ BellBaseLayout *body{};
+ UTF8Spinner *spinner{};
+ Label *bottomDescription{};
+ };
+} // namespace gui
A products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationRunningWindow.cpp => products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationRunningWindow.cpp +188 -0
@@ 0,0 1,188 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "ApplicationBellMeditationTimer.hpp"
+#include "MeditationRunningWindow.hpp"
+#include "MeditationStyle.hpp"
+
+#include <apps-common/widgets/BellBaseLayout.hpp>
+#include <apps-common/widgets/ProgressTimerWithBarGraphAndCounter.hpp>
+#include <purefs/filesystem_paths.hpp>
+#include <service-audio/AudioServiceAPI.hpp>
+
+namespace
+{
+ inline constexpr auto meditationProgressTimerName = "MeditationProgressTimer";
+ inline constexpr std::chrono::seconds baseTick{1};
+ inline constexpr auto meditationProgressMode = app::ProgressCountdownMode::Increasing;
+ inline constexpr auto meditationAudioPath = "assets/audio/bell/meditation/Meditation_Gong.mp3";
+
+ using namespace app::meditationStyle;
+
+ void decorateProgressItem(gui::Rect *item, gui::Alignment::Vertical alignment)
+ {
+ item->setEdges(gui::RectangleEdge::None);
+ item->activeItem = false;
+ item->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, alignment));
+ }
+
+ gui::Label *createTitle(gui::VBox *parent)
+ {
+ auto title = new gui::Label(parent, 0, 0, parent->getWidth(), parent->getHeight() / 2);
+ title->setText(utils::translate("app_bell_meditation_progress"));
+ title->setFont(mrStyle::title::font);
+ decorateProgressItem(title, gui::Alignment::Vertical::Top);
+ return title;
+ }
+
+ gui::HBarGraph *createProgress(gui::VBox *parent)
+ {
+ auto progressBox = new gui::HBox(parent, 0, 0, parent->getWidth(), parent->getHeight() / 2);
+ decorateProgressItem(progressBox, gui::Alignment::Vertical::Bottom);
+ auto progressBar =
+ new gui::HBarGraph(progressBox, 0, 0, mrStyle::progress::boxesCount, gui::BarGraphStyle::Heavy);
+ decorateProgressItem(progressBar, gui::Alignment::Vertical::Center);
+ return progressBar;
+ }
+
+ gui::Text *createTimer(gui::Item *parent)
+ {
+ auto timer = new gui::Text(parent,
+ 0,
+ 0,
+ style::bell_base_layout::w,
+ style::bell_base_layout::outer_layouts_h - mrStyle::timer::timerMarginBottom);
+ timer->setFont(mrStyle::timer::font);
+ timer->setMargins(gui::Margins(0, mrStyle::timer::timerMarginBottom, 0, 0));
+ decorateProgressItem(timer, gui::Alignment::Vertical::Top);
+ return timer;
+ }
+} // namespace
+
+namespace gui
+{
+ MeditationRunningWindow::MeditationRunningWindow(
+ app::ApplicationCommon *app,
+ std::unique_ptr<app::meditation::MeditationProgressContract::Presenter> &&windowPresenter)
+ : AppWindow(app, gui::name::window::meditationProgress), presenter{std::move(windowPresenter)}
+ {
+ presenter->attach(this);
+ buildInterface();
+ }
+
+ void MeditationRunningWindow::buildInterface()
+ {
+ AppWindow::buildInterface();
+
+ statusBar->setVisible(false);
+ header->setTitleVisibility(false);
+ navBar->setVisible(false);
+
+ buildLayout();
+ configureTimer();
+ }
+
+ void MeditationRunningWindow::buildLayout()
+ {
+ auto body = new gui::BellBaseLayout(this, 0, 0, style::bell_base_layout::w, style::bell_base_layout::h, false);
+ auto vBox =
+ new VBox(body->getCenterBox(), 0, 0, style::bell_base_layout::w, style::bell_base_layout::center_layout_h);
+
+ decorateProgressItem(vBox, gui::Alignment::Vertical::Top);
+ createTitle(vBox);
+ progress = createProgress(vBox);
+ timer = createTimer(body->lastBox);
+
+ time = new BellStatusClock(body->firstBox);
+ time->setMaximumSize(body->firstBox->getWidth(), body->firstBox->getHeight());
+ time->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
+ body->firstBox->resizeItems();
+
+ dimensionChangedCallback = [&](Item &, const BoundingBox &newDim) -> bool {
+ body->setArea({0, 0, newDim.w, newDim.h});
+ return true;
+ };
+ }
+
+ void MeditationRunningWindow::onBeforeShow(ShowMode mode, SwitchData *data)
+ {
+ AppWindow::onBeforeShow(mode, data);
+
+ if (mode == ShowMode::GUI_SHOW_INIT) {
+ playGong();
+ presenter->start();
+ }
+ else {
+ presenter->resume();
+ }
+ }
+
+ bool MeditationRunningWindow::onInput(const InputEvent &inputEvent)
+ {
+ if (inputEvent.isShortRelease(gui::KeyCode::KEY_ENTER)) {
+ presenter->pause();
+ return true;
+ }
+ if (inputEvent.isShortRelease(gui::KeyCode::KEY_RF)) {
+ presenter->abandon();
+ return true;
+ }
+
+ return AppWindow::onInput(inputEvent);
+ }
+
+ void MeditationRunningWindow::progressFinished()
+ {
+ endSession();
+ }
+
+ void MeditationRunningWindow::intervalReached()
+ {
+ intervalTimeout();
+ }
+
+ void MeditationRunningWindow::configureTimer()
+ {
+ auto progressTimer = std::make_unique<app::ProgressTimerWithBarGraphAndCounter>(
+ application, *this, meditationProgressTimerName, baseTick, meditationProgressMode);
+ progressTimer->attach(progress);
+ progressTimer->attach(timer);
+ presenter->setTimer(std::move(progressTimer));
+ }
+
+ void MeditationRunningWindow::setTime(std::time_t newTime)
+ {
+ time->setTime(newTime);
+ time->setTimeFormatSpinnerVisibility(true);
+ }
+
+ void MeditationRunningWindow::setTimeFormat(utils::time::Locale::TimeFormat fmt)
+ {
+ time->setTimeFormat(fmt);
+ }
+
+ bool MeditationRunningWindow::updateTime()
+ {
+ if (presenter != nullptr) {
+ presenter->handleUpdateTimeEvent();
+ }
+ return true;
+ }
+
+ void MeditationRunningWindow::intervalTimeout()
+ {
+ playGong();
+ }
+
+ void MeditationRunningWindow::endSession()
+ {
+ playGong();
+ presenter->finish();
+ }
+
+ void MeditationRunningWindow::playGong()
+ {
+ AudioServiceAPI::PlaybackStart(
+ application, audio::PlaybackType::Meditation, purefs::dir::getCurrentOSPath() / meditationAudioPath);
+ }
+} // namespace gui
A products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationRunningWindow.hpp => products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationRunningWindow.hpp +48 -0
@@ 0,0 1,48 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <Application.hpp>
+#include <AppWindow.hpp>
+#include <InputEvent.hpp>
+#include <Text.hpp>
+#include <apps-common/widgets/BarGraph.hpp>
+#include <common/widgets/BellStatusClock.hpp>
+
+#include "MeditationProgressPresenter.hpp"
+
+namespace gui
+{
+ class MeditationRunningWindow : public AppWindow, public app::meditation::MeditationProgressContract::View
+ {
+ public:
+ MeditationRunningWindow(
+ app::ApplicationCommon *app,
+ std::unique_ptr<app::meditation::MeditationProgressContract::Presenter> &&windowPresenter);
+
+ // virtual methods
+ void onBeforeShow(ShowMode mode, SwitchData *data) override;
+ bool onInput(const InputEvent &inputEvent) override;
+ void buildInterface() override;
+ void progressFinished() override;
+ void intervalReached() override;
+
+ private:
+ std::unique_ptr<app::meditation::MeditationProgressContract::Presenter> presenter;
+ gui::HBarGraph *progress = nullptr;
+ gui::Text *timer = nullptr;
+ gui::BellStatusClock *time = nullptr;
+
+ void setTime(std::time_t newTime) override;
+ void setTimeFormat(utils::time::Locale::TimeFormat fmt) override;
+ bool updateTime() override;
+
+ void buildLayout();
+ void configureTimer();
+
+ void endSession();
+ void intervalTimeout();
+ void playGong();
+ };
+} // namespace gui
A products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationTimerWindow.cpp => products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationTimerWindow.cpp +86 -0
@@ 0,0 1,86 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "ApplicationBellMeditationTimer.hpp"
+#include "MeditationStyle.hpp"
+#include "MeditationTimerWindow.hpp"
+
+namespace gui
+{
+ MeditationTimerWindow::MeditationTimerWindow(
+ app::ApplicationCommon *app,
+ std::unique_ptr<app::meditation::MeditationTimerContract::Presenter> &&windowPresenter)
+ : AppWindow(app, gui::name::window::meditationTimer), presenter{std::move(windowPresenter)}
+ {
+ presenter->attach(this);
+ buildInterface();
+ }
+
+ void MeditationTimerWindow::buildInterface()
+ {
+ AppWindow::buildInterface();
+
+ statusBar->setVisible(false);
+ header->setTitleVisibility(false);
+ navBar->setVisible(false);
+
+ body = new BellBaseLayout(this, 0, 0, style::window_width, style::window_height, true);
+
+ auto topMessage = new TextFixedSize(body->firstBox);
+ topMessage->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::outer_layouts_h);
+ topMessage->setFont(style::window::font::largelight);
+ topMessage->setEdges(gui::RectangleEdge::None);
+ topMessage->activeItem = false;
+ topMessage->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
+ topMessage->setText(utils::translate("app_bell_meditation_timer"));
+ topMessage->drawUnderline(false);
+
+ spinner = new UIntegerSpinner(
+ UIntegerSpinner ::Range{presenter->getMinValue(), presenter->getMaxValue(), presenter->getStepValue()},
+ Boundaries::Fixed);
+ spinner->onValueChanged = [this](const auto val) { this->onValueChanged(val); };
+ spinner->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::h);
+ spinner->setFont(app::meditationStyle::mtStyle::text::font);
+ spinner->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
+ spinner->setEdges(RectangleEdge::None);
+ spinner->setFocusEdges(RectangleEdge::None);
+ body->getCenterBox()->addWidget(spinner);
+
+ auto currentValue = presenter->getCurrentValue();
+ spinner->setCurrentValue(currentValue);
+ body->setMinMaxArrowsVisibility(currentValue == presenter->getMinValue(),
+ currentValue == presenter->getMaxValue());
+
+ bottomDescription = new Label(body->lastBox);
+ bottomDescription->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::outer_layouts_h);
+ bottomDescription->setFont(app::meditationStyle::mtStyle::minute::font);
+ bottomDescription->setEdges(RectangleEdge::None);
+ bottomDescription->activeItem = false;
+ bottomDescription->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
+ bottomDescription->setText(presenter->getTimeUnitName(spinner->getCurrentValue()));
+
+ setFocusItem(spinner);
+ body->resize();
+ }
+
+ bool MeditationTimerWindow::onInput(const gui::InputEvent &inputEvent)
+ {
+ if (spinner->onInput(inputEvent)) {
+ return true;
+ }
+
+ if (inputEvent.isShortRelease(gui::KeyCode::KEY_ENTER)) {
+ presenter->activate(spinner->getCurrentValue());
+ return true;
+ }
+
+ return AppWindow::onInput(inputEvent);
+ }
+
+ void MeditationTimerWindow::onValueChanged(const std::uint32_t currentValue)
+ {
+ body->setMinMaxArrowsVisibility(currentValue == presenter->getMinValue(),
+ currentValue == presenter->getMaxValue());
+ bottomDescription->setText(presenter->getTimeUnitName(spinner->getCurrentValue()));
+ }
+} // namespace gui
A products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationTimerWindow.hpp => products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationTimerWindow.hpp +36 -0
@@ 0,0 1,36 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <apps-common/widgets/spinners/Spinners.hpp>
+#include <widgets/BellBaseLayout.hpp>
+
+#include <Application.hpp>
+#include <AppWindow.hpp>
+#include <InputEvent.hpp>
+
+#include "MeditationTimerPresenter.hpp"
+
+namespace gui
+{
+ class MeditationTimerWindow : public AppWindow, public app::meditation::MeditationTimerContract::View
+ {
+ public:
+ explicit MeditationTimerWindow(
+ app::ApplicationCommon *app,
+ std::unique_ptr<app::meditation::MeditationTimerContract::Presenter> &&windowPresenter);
+
+ // virtual methods
+ void buildInterface() override;
+ bool onInput(const gui::InputEvent &inputEvent) override;
+
+ void onValueChanged(const std::uint32_t currentValue);
+
+ private:
+ std::unique_ptr<app::meditation::MeditationTimerContract::Presenter> presenter;
+ BellBaseLayout *body{};
+ UIntegerSpinner *spinner{};
+ Label *bottomDescription{};
+ };
+} // namespace gui
A products/BellHybrid/apps/application-bell-meditation-timer/windows/ReadyGoingWindow.cpp => products/BellHybrid/apps/application-bell-meditation-timer/windows/ReadyGoingWindow.cpp +51 -0
@@ 0,0 1,51 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "ApplicationBellMeditationTimer.hpp"
+#include "MeditationStyle.hpp"
+#include "ReadyGoingWindow.hpp"
+
+namespace
+{
+ constexpr inline auto defaultTimeout = std::chrono::seconds{5};
+}
+
+namespace gui
+{
+ ReadyGoingWindow::ReadyGoingWindow(
+ app::ApplicationCommon *app,
+ std::shared_ptr<app::meditation::ReadyGoingPresenterContract::Presenter> winPresenter)
+ : WindowWithTimer(app, gui::name::window::readyGoing, defaultTimeout), presenter{std::move(winPresenter)}
+ {
+ buildInterface();
+
+ timerCallback = [this](Item &, sys::Timer &) {
+ presenter->activate();
+ return true;
+ };
+ }
+
+ void ReadyGoingWindow::buildInterface()
+ {
+ WindowWithTimer::buildInterface();
+
+ statusBar->setVisible(false);
+ header->setTitleVisibility(false);
+ navBar->setVisible(false);
+
+ if (icon == nullptr) {
+ using namespace app::meditationStyle;
+ icon = new Icon(this, 0, 0, style::window_width, style::window_height, {}, {});
+ icon->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
+ icon->image->setMargins({0, itStyle::icon::imageTopMargin, 0, itStyle::icon::imageBottomMargin});
+ icon->image->set(app::meditationStyle::itStyle::icon::imageLogo, ImageTypeSpecifier::W_G);
+ icon->text->setFont(itStyle::text::font);
+ icon->text->setRichText(utils::translate("app_bell_meditation_put_down_and_wait"));
+ }
+ }
+
+ bool ReadyGoingWindow::onInput(const InputEvent &inputEvent)
+ {
+ return true;
+ }
+} // namespace gui
A products/BellHybrid/apps/application-bell-meditation-timer/windows/ReadyGoingWindow.hpp => products/BellHybrid/apps/application-bell-meditation-timer/windows/ReadyGoingWindow.hpp +29 -0
@@ 0,0 1,29 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "ReadyGoingPresenter.hpp"
+
+#include <apps-common/popups/WindowWithTimer.hpp>
+#include <gui/widgets/Icon.hpp>
+
+namespace gui
+{
+ class ReadyGoingWindow : public WindowWithTimer
+ {
+ private:
+ std::shared_ptr<app::meditation::ReadyGoingPresenterContract::Presenter> presenter;
+
+ public:
+ ReadyGoingWindow(app::ApplicationCommon *app,
+ std::shared_ptr<app::meditation::ReadyGoingPresenterContract::Presenter> winPresenter);
+
+ // virtual methods
+ void buildInterface() override;
+ bool onInput(const InputEvent &inputEvent) override;
+
+ private:
+ Icon *icon{};
+ };
+} // namespace gui
A products/BellHybrid/apps/application-bell-meditation-timer/windows/SessionEndWindow.cpp => products/BellHybrid/apps/application-bell-meditation-timer/windows/SessionEndWindow.cpp +32 -0
@@ 0,0 1,32 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "ApplicationBellMeditationTimer.hpp"
+#include "SessionEndWindow.hpp"
+
+namespace gui
+{
+ SessionEndWindow::SessionEndWindow(
+ app::ApplicationCommon *app,
+ std::shared_ptr<app::meditation::SessionEndedPresenterContract::Presenter> winPresenter)
+ : BellFinishedWindow(app, gui::name::window::sessionEnded), presenter{std::move(winPresenter)}
+ {
+ timerCallback = [this](Item &, sys::Timer &) {
+ presenter->activate();
+ return true;
+ };
+ }
+
+ bool SessionEndWindow::onInput(const InputEvent &inputEvent)
+ {
+ return true;
+ }
+
+ void SessionEndWindow::onBeforeShow(ShowMode mode, SwitchData *data)
+ {
+ BellFinishedWindow::onBeforeShow(mode, data);
+
+ icon->image->set("big_namaste", ImageTypeSpecifier::W_G);
+ icon->text->setRichText(utils::translate("app_bell_meditation_thank_you_for_session"));
+ }
+} // namespace gui
A products/BellHybrid/apps/application-bell-meditation-timer/windows/SessionEndWindow.hpp => products/BellHybrid/apps/application-bell-meditation-timer/windows/SessionEndWindow.hpp +26 -0
@@ 0,0 1,26 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "SessionEndedPresenter.hpp"
+
+#include <common/windows/BellFinishedWindow.hpp>
+#include <gui/widgets/Icon.hpp>
+
+namespace gui
+{
+ class SessionEndWindow : public BellFinishedWindow
+ {
+ private:
+ std::shared_ptr<app::meditation::SessionEndedPresenterContract::Presenter> presenter;
+
+ public:
+ SessionEndWindow(app::ApplicationCommon *app,
+ std::shared_ptr<app::meditation::SessionEndedPresenterContract::Presenter> winPresenter);
+
+ // virtual methods
+ bool onInput(const InputEvent &inputEvent) override;
+ void onBeforeShow(ShowMode mode, SwitchData *data) override;
+ };
+} // namespace gui
A products/BellHybrid/apps/application-bell-meditation-timer/windows/SessionPausedWindow.cpp => products/BellHybrid/apps/application-bell-meditation-timer/windows/SessionPausedWindow.cpp +45 -0
@@ 0,0 1,45 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "ApplicationBellMeditationTimer.hpp"
+#include "MeditationStyle.hpp"
+#include "SessionPausedWindow.hpp"
+
+namespace gui
+{
+ SessionPausedWindow::SessionPausedWindow(app::ApplicationCommon *app)
+ : AppWindow(app, gui::name::window::sessionPaused)
+ {
+ buildInterface();
+ }
+
+ bool SessionPausedWindow::onInput(const gui::InputEvent &inputEvent)
+ {
+ if (inputEvent.isShortRelease(gui::KeyCode::KEY_RF) || inputEvent.isShortRelease(gui::KeyCode::KEY_ENTER)) {
+ application->returnToPreviousWindow();
+ return true;
+ }
+
+ return AppWindow::onInput(inputEvent);
+ }
+
+ void SessionPausedWindow::buildInterface()
+ {
+ AppWindow::buildInterface();
+
+ statusBar->setVisible(false);
+ header->setTitleVisibility(false);
+ navBar->setVisible(false);
+
+ if (icon == nullptr) {
+ using namespace app::meditationStyle;
+
+ icon = new Icon(this, 0, 0, style::window_width, style::window_height, {}, {});
+ icon->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
+ icon->image->setMargins({0, itStyle::icon::imageTopMargin, 0, itStyle::icon::imageBottomMargin});
+ icon->image->set(app::meditationStyle::itStyle::icon::imagePause, ImageTypeSpecifier::W_G);
+ icon->text->setFont(itStyle::text::font);
+ icon->text->setRichText(utils::translate("app_bell_meditation_paused"));
+ }
+ }
+} // namespace gui
A products/BellHybrid/apps/application-bell-meditation-timer/windows/SessionPausedWindow.hpp => products/BellHybrid/apps/application-bell-meditation-timer/windows/SessionPausedWindow.hpp +25 -0
@@ 0,0 1,25 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <gui/widgets/Icon.hpp>
+#include <Application.hpp>
+#include <AppWindow.hpp>
+#include <InputEvent.hpp>
+
+namespace gui
+{
+ class SessionPausedWindow : public AppWindow
+ {
+ public:
+ SessionPausedWindow(app::ApplicationCommon *app);
+
+ // virtual methods
+ void buildInterface() override;
+ bool onInput(const gui::InputEvent &inputEvent) override;
+
+ private:
+ Icon *icon{};
+ };
+} // namespace gui