~aleteoryx/muditaos

a2779d90b5fad7f42990549436b374dbf8bdb8d3 — Dawid Wojtas 3 years ago d6fbf63
[BH-1594] Add shortcuts instruction

Shortcuts instruction is a new functionality
during the Onboarding process. It shows hints
on how to use buttons.
30 files changed, 585 insertions(+), 32 deletions(-)

A art/bell/shortcuts_step_bedside_lamp_W_G.png
A art/bell/shortcuts_step_deep_press_W_G.png
A art/bell/shortcuts_step_home_and_battery_W_G.png
A art/bell/shortcuts_step_light_click_W_G.png
A art/bell/shortcuts_step_restart_W_G.png
A art/bell/shortcuts_step_rotate_W_G.png
A art/bell/shortcuts_step_turn_off_W_G.png
M harmony_changelog.md
M image/assets/lang/English.json
M module-apps/apps-common/widgets/BellBaseLayout.hpp
M products/BellHybrid/CMakeLists.txt
M products/BellHybrid/apps/application-bell-onboarding/ApplicationBellOnBoarding.cpp
M products/BellHybrid/apps/application-bell-onboarding/CMakeLists.txt
M products/BellHybrid/apps/application-bell-onboarding/include/application-bell-onboarding/BellOnBoardingNames.hpp
A products/BellHybrid/apps/application-bell-onboarding/layouts/OnBoardingShortcutsLayoutClassic.cpp
A products/BellHybrid/apps/application-bell-onboarding/layouts/OnBoardingShortcutsLayoutClassic.hpp
A products/BellHybrid/apps/application-bell-onboarding/layouts/OnBoardingShortcutsLayoutProvider.hpp
A products/BellHybrid/apps/application-bell-onboarding/layouts/OnBoardingShortcutsLayouts.cpp
A products/BellHybrid/apps/application-bell-onboarding/layouts/OnBoardingShortcutsLayouts.hpp
A products/BellHybrid/apps/application-bell-onboarding/presenter/OnBoardingShortcutsWindowPresenter.cpp
A products/BellHybrid/apps/application-bell-onboarding/presenter/OnBoardingShortcutsWindowPresenter.hpp
M products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingSettingsWindow.cpp
A products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingShortcutsOptionWindow.cpp
A products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingShortcutsOptionWindow.hpp
A products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingShortcutsWindow.cpp
A products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingShortcutsWindow.hpp
M products/BellHybrid/apps/application-bell-settings/include/application-bell-settings/windows/BellSettingsTimeUnitsWindow.hpp
M products/BellHybrid/apps/application-bell-settings/windows/BellSettingsTimeUnitsWindow.cpp
M products/BellHybrid/apps/common/src/options/BellShortOptionWindow.cpp
M products/BellHybrid/assets/assets_common.json
A art/bell/shortcuts_step_bedside_lamp_W_G.png => art/bell/shortcuts_step_bedside_lamp_W_G.png +0 -0
A art/bell/shortcuts_step_deep_press_W_G.png => art/bell/shortcuts_step_deep_press_W_G.png +0 -0
A art/bell/shortcuts_step_home_and_battery_W_G.png => art/bell/shortcuts_step_home_and_battery_W_G.png +0 -0
A art/bell/shortcuts_step_light_click_W_G.png => art/bell/shortcuts_step_light_click_W_G.png +0 -0
A art/bell/shortcuts_step_restart_W_G.png => art/bell/shortcuts_step_restart_W_G.png +0 -0
A art/bell/shortcuts_step_rotate_W_G.png => art/bell/shortcuts_step_rotate_W_G.png +0 -0
A art/bell/shortcuts_step_turn_off_W_G.png => art/bell/shortcuts_step_turn_off_W_G.png +0 -0
M harmony_changelog.md => harmony_changelog.md +3 -0
@@ 13,6 13,9 @@
#### UI/UX:
* Improve refreshing of the display.

#### Onboarding
* Shortcuts instruction

### Fixed

## [1.7.0 2022-11-14]

M image/assets/lang/English.json => image/assets/lang/English.json +11 -0
@@ 639,6 639,17 @@
  "app_bell_onboarding_info_deep_click_warning": "<text weight='light' size='38'>You've </text><text weight='regular' size='38'>deep pressed</text>",
  "app_bell_onboarding_info_deep_click_correction": "<text weight='light' size='38'>Be more gentle,<br></br>try </text><text weight='regular' size='38'>light click </text><text weight='light' size='38'>this time</text>",
  "app_bell_onboarding_welcome": "Welcome",
  "app_bell_onboarding_shortcuts_question": "Do you want to see Shortcuts instruction?",
  "app_bell_onboarding_shortcuts_start": "Start",
  "app_bell_onboarding_shortcuts_skip": "Skip",
  "app_bell_onboarding_shortcuts_step_rotate": "Rotate to select",
  "app_bell_onboarding_shortcuts_step_light_click": "Light click to accept and move forward",
  "app_bell_onboarding_shortcuts_step_deep_press": "Deep press to active or deactivate the alarm",
  "app_bell_onboarding_shortcuts_step_home": "Long press back (2s) to return to the home view",
  "app_bell_onboarding_shortcuts_step_battery": "Long press back (2s) on the home view to see status battery",
  "app_bell_onboarding_shortcuts_step_turn_off": "Press back for 10s to turn off the device",
  "app_bell_onboarding_shortcuts_step_restart": "Press both side buttons for 10s to restart the device",
  "app_bell_onboarding_shortcuts_step_bedside_lamp": "Long press frontlight (2s) to turn on a bedside lamp",
  "app_bell_settings_advanced": "Advanced",
  "app_bell_settings_time_units": "Time",
  "app_bell_settings_temp_scale": "Temperature scale",

M module-apps/apps-common/widgets/BellBaseLayout.hpp => module-apps/apps-common/widgets/BellBaseLayout.hpp +3 -3
@@ 11,9 11,9 @@ namespace style::bell_base_layout
    constexpr inline auto w                   = style::window_width;
    constexpr inline auto h                   = style::window_height;
    constexpr inline auto first_layout_min_h  = 30U;
    constexpr inline auto outer_layouts_w     = 390U;
    constexpr inline auto outer_layouts_h     = 100U;
    constexpr inline auto outer_layout_margin = 40U;
    constexpr inline auto outer_layouts_w     = 448U;
    constexpr inline auto outer_layouts_h     = 102U;
    constexpr inline auto outer_layout_margin = 38U;
    constexpr inline auto center_layout_w     = 504U;
    constexpr inline auto center_layout_h     = h - 2 * outer_layout_margin - 2 * outer_layouts_h;


M products/BellHybrid/CMakeLists.txt => products/BellHybrid/CMakeLists.txt +2 -2
@@ 115,14 115,14 @@ download_asset_release_json(json-common-target
                            ${CMAKE_CURRENT_SOURCE_DIR}/assets/assets_common.json
                            ${CMAKE_BINARY_DIR}/sysroot/sys/current/
                            MuditaOSPublicAssets
                            0.0.12
                            0.0.13
                            ${MUDITA_CACHE_DIR}
    )
download_asset_release_json(json-community-target
                            ${CMAKE_CURRENT_SOURCE_DIR}/assets/assets_community.json
                            ${CMAKE_BINARY_DIR}/sysroot/sys/current/
                            MuditaOSPublicAssets
                            0.0.12
                            0.0.13
                            ${MUDITA_CACHE_DIR}
    )
download_asset_json(json-rt1051-target

M products/BellHybrid/apps/application-bell-onboarding/ApplicationBellOnBoarding.cpp => products/BellHybrid/apps/application-bell-onboarding/ApplicationBellOnBoarding.cpp +34 -19
@@ 4,12 4,15 @@
#include "ApplicationBellOnBoarding.hpp"

#include <presenter/OnBoardingLanguageWindowPresenter.hpp>
#include <presenter/OnBoardingShortcutsWindowPresenter.hpp>
#include <windows/OnBoardingLanguageWindow.hpp>
#include <windows/OnBoardingFinalizeWindow.hpp>
#include <windows/OnBoardingOnOffWindow.hpp>
#include <windows/OnBoardingSettingsWindow.hpp>
#include <windows/OnBoardingWelcomeWindow.hpp>
#include <windows/OnBoardingInstructionPromptWindow.hpp>
#include <windows/OnBoardingShortcutsOptionWindow.hpp>
#include <windows/OnBoardingShortcutsWindow.hpp>

#include <service-appmgr/Constants.hpp>
#include <service-appmgr/messages/GetCurrentDisplayLanguageResponse.hpp>


@@ 45,7 48,7 @@ namespace app

        connect(typeid(manager::GetCurrentDisplayLanguageResponse), [&](sys::Message *msg) {
            if (gui::window::name::onBoardingLanguageWindow == getCurrentWindow()->getName()) {
                switchWindow(gui::window::name::onBoardingSettingsWindow);
                switchWindow(gui::window::name::onBoardingShortcutsOptionWindow);
                return sys::msgHandled();
            }
            return sys::msgNotHandled();


@@ 74,6 77,17 @@ namespace app
                return std::make_unique<gui::OnBoardingLanguageWindow>(app, std::move(presenter), name);
            });

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

        windowsFactory.attach(
            gui::window::name::onBoardingShortcutsWindow, [this](ApplicationCommon *app, const std::string &name) {
                auto presenter = std::make_unique<OnBoarding::OnBoardingShortcutsWindowPresenter>(this);
                return std::make_unique<gui::OnBoardingShortcutsWindow>(app, std::move(presenter), name);
            });

        windowsFactory.attach(
            gui::window::name::onBoardingSettingsWindow, [this](ApplicationCommon *app, const std::string &name) {
                auto layoutModel          = std::make_unique<bell_settings::LayoutModel>(this);


@@ 234,24 248,26 @@ namespace app
            if (inputEvent.isKeyRelease(gui::KeyCode::KEY_UP) || inputEvent.isKeyRelease(gui::KeyCode::KEY_DOWN)) {
                informationState = OnBoarding::InformationStates::LightClickInfo;
            }
            else if (inputEvent.isKeyRelease(gui::KeyCode::KEY_RIGHT) ||
                     inputEvent.isKeyRelease(gui::KeyCode::KEY_LEFT)) {
                informationState = OnBoarding::InformationStates::DeepClickWarningInfo;
                if (getCurrentWindow()->getName() == gui::window::name::informationOnBoardingWindow) {
                    displayInformation(*getPreviousWindow());
                }
                else {
                    displayInformation(getCurrentWindow()->getName());
                }
            }
            else if (inputEvent.isKeyRelease(gui::KeyCode::KEY_ENTER)) {
                if (informationState == OnBoarding::InformationStates::DeepClickWarningInfo) {
                    informationPromptTimer.stop();
                    informationState = OnBoarding::InformationStates::DeepClickCorrectionInfo;
                    displayInformation(*getPreviousWindow());
            else if (getCurrentWindow()->getName() != gui::window::name::onBoardingShortcutsWindow) {
                if (inputEvent.isKeyRelease(gui::KeyCode::KEY_RIGHT) ||
                    inputEvent.isKeyRelease(gui::KeyCode::KEY_LEFT)) {
                    informationState = OnBoarding::InformationStates::DeepClickWarningInfo;
                    if (getCurrentWindow()->getName() == gui::window::name::informationOnBoardingWindow) {
                        displayInformation(*getPreviousWindow());
                    }
                    else {
                        displayInformation(getCurrentWindow()->getName());
                    }
                }
                else {
                    informationState = OnBoarding::InformationStates::RotateInfo;
                else if (inputEvent.isKeyRelease(gui::KeyCode::KEY_ENTER)) {
                    if (informationState == OnBoarding::InformationStates::DeepClickWarningInfo) {
                        informationPromptTimer.stop();
                        informationState = OnBoarding::InformationStates::DeepClickCorrectionInfo;
                        displayInformation(*getPreviousWindow());
                    }
                    else {
                        informationState = OnBoarding::InformationStates::RotateInfo;
                    }
                }
            }
        }


@@ 283,7 299,6 @@ namespace app
                }
            }
        }

        return false;
    }


M products/BellHybrid/apps/application-bell-onboarding/CMakeLists.txt => products/BellHybrid/apps/application-bell-onboarding/CMakeLists.txt +12 -0
@@ 19,16 19,27 @@ target_sources(application-bell-onboarding
        windows/OnBoardingOnOffWindow.cpp
        windows/OnBoardingInstructionPromptWindow.cpp
        windows/OnBoardingWelcomeWindow.cpp
        windows/OnBoardingShortcutsOptionWindow.cpp
        windows/OnBoardingShortcutsWindow.cpp
        presenter/OnBoardingLanguageWindowPresenter.cpp
        presenter/OnBoardingFinalizeWindowPresenter.cpp
        presenter/OnBoardingShortcutsWindowPresenter.cpp
        layouts/OnBoardingShortcutsLayouts.cpp
        layouts/OnBoardingShortcutsLayoutClassic.cpp

        presenter/OnBoardingLanguageWindowPresenter.hpp
        presenter/OnBoardingFinalizeWindowPresenter.hpp
        presenter/OnBoardingShortcutsWindowPresenter.hpp
        windows/OnBoardingLanguageWindow.hpp
        windows/OnBoardingOnOffWindow.hpp
        windows/OnBoardingSettingsWindow.hpp
        windows/OnBoardingInstructionPromptWindow.hpp
        windows/OnBoardingWelcomeWindow.hpp
        windows/OnBoardingShortcutsOptionWindow.hpp
        windows/OnBoardingShortcutsWindow.hpp
        layouts/OnBoardingShortcutsLayouts.hpp
        layouts/OnBoardingShortcutsLayoutProvider.hpp
        layouts/OnBoardingShortcutsLayoutClassic.hpp

    PUBLIC
        include/application-bell-onboarding/ApplicationBellOnBoarding.hpp


@@ 38,6 49,7 @@ target_link_libraries(application-bell-onboarding
    PRIVATE
        app
        apps-common
        bell::keymap
        bell::app-settings

    PUBLIC

M products/BellHybrid/apps/application-bell-onboarding/include/application-bell-onboarding/BellOnBoardingNames.hpp => products/BellHybrid/apps/application-bell-onboarding/include/application-bell-onboarding/BellOnBoardingNames.hpp +7 -5
@@ 10,10 10,12 @@ namespace app

namespace gui::window::name
{
    inline constexpr auto onBoardingOnOffWindow       = "BellOnBoardingOnOff";
    inline constexpr auto onBoardingLanguageWindow    = "BellOnBoardingLanguage";
    inline constexpr auto onBoardingSettingsWindow    = "BellOnBoardingSettings";
    inline constexpr auto finalizeOnBoardingWindow    = "BellOnBoardingFinalize";
    inline constexpr auto informationOnBoardingWindow = "BellOnBoardingInformation";
    inline constexpr auto onBoardingOnOffWindow           = "BellOnBoardingOnOff";
    inline constexpr auto onBoardingLanguageWindow        = "BellOnBoardingLanguage";
    inline constexpr auto onBoardingShortcutsOptionWindow = "BellOnBoardingShortcutsOption";
    inline constexpr auto onBoardingShortcutsWindow       = "BellOnBoardingShortcuts";
    inline constexpr auto onBoardingSettingsWindow        = "BellOnBoardingSettings";
    inline constexpr auto finalizeOnBoardingWindow        = "BellOnBoardingFinalize";
    inline constexpr auto informationOnBoardingWindow     = "BellOnBoardingInformation";

} // namespace gui::window::name

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

#include "OnBoardingShortcutsLayoutClassic.hpp"
#include <apps-common/widgets/BellBaseLayout.hpp>
#include <i18n/i18n.hpp>
#include <Style.hpp>
#include <ImageBox.hpp>
#include <TextFixedSize.hpp>

namespace
{
    namespace container
    {
        constexpr inline auto width      = 544U;
        constexpr inline auto height     = 220U;
        constexpr inline auto top_margin = 74U;

        namespace separator
        {
            constexpr inline auto height = 22U;
        } // namespace separator

        namespace image
        {
            constexpr inline auto height = container::height - separator::height;
            constexpr inline auto width  = 448U;
        } // namespace image

        namespace text
        {
            constexpr inline auto height = 146U;
            constexpr inline auto width  = 448U;
        } // namespace text

    } // namespace container
} // namespace

namespace gui
{
    OnBoardingShortcutsLayoutClassic::OnBoardingShortcutsLayoutClassic(const UTF8 &image,
                                                                       const UTF8 &description,
                                                                       bool leftArrowVisible,
                                                                       bool rightArrowVisible)
        : OnBoardingShortcutsLayoutProvider(image, description),
          VBox(nullptr, 0, 0, style::bell_base_layout::w, style::bell_base_layout::h), image{image},
          description{description}, leftArrowVisible{leftArrowVisible}, rightArrowVisible{rightArrowVisible}
    {
        buildInterface();
    }

    void OnBoardingShortcutsLayoutClassic::buildInterface()
    {
        setAlignment(Alignment::Horizontal::Center);

        auto containerThreeBox = new HThreeBox<HBox, HBox, HBox>(this);
        containerThreeBox->setMinimumSize(container::width, container::image::height);
        containerThreeBox->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Bottom));
        containerThreeBox->setMargins(Margins(0, container::top_margin, 0, 0));
        containerThreeBox->setEdges(RectangleEdge::None);

        containerThreeBox->firstBox = new HBox(containerThreeBox);
        containerThreeBox->firstBox->setAlignment(Alignment(Alignment::Vertical::Top));
        containerThreeBox->firstBox->setEdges(RectangleEdge::None);
        containerThreeBox->firstBox->activeItem = false;

        auto leftArrowBox = new ImageBox(containerThreeBox->firstBox, new Image("bell_arrow_left_W_M"));
        leftArrowBox->setAlignment(Alignment(Alignment::Horizontal::Left, Alignment::Vertical::Bottom));
        leftArrowBox->setMinimumSizeToFitImage();
        leftArrowBox->setVisible(leftArrowVisible);
        leftArrowBox->setEdges(RectangleEdge::None);
        containerThreeBox->firstBox->setMinimumSize(leftArrowBox->widgetMinimumArea.w,
                                                    leftArrowBox->widgetMinimumArea.h);

        containerThreeBox->centerBox = new HBox(containerThreeBox);
        containerThreeBox->centerBox->setEdges(RectangleEdge::None);
        containerThreeBox->centerBox->setAlignment(
            Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Bottom));
        containerThreeBox->centerBox->setMaximumSize(container::image::width, container::image::height);

        auto imageBox = new ImageBox(containerThreeBox->centerBox, new Image(image, ImageTypeSpecifier::W_G));
        imageBox->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Bottom));
        imageBox->setMinimumSizeToFitImage();
        imageBox->setVisible(true);

        containerThreeBox->lastBox = new HBox(containerThreeBox);
        containerThreeBox->lastBox->setAlignment(Alignment(Alignment::Vertical::Bottom));
        containerThreeBox->lastBox->setEdges(RectangleEdge::None);
        containerThreeBox->lastBox->activeItem = false;

        auto rightArrowBox = new ImageBox(containerThreeBox->lastBox, new Image("bell_arrow_right_W_M"));
        rightArrowBox->setAlignment(Alignment(Alignment::Horizontal::Left, Alignment::Vertical::Bottom));
        rightArrowBox->setMinimumSizeToFitImage();
        rightArrowBox->setVisible(rightArrowVisible);
        rightArrowBox->setEdges(RectangleEdge::None);
        containerThreeBox->lastBox->setMinimumSize(rightArrowBox->widgetMinimumArea.w,
                                                   rightArrowBox->widgetMinimumArea.h);

        auto containerSeparator = new VBox(this, 0, 0, container::width, container::separator::height);
        containerSeparator->setAlignment(Alignment(gui::Alignment::Horizontal::Center));
        containerSeparator->setEdges(RectangleEdge::None);
        containerSeparator->activeItem = false;

        auto containerText = new VBox(this, 0, 0, container::text::width, container::text::height);
        containerText->setAlignment(Alignment(gui::Alignment::Horizontal::Center));
        containerText->setEdges(RectangleEdge::None);
        containerText->activeItem = false;

        auto textBox = new Text(containerText, 0, 0, 0, 0);
        textBox->setMinimumSize(container::text::width, container::text::height);
        textBox->setAlignment(Alignment::Horizontal::Center);
        textBox->setTextType(TextType::MultiLine);
        textBox->setEditMode(EditMode::Browse);
        textBox->setFont(style::window::font::verybiglight);
        textBox->setRichText(utils::translate(description));

        this->resizeItems();
    }

    auto OnBoardingShortcutsLayoutClassic::getLayout() -> Item *
    {
        return this;
    }
}; // namespace gui

A products/BellHybrid/apps/application-bell-onboarding/layouts/OnBoardingShortcutsLayoutClassic.hpp => products/BellHybrid/apps/application-bell-onboarding/layouts/OnBoardingShortcutsLayoutClassic.hpp +33 -0
@@ 0,0 1,33 @@
// 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 "OnBoardingShortcutsLayoutProvider.hpp"

#include <BoxLayout.hpp>

namespace gui
{
    class BellBaseLayout;

    class OnBoardingShortcutsLayoutClassic : public OnBoardingShortcutsLayoutProvider, VBox
    {
      private:
        const UTF8 image;
        const UTF8 description;

        const bool leftArrowVisible;
        const bool rightArrowVisible;

        void buildInterface();

      public:
        OnBoardingShortcutsLayoutClassic(const UTF8 &image,
                                         const UTF8 &description,
                                         bool leftArrowVisible  = true,
                                         bool rightArrowVisible = true);

        auto getLayout() -> Item * override;
    };
}; // namespace gui

A products/BellHybrid/apps/application-bell-onboarding/layouts/OnBoardingShortcutsLayoutProvider.hpp => products/BellHybrid/apps/application-bell-onboarding/layouts/OnBoardingShortcutsLayoutProvider.hpp +30 -0
@@ 0,0 1,30 @@
// 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 <utf8/UTF8.hpp>

namespace gui
{
    class Item;

    class OnBoardingShortcutsLayoutProvider
    {
      private:
        const UTF8 image;
        const UTF8 description;
        const bool leftArrow;
        const bool rightArrow;

      public:
        OnBoardingShortcutsLayoutProvider(const UTF8 &image,
                                          const UTF8 &description,
                                          bool leftArrow  = true,
                                          bool rightArrow = true)
            : image{image}, description{description}, leftArrow{leftArrow}, rightArrow{rightArrow} {};
        virtual ~OnBoardingShortcutsLayoutProvider() noexcept = default;

        virtual Item *getLayout() = 0;
    };
}; // namespace gui

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

#include "OnBoardingShortcutsLayouts.hpp"
#include "OnBoardingShortcutsLayoutClassic.hpp"

namespace gui::factory
{
    std::vector<LayoutGenerator> getLayouts()
    {
        return {{[]() {
                    return new OnBoardingShortcutsLayoutClassic(
                        "shortcuts_step_rotate", "app_bell_onboarding_shortcuts_step_rotate", false, true);
                }},
                {[]() {
                    return new OnBoardingShortcutsLayoutClassic("shortcuts_step_light_click",
                                                                "app_bell_onboarding_shortcuts_step_light_click");
                }},
                {[]() {
                    return new OnBoardingShortcutsLayoutClassic("shortcuts_step_deep_press",
                                                                "app_bell_onboarding_shortcuts_step_deep_press");
                }},
                {[]() {
                    return new OnBoardingShortcutsLayoutClassic("shortcuts_step_home_and_battery",
                                                                "app_bell_onboarding_shortcuts_step_home");
                }},
                {[]() {
                    return new OnBoardingShortcutsLayoutClassic("shortcuts_step_home_and_battery",
                                                                "app_bell_onboarding_shortcuts_step_battery");
                }},
                {[]() {
                    return new OnBoardingShortcutsLayoutClassic("shortcuts_step_turn_off",
                                                                "app_bell_onboarding_shortcuts_step_turn_off");
                }},
                {[]() {
                    return new OnBoardingShortcutsLayoutClassic("shortcuts_step_restart",
                                                                "app_bell_onboarding_shortcuts_step_restart");
                }},
                {[]() {
                    return new OnBoardingShortcutsLayoutClassic(
                        "shortcuts_step_bedside_lamp", "app_bell_onboarding_shortcuts_step_bedside_lamp", true, false);
                }}};
    }
} // namespace gui::factory

A products/BellHybrid/apps/application-bell-onboarding/layouts/OnBoardingShortcutsLayouts.hpp => products/BellHybrid/apps/application-bell-onboarding/layouts/OnBoardingShortcutsLayouts.hpp +19 -0
@@ 0,0 1,19 @@
// 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 <functional>
#include <map>
#include <string>

namespace gui
{
    class OnBoardingShortcutsLayoutProvider;
    using LayoutGenerator = std::function<OnBoardingShortcutsLayoutProvider *()>;

    namespace factory
    {
        std::vector<LayoutGenerator> getLayouts();
    } // namespace factory
};    // namespace gui

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

#include "OnBoardingShortcutsWindowPresenter.hpp"
#include "layouts/OnBoardingShortcutsLayoutProvider.hpp"

namespace app::OnBoarding
{
    OnBoardingShortcutsWindowPresenter::OnBoardingShortcutsWindowPresenter(app::ApplicationCommon *app)
    {
        initLayoutOptions();
    }

    std::vector<gui::Item *> OnBoardingShortcutsWindowPresenter::getLayouts() const
    {
        return layoutOptions;
    }

    gui::Item *OnBoardingShortcutsWindowPresenter::getFirstLayout() const
    {
        return layoutOptions.front();
    }

    bool OnBoardingShortcutsWindowPresenter::isLastLayout(const gui::Item *layout) const
    {
        return layoutOptions.back() == layout;
    }

    void OnBoardingShortcutsWindowPresenter::initLayoutOptions()
    {
        auto layoutsList = gui::factory::getLayouts();

        for (auto &layoutEntry : layoutsList) {
            layoutOptions.push_back(layoutEntry()->getLayout());
        }
    }
} // namespace app::OnBoarding

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

#pragma once

#include <apps-common/BasePresenter.hpp>
#include <apps-common/ApplicationCommon.hpp>
#include <layouts/OnBoardingShortcutsLayouts.hpp>

#include <vector>
#include <string>
#include <Item.hpp>

namespace app::OnBoarding
{
    class OnBoardingShortcutsWindowContract
    {
      public:
        class View
        {
          public:
            virtual ~View() = default;
        };

        class Presenter : public BasePresenter<OnBoardingShortcutsWindowContract::View>
        {
          public:
            virtual std::vector<gui::Item *> getLayouts() const      = 0;
            virtual bool isLastLayout(const gui::Item *layout) const = 0;
            virtual gui::Item *getFirstLayout() const                = 0;
        };
    };

    class OnBoardingShortcutsWindowPresenter : public OnBoardingShortcutsWindowContract::Presenter
    {
      private:
        std::vector<gui::Item *> layoutOptions;
        void initLayoutOptions();

      public:
        explicit OnBoardingShortcutsWindowPresenter(app::ApplicationCommon *app);

        std::vector<gui::Item *> getLayouts() const override;
        bool isLastLayout(const gui::Item *layout) const override;
        gui::Item *getFirstLayout() const override;
    };
} // namespace app::OnBoarding

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

#include "OnBoardingSettingsWindow.hpp"


@@ 13,5 13,6 @@ namespace gui
        : BellSettingsTimeUnitsWindow(app, std::move(windowPresenter), name)
    {
        finishedCallback = [this]() { application->switchWindow(window::name::finalizeOnBoardingWindow); };
        returnCallback   = [this]() { application->switchWindow(window::name::onBoardingShortcutsOptionWindow); };
    }
} // namespace gui

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

#include "OnBoardingShortcutsOptionWindow.hpp"
#include "BellOnBoardingNames.hpp"

#include <apps-common/ApplicationCommon.hpp>
#include <i18n/i18n.hpp>
#include <common/options/OptionBellMenu.hpp>

namespace gui
{
    OnBoardingShortcutsOptionWindow::OnBoardingShortcutsOptionWindow(app::ApplicationCommon *app,
                                                                     const std::string &name)
        : BellShortOptionWindow(app, name), startString{utils::translate("app_bell_onboarding_shortcuts_start")},
          skipString{utils::translate("app_bell_onboarding_shortcuts_skip")}
    {
        addOptions(settingsOptionsList());
        setListTitle(utils::translate("app_bell_onboarding_shortcuts_question"));
    }

    std::list<Option> OnBoardingShortcutsOptionWindow::settingsOptionsList()
    {
        std::list<gui::Option> settingsOptionList;
        auto addWinSettings = [&](const UTF8 &name, std::function<bool(Item &)> activatedCallback) {
            settingsOptionList.emplace_back(std::make_unique<gui::option::OptionBellMenu>(
                name, activatedCallback, [=](gui::Item &) { return true; }, this));
        };

        addWinSettings(startString, [this](auto &) {
            getApplication()->switchWindow(gui::window::name::onBoardingShortcutsWindow);
            return true;
        });
        addWinSettings(skipString, [this](auto &) {
            getApplication()->switchWindow(gui::window::name::onBoardingSettingsWindow);
            return true;
        });

        return settingsOptionList;
    }
} /* namespace gui */

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

#pragma once

#include <common/options/BellShortOptionWindow.hpp>
#include <apps-common/ApplicationCommon.hpp>

namespace gui
{
    class OnBoardingShortcutsOptionWindow : public BellShortOptionWindow
    {
      public:
        explicit OnBoardingShortcutsOptionWindow(app::ApplicationCommon *app, const std::string &name);

      private:
        std::list<Option> settingsOptionsList();

        const UTF8 startString;
        const UTF8 skipString;
    };
} /* namespace gui */

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

#include "OnBoardingShortcutsWindow.hpp"
#include "BellOnBoardingNames.hpp"

#include <Style.hpp>
#include <SideListView.hpp>
#include <gui/input/InputEvent.hpp>
#include <keymap/KeyMap.hpp>

namespace gui
{
    OnBoardingShortcutsWindow::OnBoardingShortcutsWindow(
        app::ApplicationCommon *app,
        std::unique_ptr<app::OnBoarding::OnBoardingShortcutsWindowContract::Presenter> &&presenter,
        const std::string &name)
        : AppWindow(app, name), presenter{std::move(presenter)}
    {
        this->presenter->attach(this);
        buildInterface();
    }

    void OnBoardingShortcutsWindow::buildInterface()
    {
        AppWindow::buildInterface();

        statusBar->setVisible(false);
        header->setTitleVisibility(false);
        navBar->setVisible(false);

        auto layouts = presenter->getLayouts();
        spinner      = new WidgetSpinner(this, {layouts.begin(), layouts.end()}, Boundaries::Fixed);
        spinner->setSize(style::window_width, style::window_height);
        spinner->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Center));
        spinner->setFocusEdges(RectangleEdge::None);
        auto selectedLayout = presenter->getFirstLayout();
        spinner->setCurrentValue(selectedLayout);

        spinner->onValueChanged = [this](const auto &) {
            getApplication()->render(gui::RefreshModes::GUI_REFRESH_DEEP);
        };

        setFocusItem(spinner);
    }

    bool OnBoardingShortcutsWindow::onInput(const gui::InputEvent &inputEvent)
    {
        if (spinner->onInput(inputEvent)) {
            return true;
        }

        if (inputEvent.isShortRelease()) {
            const auto key = mapKey(inputEvent.getKeyCode());
            if (key == KeyMap::LightPress) {
                auto currentLayout = spinner->getCurrentValue();
                if (presenter->isLastLayout(currentLayout)) {
                    getApplication()->switchWindow(window::name::onBoardingSettingsWindow);
                }
                return true;
            }
        }

        return AppWindow::onInput(inputEvent);
    }

} // namespace gui

A products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingShortcutsWindow.hpp => products/BellHybrid/apps/application-bell-onboarding/windows/OnBoardingShortcutsWindow.hpp +31 -0
@@ 0,0 1,31 @@
// 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/OnBoardingShortcutsWindowPresenter.hpp"
#include <ApplicationCommon.hpp>
#include <AppWindow.hpp>
#include <apps-common/widgets/spinners/Spinners.hpp>

namespace gui
{
    class SideListView;
    class OnBoardingShortcutsWindow : public AppWindow, public app::OnBoarding::OnBoardingShortcutsWindowContract::View
    {
        std::unique_ptr<app::OnBoarding::OnBoardingShortcutsWindowContract::Presenter> presenter;
        SideListView *sideListView = nullptr;
        WidgetSpinner *spinner     = nullptr;

        bool onInput(const gui::InputEvent &inputEvent) override;
        void buildInterface() override;

        void onValueChanged(const std::uint32_t currentValue);

      public:
        OnBoardingShortcutsWindow(
            app::ApplicationCommon *app,
            std::unique_ptr<app::OnBoarding::OnBoardingShortcutsWindowContract::Presenter> &&presenter,
            const std::string &name);
    };
} // namespace gui

M products/BellHybrid/apps/application-bell-settings/include/application-bell-settings/windows/BellSettingsTimeUnitsWindow.hpp => products/BellHybrid/apps/application-bell-settings/include/application-bell-settings/windows/BellSettingsTimeUnitsWindow.hpp +1 -0
@@ 28,6 28,7 @@ namespace gui

      protected:
        std::function<void()> finishedCallback = nullptr;
        std::function<void()> returnCallback   = nullptr;

      private:
        SideListView *sidelistview = nullptr;

M products/BellHybrid/apps/application-bell-settings/windows/BellSettingsTimeUnitsWindow.cpp => products/BellHybrid/apps/application-bell-settings/windows/BellSettingsTimeUnitsWindow.cpp +6 -0
@@ 69,6 69,12 @@ namespace gui
            }
            return true;
        }
        if (inputEvent.isShortRelease(KeyCode::KEY_RF)) {
            if (returnCallback) {
                returnCallback();
                return true;
            }
        }
        if (AppWindow::onInput(inputEvent)) {
            return true;
        }

M products/BellHybrid/apps/common/src/options/BellShortOptionWindow.cpp => products/BellHybrid/apps/common/src/options/BellShortOptionWindow.cpp +2 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "common/options/BellShortOptionWindow.hpp"


@@ 36,6 36,7 @@ namespace gui
        navBar->setVisible(false);

        body = new BellBaseLayout(this, 0, 0, style::window_width, style::window_height, false);
        body->setEdges(RectangleEdge::None);

        optionsList = new gui::ListView(body->centerBox, 0, 0, 0, 0, optionsModel, listview::ScrollBarType::None);
        optionsList->setAlignment(Alignment(Alignment::Vertical::Bottom));

M products/BellHybrid/assets/assets_common.json => products/BellHybrid/assets/assets_common.json +7 -1
@@ 53,7 53,13 @@
        {"name": "release.tgz", "tarfile" :"image/assets/images/bell/alarm_colon_select_W_M.vpi", "output": "assets/images/bell/alarm_colon_select_W_M.vpi"},
        {"name": "release.tgz", "tarfile" :"image/assets/images/bell/bell_arrow_down_W_M.vpi", "output": "assets/images/bell/bell_arrow_down_W_M.vpi"},
        {"name": "release.tgz", "tarfile" :"image/assets/images/bell/big_bell_ringing_W_G.vpi", "output": "assets/images/bell/big_bell_ringing_W_G.vpi"},

        {"name": "release.tgz", "tarfile" :"image/assets/images/bell/shortcuts_step_rotate_W_G.vpi", "output": "assets/images/bell/shortcuts_step_rotate_W_G.vpi"},
        {"name": "release.tgz", "tarfile" :"image/assets/images/bell/shortcuts_step_light_click_W_G.vpi", "output": "assets/images/bell/shortcuts_step_light_click_W_G.vpi"},
        {"name": "release.tgz", "tarfile" :"image/assets/images/bell/shortcuts_step_deep_press_W_G.vpi", "output": "assets/images/bell/shortcuts_step_deep_press_W_G.vpi"},
        {"name": "release.tgz", "tarfile" :"image/assets/images/bell/shortcuts_step_home_and_battery_W_G.vpi", "output": "assets/images/bell/shortcuts_step_home_and_battery_W_G.vpi"},
        {"name": "release.tgz", "tarfile" :"image/assets/images/bell/shortcuts_step_turn_off_W_G.vpi", "output": "assets/images/bell/shortcuts_step_turn_off_W_G.vpi"},
        {"name": "release.tgz", "tarfile" :"image/assets/images/bell/shortcuts_step_restart_W_G.vpi", "output": "assets/images/bell/shortcuts_step_restart_W_G.vpi"},
        {"name": "release.tgz", "tarfile" :"image/assets/images/bell/shortcuts_step_bedside_lamp_W_G.vpi", "output": "assets/images/bell/shortcuts_step_bedside_lamp_W_G.vpi"},
        
        {"name": "release_audio.tgz", "tarfile" :"./image/assets/audio/bell/chimes/Blissful_Dream.mp3", "output": "assets/audio/chimes/Blissful_Dream.mp3"},
        {"name": "release_audio.tgz", "tarfile" :"./image/assets/audio/bell/chimes/Gentle_Chime.mp3", "output": "assets/audio/chimes/Gentle_Chime.mp3"},