~aleteoryx/muditaos

cd6db6491edef8b71e490a8905603228286e564b — Lefucjusz 1 year, 11 months ago 75c12a8
[BH-1890] Change pre-wakeup chime list to vertical

* Added new widget SongsListViewItem
implementing ListViewWithLabels that
can be added as SettingsListItem.
* Changed horizontal list in pre-wakeup
to vertical using that new widget.
46 files changed, 328 insertions(+), 171 deletions(-)

M image/system_a/data/lang/Deutsch.json
M image/system_a/data/lang/English.json
M image/system_a/data/lang/Espanol.json
M image/system_a/data/lang/Francais.json
M image/system_a/data/lang/Polski.json
M module-apps/apps-common/widgets/BellBaseLayout.cpp
M module-apps/apps-common/widgets/BellBaseLayout.hpp
M module-apps/apps-common/widgets/BellSideListItem.cpp
M module-apps/apps-common/widgets/BellSideListItem.hpp
M module-apps/apps-common/widgets/BellSideListItemStyle.hpp
M module-gui/gui/widgets/ListItem.hpp
M module-gui/gui/widgets/ListItemProvider.hpp
M module-gui/gui/widgets/ListViewWithArrows.cpp
M module-gui/gui/widgets/ListViewWithArrows.hpp
M products/BellHybrid/apps/application-bell-meditation-timer/windows/MeditationTimerWindow.cpp
M products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationMainWindow.cpp
M products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationPausedWindow.cpp
M products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationRunningLoopWindow.cpp
M products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationTimerSelectWindow.cpp
M products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationVolumeWindow.cpp
M products/BellHybrid/apps/application-bell-settings/ApplicationBellSettings.cpp
M products/BellHybrid/apps/application-bell-settings/CMakeLists.txt
M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/PrewakeUpListItemProvider.cpp
M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/PrewakeUpListItemProvider.hpp
M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/PrewakeUpSettingsModel.cpp
M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/PrewakeUpSettingsModel.hpp
M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/PrewakeUpPresenter.cpp
M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/PrewakeUpPresenter.hpp
A products/BellHybrid/apps/application-bell-settings/widgets/SongsListViewItem.cpp
A products/BellHybrid/apps/application-bell-settings/widgets/SongsListViewItem.hpp
M products/BellHybrid/apps/application-bell-settings/windows/BellSettingsLanguageWindow.cpp
M products/BellHybrid/apps/common/include/common/models/SongsModel.hpp
M products/BellHybrid/apps/common/include/common/options/OptionBellMenu.hpp
M products/BellHybrid/apps/common/include/common/widgets/BellSideListItemWithCallbacks.hpp
M products/BellHybrid/apps/common/include/common/widgets/ListViewWithLabels.hpp
M products/BellHybrid/apps/common/include/common/widgets/list_items/NumericWithBar.hpp
M products/BellHybrid/apps/common/src/BellSideListItemWithCallbacks.cpp
M products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutClassic.cpp
M products/BellHybrid/apps/common/src/models/SongsModel.cpp
M products/BellHybrid/apps/common/src/options/BellOptionWithDescriptionWindow.cpp
M products/BellHybrid/apps/common/src/options/BellShortOptionWindow.cpp
M products/BellHybrid/apps/common/src/widgets/LabelListItem.cpp
M products/BellHybrid/apps/common/src/widgets/LabelOption.cpp
M products/BellHybrid/apps/common/src/widgets/ListViewWithLabels.cpp
M products/BellHybrid/apps/common/src/windows/BellBatteryStatusWindow.cpp
M products/BellHybrid/apps/common/src/windows/BellWelcomeWindow.cpp
M image/system_a/data/lang/Deutsch.json => image/system_a/data/lang/Deutsch.json +4 -4
@@ 77,12 77,12 @@
    "app_bell_settings_alarm_settings_fade": "Erh\u00f6ht allm\u00e4hlich Alarmlautst\u00e4rke",
    "app_bell_settings_alarm_settings_light": "Alarmleuchte",
    "app_bell_settings_alarm_settings_prewake_up": "Sanftes Wecken",
    "app_bell_settings_alarm_settings_prewake_up_chime_bottom_description": "vor dem Alarm",
    "app_bell_settings_alarm_settings_prewake_up_chime_tone": "Klang",
    "app_bell_settings_alarm_settings_prewake_up_chime_top_description": "Klang vor dem Aufwachen",
    "app_bell_settings_alarm_settings_prewake_up_time_top_description": "Klang vor dem Aufwachen",
    "app_bell_settings_alarm_settings_prewake_up_time_bottom_description": "vor dem Alarm",
    "app_bell_settings_alarm_settings_prewake_up_chime_top_description": "Klang",
    "app_bell_settings_alarm_settings_prewake_up_chime_volume": "Lautst\u00e4rke",
    "app_bell_settings_alarm_settings_prewake_up_light_bottom_description": "vor dem Alarm",
    "app_bell_settings_alarm_settings_prewake_up_light_top_description": "Licht",
    "app_bell_settings_alarm_settings_prewake_up_light_bottom_description": "vor dem Alarm",
    "app_bell_settings_alarm_settings_snooze": "Schlummer",
    "app_bell_settings_alarm_settings_snooze_chime_interval": "Schlummer Klangintervall",
    "app_bell_settings_alarm_settings_snooze_chime_interval_bot_desc": "w\u00e4hrend des Schlummern",

M image/system_a/data/lang/English.json => image/system_a/data/lang/English.json +4 -4
@@ 111,12 111,12 @@
    "app_bell_settings_alarm_settings_fade": "Gradually raise the alarm volume",
    "app_bell_settings_alarm_settings_light": "Main alarm light",
    "app_bell_settings_alarm_settings_prewake_up": "Pre-wake up",
    "app_bell_settings_alarm_settings_prewake_up_chime_bottom_description": "before the alarm",
    "app_bell_settings_alarm_settings_prewake_up_chime_tone": "Pre-wake up chime tone",
    "app_bell_settings_alarm_settings_prewake_up_time_top_description": "Play Pre-wake up",
    "app_bell_settings_alarm_settings_prewake_up_time_bottom_description": "before the alarm",
    "app_bell_settings_alarm_settings_prewake_up_chime_top_description": "Pre-wake up chime",
    "app_bell_settings_alarm_settings_prewake_up_chime_volume": "Pre-wake up chime volume",
    "app_bell_settings_alarm_settings_prewake_up_light_bottom_description": "before the alarm",
    "app_bell_settings_alarm_settings_prewake_up_chime_volume": "Pre-wake up volume",
    "app_bell_settings_alarm_settings_prewake_up_light_top_description": "Pre-wake up light",
    "app_bell_settings_alarm_settings_prewake_up_light_bottom_description": "before the alarm",
    "app_bell_settings_alarm_settings_snooze": "Snooze",
    "app_bell_settings_alarm_settings_snooze_chime_interval": "Snooze chime interval",
    "app_bell_settings_alarm_settings_snooze_chime_interval_bot_desc": "<text>recurring during<br />snooze</text>",

M image/system_a/data/lang/Espanol.json => image/system_a/data/lang/Espanol.json +4 -4
@@ 76,12 76,12 @@
    "app_bell_settings_alarm_settings_fade": "Aumentar vol. alarma gradualmente",
    "app_bell_settings_alarm_settings_light": "Luz de alarma",
    "app_bell_settings_alarm_settings_prewake_up": "Despertar gradual",
    "app_bell_settings_alarm_settings_prewake_up_chime_bottom_description": "antes de la alarma",
    "app_bell_settings_alarm_settings_prewake_up_chime_tone": "Tono",
    "app_bell_settings_alarm_settings_prewake_up_chime_top_description": "Despertar gradualmente",
    "app_bell_settings_alarm_settings_prewake_up_time_top_description": "Despertar gradualmente",
    "app_bell_settings_alarm_settings_prewake_up_time_bottom_description": "antes de la alarma",
    "app_bell_settings_alarm_settings_prewake_up_chime_top_description": "Tono",
    "app_bell_settings_alarm_settings_prewake_up_chime_volume": "Volumen",
    "app_bell_settings_alarm_settings_prewake_up_light_bottom_description": "antes de la alarma",
    "app_bell_settings_alarm_settings_prewake_up_light_top_description": "Luz",
    "app_bell_settings_alarm_settings_prewake_up_light_bottom_description": "antes de la alarma",
    "app_bell_settings_alarm_settings_snooze": "Repetici\u00f3n",
    "app_bell_settings_alarm_settings_snooze_chime_interval": "Intervalo del tono",
    "app_bell_settings_alarm_settings_snooze_chime_interval_bot_desc": "durante la funci\u00f3n de repetici\u00f3n",

M image/system_a/data/lang/Francais.json => image/system_a/data/lang/Francais.json +4 -4
@@ 78,12 78,12 @@
    "app_bell_settings_alarm_settings_fade": "Augmentation graduelle du volume",
    "app_bell_settings_alarm_settings_light": "Lumi\u00e8re de r\u00e9veil",
    "app_bell_settings_alarm_settings_prewake_up": "Pr\u00e9-r\u00e9veil",
    "app_bell_settings_alarm_settings_prewake_up_chime_bottom_description": "avant l'alarme",
    "app_bell_settings_alarm_settings_prewake_up_chime_tone": "M\u00e9lodie de pr\u00e9-r\u00e9veil",
    "app_bell_settings_alarm_settings_prewake_up_chime_top_description": "Pr\u00e9-r\u00e9veil",
    "app_bell_settings_alarm_settings_prewake_up_time_top_description": "Pr\u00e9-r\u00e9veil",
    "app_bell_settings_alarm_settings_prewake_up_time_bottom_description": "avant l'alarme",
    "app_bell_settings_alarm_settings_prewake_up_chime_top_description": "M\u00e9lodie de pr\u00e9-r\u00e9veil",
    "app_bell_settings_alarm_settings_prewake_up_chime_volume": "Volume",
    "app_bell_settings_alarm_settings_prewake_up_light_bottom_description": "avant l'alarme",
    "app_bell_settings_alarm_settings_prewake_up_light_top_description": "Lumi\u00e8re de pr\u00e9-r\u00e9veil",
    "app_bell_settings_alarm_settings_prewake_up_light_bottom_description": "avant l'alarme",
    "app_bell_settings_alarm_settings_snooze": "Snooze",
    "app_bell_settings_alarm_settings_snooze_chime_interval": "Intervalle de rappel",
    "app_bell_settings_alarm_settings_snooze_chime_interval_bot_desc": "pendant le snooze",

M image/system_a/data/lang/Polski.json => image/system_a/data/lang/Polski.json +4 -4
@@ 77,12 77,12 @@
    "app_bell_settings_alarm_settings_fade": "Stopniowo podno\u015b g\u0142o\u015bno\u015b\u0107 alarmu",
    "app_bell_settings_alarm_settings_light": "\u015awiat\u0142o alarmu",
    "app_bell_settings_alarm_settings_prewake_up": "Wst\u0119pne budzenie",
    "app_bell_settings_alarm_settings_prewake_up_chime_bottom_description": "przed alarmem",
    "app_bell_settings_alarm_settings_prewake_up_chime_tone": "D\u017awi\u0119k wst\u0119pnego budzenia",
    "app_bell_settings_alarm_settings_prewake_up_chime_top_description": "Wst\u0119pne budzenie",
    "app_bell_settings_alarm_settings_prewake_up_time_top_description": "Wst\u0119pne budzenie",
    "app_bell_settings_alarm_settings_prewake_up_time_bottom_description": "przed alarmem",
    "app_bell_settings_alarm_settings_prewake_up_chime_top_description": "D\u017awi\u0119k wst\u0119pnego budzenia",
    "app_bell_settings_alarm_settings_prewake_up_chime_volume": "G\u0142o\u015bno\u015b\u0107",
    "app_bell_settings_alarm_settings_prewake_up_light_bottom_description": "przed alarmem",
    "app_bell_settings_alarm_settings_prewake_up_light_top_description": "\u015awiat\u0142o wst\u0119pnego budzenia",
    "app_bell_settings_alarm_settings_prewake_up_light_bottom_description": "przed alarmem",
    "app_bell_settings_alarm_settings_snooze": "Drzemka",
    "app_bell_settings_alarm_settings_snooze_chime_interval": "Interwa\u0142 d\u017awi\u0119ku",
    "app_bell_settings_alarm_settings_snooze_chime_interval_bot_desc": "powtarzaj\u0105cy si\u0119 podczas drzemki",

M module-apps/apps-common/widgets/BellBaseLayout.cpp => module-apps/apps-common/widgets/BellBaseLayout.cpp +3 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "BellBaseLayout.hpp"


@@ 6,7 6,7 @@

namespace gui
{
    BellBaseLayout::BellBaseLayout(Item *parent, Position x, Position y, Length w, Length h, bool withSideArrows)
    BellBaseLayout::BellBaseLayout(Item *parent, Position x, Position y, Length w, Length h, LayoutType type)
        : VThreeBox(parent, x, y, w, h)
    {
        setMinimumSize(style::bell_base_layout::w, style::bell_base_layout::h);


@@ 34,7 34,7 @@ namespace gui

        resizeItems();

        if (withSideArrows) {
        if (type == LayoutType::WithArrows) {
            addSideArrows();
        }
    }

M module-apps/apps-common/widgets/BellBaseLayout.hpp => module-apps/apps-common/widgets/BellBaseLayout.hpp +12 -2
@@ 29,14 29,24 @@ namespace gui
    class BellBaseLayout : public VThreeBox<VBox, VBox, VBox>
    {
      public:
        enum class LayoutType
        {
            WithArrows,
            WithoutArrows
        };

        enum class Arrow
        {
            Left,
            Right
        };

        explicit BellBaseLayout(
            Item *parent, Position x = 0, Position y = 0, Length w = 0, Length h = 0, bool withSideArrows = true);
        explicit BellBaseLayout(Item *parent,
                                Position x      = 0,
                                Position y      = 0,
                                Length w        = 0,
                                Length h        = 0,
                                LayoutType type = LayoutType::WithArrows);

        [[nodiscard]] Item *getCenterBox() const noexcept;
        void resizeCenter();

M module-apps/apps-common/widgets/BellSideListItem.cpp => module-apps/apps-common/widgets/BellSideListItem.cpp +3 -5
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "TextFixedSize.hpp"


@@ 7,12 7,11 @@

namespace gui
{

    BellSideListItem::BellSideListItem()
    BellSideListItem::BellSideListItem(BellBaseLayout::LayoutType type)
    {
        setMinimumSize(style::sidelistview::list_item::w, style::sidelistview::list_item::h);
        setEdges(RectangleEdge::None);
        body = new BellBaseLayout(this);
        body = new BellBaseLayout(this, 0, 0, 0, 0, type);
    }

    void BellSideListItem::setBottomDescriptionText(const std::string &description)


@@ 46,5 45,4 @@ namespace gui
        textBox->setRichText(description);
        textBox->drawUnderline(false);
    }

} /* namespace gui */

M module-apps/apps-common/widgets/BellSideListItem.hpp => module-apps/apps-common/widgets/BellSideListItem.hpp +3 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 10,13 10,14 @@
namespace gui
{
    class TextFixedSize;

    class BellSideListItem : public ListItem
    {
      public:
        void setBottomDescriptionText(const std::string &description);

      protected:
        BellSideListItem();
        BellSideListItem(BellBaseLayout::LayoutType type = BellBaseLayout::LayoutType::WithArrows);
        void setupBottomTextBox(const std::string &description);
        void setupTopTextBox(const std::string &description);


M module-apps/apps-common/widgets/BellSideListItemStyle.hpp => module-apps/apps-common/widgets/BellSideListItemStyle.hpp +1 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 7,5 7,4 @@ namespace style::bell_sidelist_item
{
    inline constexpr auto title_font       = style::window::font::largelight;
    inline constexpr auto description_font = style::window::font::verybiglight;

} // namespace style::bell_sidelist_item

M module-gui/gui/widgets/ListItem.hpp => module-gui/gui/widgets/ListItem.hpp +2 -4
@@ 1,4 1,4 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 7,10 7,8 @@

namespace gui
{

    class ListItem : public Rect
    {

      public:
        bool deleteByList = true;
        void accept(GuiVisitor &visitor) override;


@@ 29,4 27,4 @@ namespace gui
        std::function<void(std::shared_ptr<T> record)> onLoadCallback               = nullptr;
        std::function<bool(std::shared_ptr<T> record)> onCheckUnsavedChangeCallback = nullptr;
    };
} /* namespace gui */
} // namespace gui

M module-gui/gui/widgets/ListItemProvider.hpp => module-gui/gui/widgets/ListItemProvider.hpp +12 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 15,6 15,17 @@ namespace gui
        Previous
    };

    inline constexpr Order operator~(const Order &order)
    {
        switch (order) {
        case Order::Next:
            return Order::Previous;
        case Order::Previous:
        default:
            return Order::Next;
        }
    }

    class ListItemProvider
    {
      public:

M module-gui/gui/widgets/ListViewWithArrows.cpp => module-gui/gui/widgets/ListViewWithArrows.cpp +7 -2
@@ 1,8 1,9 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ListViewWithArrows.hpp"
#include "TextFixedSize.hpp"
#include "ImageBox.hpp"
#include <InputEvent.hpp>

namespace gui


@@ 140,6 141,11 @@ namespace gui
        listOverlay->firstBox->resizeItems();
    }

    void ListViewWithArrows::setListTitleFont(const UTF8 &fontName)
    {
        titleBody->setFont(fontName);
    }

    void ListViewWithArrows::applyScrollCallbacks()
    {
        updateScrollCallback = [this](ListViewScrollUpdateData data) {


@@ 214,5 220,4 @@ namespace gui

        return true;
    }

} /* namespace gui */

M module-gui/gui/widgets/ListViewWithArrows.hpp => module-gui/gui/widgets/ListViewWithArrows.hpp +7 -5
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 6,11 6,13 @@
#include "ListViewEngine.hpp"
#include "ListItemProvider.hpp"
#include "ThreeBox.hpp"
#include "ImageBox.hpp"
#include "TextFixedSize.hpp"
#include <utf8/UTF8.hpp>

namespace gui
{
    class ImageBox;
    class TextFixedSize;

    class ListViewWithArrows : public Rect, public ListViewEngine
    {
      protected:


@@ 33,10 35,10 @@ namespace gui
                           std::shared_ptr<ListItemProvider> prov);

        void setListTitle(const std::string &title);
        void setListTitleFont(const UTF8 &fontName);
        void applySizeRestrictions(unsigned int w, unsigned int h, unsigned int outerLayoutsH, int outerLayoutsMargin);

        void setAlignment(const Alignment &value) override;
        bool onDimensionChanged(const BoundingBox &oldDim, const BoundingBox &newDim) override;
    };

} /* namespace gui */
} // namespace gui

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

#include "MeditationTimer.hpp"


@@ 28,7 28,7 @@ namespace app::meditation
        header->setTitleVisibility(false);
        navBar->setVisible(false);

        body = new BellBaseLayout(this, 0, 0, style::window_width, style::window_height, true);
        body = new BellBaseLayout(this, 0, 0, style::window_width, style::window_height);

        auto topMessage = new TextFixedSize(body->firstBox);
        topMessage->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::outer_layouts_h);

M products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationMainWindow.cpp => products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationMainWindow.cpp +2 -2
@@ 40,7 40,7 @@ namespace gui
        songList->setListTitle(utils::translate("app_bellmain_relaxation"));

        auto storedCallback     = songList->inputCallback;
        songList->inputCallback = [&, storedCallback](Item &item, const InputEvent &event) {
        songList->inputCallback = [storedCallback](Item &item, const InputEvent &event) {
            return storedCallback(item, invertNavigationDirection(event));
        };
        setFocusItem(songList);


@@ 68,11 68,11 @@ namespace gui
    {
        songList->rebuildList(gui::listview::RebuildType::InPlace);
    }

    void RelaxationMainWindow::rebuild()
    {
        presenter->updateRecordsCount();
        songList->reset();
        songList->rebuildList(gui::listview::RebuildType::Full);
    }

} // namespace gui

M products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationPausedWindow.cpp => products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationPausedWindow.cpp +6 -1
@@ 41,7 41,12 @@ namespace gui
        AppWindow::buildInterface();

        statusBar->setVisible(false);
        auto body = new gui::BellBaseLayout(this, 0, 0, style::bell_base_layout::w, style::bell_base_layout::h, false);
        auto body = new gui::BellBaseLayout(this,
                                            0,
                                            0,
                                            style::bell_base_layout::w,
                                            style::bell_base_layout::h,
                                            BellBaseLayout::LayoutType::WithoutArrows);
        auto vBox =
            new VBox(body->getCenterBox(), 0, 0, style::bell_base_layout::w, style::bell_base_layout::center_layout_h);
        vBox->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));

M products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationRunningLoopWindow.cpp => products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationRunningLoopWindow.cpp +6 -1
@@ 124,7 124,12 @@ namespace gui
    {
        using Alignment = gui::Alignment;
        statusBar->setVisible(false);
        auto body = new gui::BellBaseLayout(this, 0, 0, style::bell_base_layout::w, style::bell_base_layout::h, false);
        auto body = new gui::BellBaseLayout(this,
                                            0,
                                            0,
                                            style::bell_base_layout::w,
                                            style::bell_base_layout::h,
                                            BellBaseLayout::LayoutType::WithoutArrows);

        title      = createTitle(body->centerBox);
        time       = createClock(body->firstBox);

M products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationTimerSelectWindow.cpp => products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationTimerSelectWindow.cpp +1 -1
@@ 78,7 78,7 @@ namespace gui
        AppWindow::buildInterface();
        statusBar->setVisible(false);

        body = new BellBaseLayout(this, 0, 0, style::window_width, style::window_height, true);
        body = new BellBaseLayout(this, 0, 0, style::window_width, style::window_height);
        createTopMessage();
        createSpinner();
        createBottomDescription();

M products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationVolumeWindow.cpp => products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationVolumeWindow.cpp +1 -1
@@ 26,7 26,7 @@ namespace gui
        header->setTitleVisibility(false);
        navBar->setVisible(false);

        body = new BellBaseLayout(this, 0, 0, style::window_width, style::window_height, true);
        body = new BellBaseLayout(this, 0, 0, style::window_width, style::window_height);

        auto topMessage = new TextFixedSize(body->firstBox);
        topMessage->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::outer_layouts_h);

M products/BellHybrid/apps/application-bell-settings/ApplicationBellSettings.cpp => products/BellHybrid/apps/application-bell-settings/ApplicationBellSettings.cpp +13 -12
@@ 43,6 43,7 @@
#include <common/models/AudioModel.hpp>
#include <common/models/TimeModel.hpp>
#include <common/models/AlarmSettingsModel.hpp>
#include <common/models/SongsModel.hpp>
#include <service-evtmgr/EventManagerServiceAPI.hpp>
#include <service-appmgr/messages/GetCurrentDisplayLanguageResponse.hpp>



@@ 160,11 161,8 @@ namespace app

        windowsFactory.attach(
            gui::BellSettingsPrewakeUpWindow::name, [this](ApplicationCommon *app, const std::string &name) {
                auto soundsRepository =
                    std::make_unique<SimpleSoundsRepository>(paths::audio::proprietary() / paths::audio::preWakeup());
                auto prewakeUpChimeDurationModel = std::make_unique<bell_settings::PrewakeUpChimeDurationModel>(this);
                auto prewakeUpChimeToneModel =
                    std::make_unique<bell_settings::PrewakeUpChimeToneModel>(this, *soundsRepository);
                auto prewakeUpChimeToneModel     = std::make_unique<bell_settings::PrewakeUpChimeToneModel>(this);
                auto prewakeUpChimeVolumeModel =
                    std::make_unique<bell_settings::PrewakeUpChimeVolumeModel>(*audioModel);
                auto prewakeUpLightDurationModel = std::make_unique<bell_settings::PrewakeUpLightDurationModel>(this);


@@ 176,15 174,18 @@ namespace app
                                                                            std::move(prewakeUpLightDurationModel),
                                                                            std::move(prewakeUpFrontlightModel));

                auto provider         = std::make_unique<bell_settings::PrewakeUpListItemProvider>(
                    *prewakeUpSettingsModel, soundsRepository->getSongTitles());
                const auto &pathSorting =
                    SoundsRepository::PathSorting{paths::audio::proprietary() / paths::audio::preWakeup(),
                                                  SoundsRepository::SortingBy::TitleAscending};
                auto soundsRepository = std::make_unique<SoundsRepository>(this, pathSorting);
                auto songsModel       = std::make_unique<SongsModel>(this, std::move(soundsRepository));

                auto provider = std::make_unique<bell_settings::PrewakeUpListItemProvider>(*prewakeUpSettingsModel,
                                                                                           std::move(songsModel));

                auto frontlightModel = std::make_unique<bell_settings::FrontlightModel>(app);
                auto presenter =
                    std::make_unique<bell_settings::PrewakeUpWindowPresenter>(std::move(provider),
                                                                              std::move(prewakeUpSettingsModel),
                                                                              *audioModel,
                                                                              std::move(soundsRepository),
                                                                              std::move(frontlightModel));
                auto presenter       = std::make_unique<bell_settings::PrewakeUpWindowPresenter>(
                    std::move(provider), std::move(prewakeUpSettingsModel), *audioModel, std::move(frontlightModel));
                return std::make_unique<gui::BellSettingsPrewakeUpWindow>(app, std::move(presenter));
            });


M products/BellHybrid/apps/application-bell-settings/CMakeLists.txt => products/BellHybrid/apps/application-bell-settings/CMakeLists.txt +2 -0
@@ 55,6 55,7 @@ target_sources(application-bell-settings
        widgets/TimeSetListItem.cpp
        widgets/AboutYourBellListItem.cpp
        widgets/DialogYesNo.cpp
        widgets/SongsListViewItem.cpp

        windows/BellSettingsBedtimeToneWindow.cpp
        windows/BellSettingsTimeUnitsWindow.cpp


@@ 98,6 99,7 @@ target_sources(application-bell-settings
        widgets/TimeSetListItem.hpp
        widgets/AboutYourBellListItem.hpp
        widgets/DialogYesNo.hpp
        widgets/SongsListViewItem.hpp

        windows/alarm_settings/BellSettingsAlarmSettingsSnoozeWindow.hpp
        windows/alarm_settings/BellSettingsAlarmSettingsWindow.hpp

M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/PrewakeUpListItemProvider.cpp => products/BellHybrid/apps/application-bell-settings/models/alarm_settings/PrewakeUpListItemProvider.cpp +15 -13
@@ 8,23 8,24 @@
#include <common/widgets/list_items/Numeric.hpp>
#include <common/widgets/list_items/NumericWithBar.hpp>
#include <common/widgets/ListItems.hpp>
#include <common/widgets/list_items/Text.hpp>
#include <apps-common/ApplicationCommon.hpp>
#include <gui/widgets/ListViewEngine.hpp>
#include <utility>

#include <SongsListViewItem.hpp>
#include <Paths.hpp>

namespace app::bell_settings
{
    using namespace gui;

    PrewakeUpListItemProvider::PrewakeUpListItemProvider(AbstractPrewakeUpSettingsModel &settingsModel,
                                                         std::vector<UTF8> chimeToneRange)
        : settingsModel{settingsModel}
                                                         std::shared_ptr<SongsModel> songsModel)
        : settingsModel{settingsModel}, songsModel{std::move(songsModel)}
    {
        buildListItems(std::move(chimeToneRange));
        buildListItems();
    }

    void PrewakeUpListItemProvider::buildListItems(std::vector<UTF8> chimeToneRange)
    void PrewakeUpListItemProvider::buildListItems()
    {
        constexpr auto brightnessMin  = 1U;
        constexpr auto brightnessMax  = 10U;


@@ 32,12 33,11 @@ namespace app::bell_settings
        constexpr auto itemCount      = 5U;
        internalData.reserve(itemCount);

        const std::string minStr = utils::translate("common_minute_short");
        auto chimeDuration       = new list_items::NumberWithSuffix(
        auto chimeDuration = new list_items::NumberWithSuffix(
            list_items::NumberWithSuffix::spinner_type::range{0, 5, 10, 15},
            settingsModel.getChimeDuration(),
            utils::translate("app_bell_settings_alarm_settings_prewake_up_chime_top_description"),
            utils::translate("app_bell_settings_alarm_settings_prewake_up_chime_bottom_description"));
            utils::translate("app_bell_settings_alarm_settings_prewake_up_time_top_description"),
            utils::translate("app_bell_settings_alarm_settings_prewake_up_time_bottom_description"));

        chimeDuration->onProceed = [chimeDuration, this]() {
            if (chimeDuration->value() == 0) {


@@ 51,14 51,16 @@ namespace app::bell_settings
        internalData.emplace_back(chimeDuration);

        auto chimeTone =
            new list_items::Text(std::move(chimeToneRange),
                                 settingsModel.getChimeTone(),
                                 utils::translate("app_bell_settings_alarm_settings_prewake_up_chime_tone"));
            new SongsListViewItem(utils::translate("app_bell_settings_alarm_settings_prewake_up_chime_top_description"),
                                  settingsModel.getChimeTone(),
                                  songsModel);

        chimeTone->set_on_value_change_cb([this](const auto &val) {
            if (onToneChange) {
                onToneChange(val);
            }
        });

        chimeTone->onEnter = [this, chimeTone]() {
            if (onToneEnter) {
                onToneEnter(chimeTone->value());

M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/PrewakeUpListItemProvider.hpp => products/BellHybrid/apps/application-bell-settings/models/alarm_settings/PrewakeUpListItemProvider.hpp +6 -2
@@ 6,6 6,7 @@
#include "SettingsListItemProvider.hpp"
#include "AbstractPrewakeUpSettingsModel.hpp"
#include <common/models/AbstractSettingsModel.hpp>
#include <common/models/SongsModel.hpp>

namespace app::list_items
{


@@ 15,17 16,20 @@ namespace app::list_items
namespace app::bell_settings
{
    class AbstractFrontlightModel;

    class PrewakeUpListItemProvider : public SettingsListItemProvider
    {
      public:
        PrewakeUpListItemProvider(AbstractPrewakeUpSettingsModel &settingsModel, std::vector<UTF8> chimeToneRange);
        PrewakeUpListItemProvider(AbstractPrewakeUpSettingsModel &settingsModel,
                                  std::shared_ptr<SongsModel> songsModel);

        auto getCurrentVolume() -> std::uint8_t;

      private:
        void buildListItems(std::vector<UTF8> preWakeupToneRange);
        void buildListItems();

        AbstractPrewakeUpSettingsModel &settingsModel;
        app::list_items::NumericWithBar *prewakeUpVolume{nullptr};
        std::shared_ptr<SongsModel> songsModel;
    };
} // namespace app::bell_settings

M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/PrewakeUpSettingsModel.cpp => products/BellHybrid/apps/application-bell-settings/models/alarm_settings/PrewakeUpSettingsModel.cpp +2 -8
@@ 23,20 23,14 @@ namespace app::bell_settings
        return utils::toNumeric(str);
    }

    PrewakeUpChimeToneModel::PrewakeUpChimeToneModel(sys::Service *app, SimpleSoundsRepository &soundsRepository)
        : gui::SettingsModel<UTF8>{app}, soundsRepository{soundsRepository}
    {}

    void PrewakeUpChimeToneModel::setValue(UTF8 value)
    {
        const auto &path = soundsRepository.titleToPath(value).value_or("");
        settings.setValue(bell::settings::PrewakeUp::tonePath, path, settings::SettingsScope::Global);
        settings.setValue(bell::settings::PrewakeUp::tonePath, value, settings::SettingsScope::Global);
    }

    UTF8 PrewakeUpChimeToneModel::getValue() const
    {
        const auto &path = settings.getValue(bell::settings::PrewakeUp::tonePath, settings::SettingsScope::Global);
        return soundsRepository.pathToTitle(path).value_or("");
        return settings.getValue(bell::settings::PrewakeUp::tonePath, settings::SettingsScope::Global);
    }

    void PrewakeUpChimeVolumeModel::setValue(std::uint8_t value)

M products/BellHybrid/apps/application-bell-settings/models/alarm_settings/PrewakeUpSettingsModel.hpp => products/BellHybrid/apps/application-bell-settings/models/alarm_settings/PrewakeUpSettingsModel.hpp +1 -4
@@ 23,13 23,10 @@ namespace app::bell_settings
    class PrewakeUpChimeToneModel : public gui::SettingsModel<UTF8>
    {
      public:
        PrewakeUpChimeToneModel(sys::Service *app, SimpleSoundsRepository &soundsRepository);
        using SettingsModel::SettingsModel;

        void setValue(UTF8 value) override;
        UTF8 getValue() const override;

      private:
        SimpleSoundsRepository &soundsRepository;
    };

    class PrewakeUpChimeVolumeModel : public gui::AbstractSettingsModel<std::uint8_t>

M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/PrewakeUpPresenter.cpp => products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/PrewakeUpPresenter.cpp +7 -11
@@ 6,21 6,17 @@

namespace app::bell_settings
{
    PrewakeUpWindowPresenter::PrewakeUpWindowPresenter(
        std::unique_ptr<PrewakeUpListItemProvider> &&provider,
        std::unique_ptr<AbstractPrewakeUpSettingsModel> &&model,
        AbstractAudioModel &audioModel,
        std::unique_ptr<AbstractSimpleSoundsRepository> &&soundsRepository,
        std::unique_ptr<AbstractFrontlightModel> &&frontlight)
        : provider{std::move(provider)}, model{std::move(model)}, audioModel{audioModel},
          soundsRepository{std::move(soundsRepository)}, frontlight{std::move(frontlight)}
    PrewakeUpWindowPresenter::PrewakeUpWindowPresenter(std::unique_ptr<PrewakeUpListItemProvider> &&provider,
                                                       std::unique_ptr<AbstractPrewakeUpSettingsModel> &&model,
                                                       AbstractAudioModel &audioModel,
                                                       std::unique_ptr<AbstractFrontlightModel> &&frontlight)
        : provider{std::move(provider)}, model{std::move(model)}, audioModel{audioModel}, frontlight{
                                                                                              std::move(frontlight)}
    {
        auto playSound = [this](const UTF8 &val) {
            currentSoundPath = val;
            this->audioModel.setVolume(this->provider->getCurrentVolume(), AbstractAudioModel::PlaybackType::PreWakeup);
            this->audioModel.play(this->soundsRepository->titleToPath(currentSoundPath).value_or(""),
                                  AbstractAudioModel::PlaybackType::PreWakeup,
                                  {});
            this->audioModel.play(currentSoundPath, AbstractAudioModel::PlaybackType::PreWakeup, {});
        };

        this->provider->onExit = [this]() { getView()->exit(); };

M products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/PrewakeUpPresenter.hpp => products/BellHybrid/apps/application-bell-settings/presenter/alarm_settings/PrewakeUpPresenter.hpp +0 -3
@@ 8,7 8,6 @@
#include <models/alarm_settings/AbstractPrewakeUpSettingsModel.hpp>
#include <common/models/AbstractAudioModel.hpp>
#include <common/models/FrontlightModel.hpp>
#include <common/SoundsRepository.hpp>
#include <memory>

namespace gui


@@ 48,7 47,6 @@ namespace app::bell_settings
        PrewakeUpWindowPresenter(std::unique_ptr<PrewakeUpListItemProvider> &&provider,
                                 std::unique_ptr<AbstractPrewakeUpSettingsModel> &&model,
                                 AbstractAudioModel &audioModel,
                                 std::unique_ptr<AbstractSimpleSoundsRepository> &&soundsRepository,
                                 std::unique_ptr<AbstractFrontlightModel> &&frontlight);

        auto getPagesProvider() const -> std::shared_ptr<gui::ListItemProvider> override;


@@ 63,7 61,6 @@ namespace app::bell_settings
        std::shared_ptr<PrewakeUpListItemProvider> provider;
        std::unique_ptr<AbstractPrewakeUpSettingsModel> model;
        AbstractAudioModel &audioModel;
        std::unique_ptr<AbstractSimpleSoundsRepository> soundsRepository;
        std::unique_ptr<AbstractFrontlightModel> frontlight;
        UTF8 currentSoundPath;
    };

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

#include "SongsListViewItem.hpp"
#include <common/options/BellOptionsNavigation.hpp>
#include <common/options/BellOptionWindow.hpp>
#include <common/widgets/ListViewWithLabels.hpp>
#include <common/models/SongsModel.hpp>

namespace gui
{
    SongsListViewItem::SongsListViewItem(const std::string &title,
                                         AbstractSettingsModel<UTF8> &settingsModel,
                                         std::shared_ptr<app::SongsModel> songsModel)
        : BellSideListItemWithCallbacks({}, BellBaseLayout::LayoutType::WithoutArrows), settingsModel{settingsModel},
          songsModel{songsModel}
    {
        rearrangeBaseLayout();

        list = new ListViewWithLabels(body, 0, 0, style::window_width, style::window_height, songsModel);
        list->setAlignment(Alignment(Alignment::Horizontal::Center, Alignment::Vertical::Top));
        list->applySizeRestrictions(style::bell_options_list::w,
                                    style::bell_options_list::h,
                                    style::bell_options_list::outer_layouts_h,
                                    style::bell_options_list::outer_layouts_margin);
        list->setListTitle(title);
        list->setListTitleFont(style::bell_sidelist_item::title_font);

        auto storedCallback = list->inputCallback;
        list->inputCallback = [storedCallback](Item &item, const InputEvent &event) {
            return storedCallback(item, invertNavigationDirection(event));
        };

        focusChangedCallback = [this]([[maybe_unused]] Item &item) {
            if (focus) {
                set_value(focusedRecordPath);
            }
            OnFocusChangedCallback();
            return true;
        };

        auto onListItemActivate = []([[maybe_unused]] const db::multimedia_files::MultimediaFilesRecord &record) {
            return false;
        };
        auto onListItemFocusAcquire = [this](const db::multimedia_files::MultimediaFilesRecord &record) {
            focusedRecordPath = record.fileInfo.path;
            onValueChange(focusedRecordPath);
            return true;
        };

        songsModel->createData(onListItemActivate, onListItemFocusAcquire);
        list->rebuildList(listview::RebuildType::Full);

        getValue = [this]() {
            this->settingsModel.setValue(focusedRecordPath);
        };
        setValue = [this]() { focusedRecordPath = this->settingsModel.getValue(); };
    }

    auto SongsListViewItem::value() const -> UTF8
    {
        return focusedRecordPath;
    }

    auto SongsListViewItem::set_value(const UTF8 &value) -> void
    {
        focusedRecordPath = value;
    }

    auto SongsListViewItem::set_on_value_change_cb(std::function<void(const UTF8 &)> &&cb) -> void
    {
        onValueChange = std::move(cb);
    }

    auto SongsListViewItem::rearrangeBaseLayout() -> void
    {
        /* Hack enabling adding ListViewWithLabels to object of type BellSideListItemWithCallback
         * without rewriting big part of GUI. Be careful while calling methods from BellBaseLayout
         * inside this widget, as they might no longer work because of this! */
        body->erase(body->firstBox);
        body->erase(body->centerBox);
        body->erase(body->lastBox);
    }
} // namespace gui

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

#pragma once

#include <common/widgets/BellSideListItemWithCallbacks.hpp>
#include <common/models/AbstractSettingsModel.hpp>

namespace app
{
    class SongsModel;
}

namespace gui
{
    class ListViewWithLabels;

    class SongsListViewItem : public gui::BellSideListItemWithCallbacks
    {
      public:
        SongsListViewItem(const std::string &description,
                          AbstractSettingsModel<UTF8> &settingsModel,
                          std::shared_ptr<app::SongsModel> songsModel);

        [[nodiscard]] auto value() const -> UTF8;
        auto set_value(const UTF8 &value) -> void;
        auto set_on_value_change_cb(std::function<void(const UTF8 &)> &&cb) -> void;

      private:
        auto rearrangeBaseLayout() -> void;

        gui::AbstractSettingsModel<UTF8> &settingsModel;
        std::shared_ptr<app::SongsModel> songsModel;
        ListViewWithLabels *list{nullptr};
        std::function<void(const UTF8 &)> onValueChange;
        std::string focusedRecordPath;
    };
} // namespace gui

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

#include "BellSettingsLanguageWindow.hpp"


@@ 24,7 24,7 @@ namespace gui
        header->setTitleVisibility(false);
        navBar->setVisible(false);

        body = new BellBaseLayout(this, 0, 0, style::window_width, style::window_height, true);
        body = new BellBaseLayout(this, 0, 0, style::window_width, style::window_height);

        auto topMessage = new TextFixedSize(body->firstBox);
        topMessage->setMaximumSize(style::bell_base_layout::w, style::bell_base_layout::outer_layouts_h);

M products/BellHybrid/apps/common/include/common/models/SongsModel.hpp => products/BellHybrid/apps/common/include/common/models/SongsModel.hpp +24 -17
@@ 16,32 16,25 @@ namespace app
                          public gui::ListItemProvider
    {
      public:
        virtual ~SongsProvider() = default;
        using OnActivateCallback =
            std::function<bool(const db::multimedia_files::MultimediaFilesRecord &selectedSound)>;
        using OnFocusAcquireCallback =
            std::function<bool(const db::multimedia_files::MultimediaFilesRecord &focusedSound)>;

        explicit SongsProvider(ApplicationCommon *application);
        virtual void createData(OnActivateCallback activateCallback) = 0;
        virtual ~SongsProvider() = default;

        virtual auto createData(OnActivateCallback activateCallback, OnFocusAcquireCallback focusChangeCallback)
            -> void = 0;
    };

    class SongsModel : public SongsProvider
    {
      private:
        ApplicationCommon *application;
        std::unique_ptr<AbstractSoundsRepository> songsRepository;
        LabelsWithPaths pathPrefixes;
        OnActivateCallback activateCallback{nullptr};

        bool onMusicListRetrieved(const std::vector<db::multimedia_files::MultimediaFilesRecord> &records,
                                  unsigned int repoRecordsCount);
        [[nodiscard]] bool updateRecords(std::vector<db::multimedia_files::MultimediaFilesRecord> records) override;
        gui::ListLabel getLabelFromPath(const std::string &path);

      public:
        virtual ~SongsModel() = default;

        SongsModel(ApplicationCommon *application,
                   std::unique_ptr<AbstractSoundsRepository> soundsRepository,
                   const LabelsWithPaths &pathPrefixes);
                   const LabelsWithPaths &pathPrefixes = {});
        virtual ~SongsModel() = default;

        unsigned int requestRecordsCount() override;



@@ 51,8 44,22 @@ namespace app

        void requestRecords(std::uint32_t offset, std::uint32_t limit) override;

        void createData(OnActivateCallback activateCallback) override;
        void createData(OnActivateCallback activateCallback        = nullptr,
                        OnFocusAcquireCallback focusChangeCallback = nullptr) override;
        void updateRecordsCount();
        bool nextRecordExist(gui::Order order);

      private:
        bool onMusicListRetrieved(const std::vector<db::multimedia_files::MultimediaFilesRecord> &records,
                                  unsigned int repoRecordsCount);
        [[nodiscard]] bool updateRecords(std::vector<db::multimedia_files::MultimediaFilesRecord> records) override;
        gui::ListLabel getLabelFromPath(const std::string &path);

        ApplicationCommon *application;
        std::unique_ptr<AbstractSoundsRepository> songsRepository;
        LabelsWithPaths pathPrefixes;
        std::string currentRecordPath;
        OnActivateCallback activateCallback{nullptr};
        OnFocusAcquireCallback focusAcquireCallback{nullptr};
    };
} // namespace app

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

#pragma once


@@ 16,7 16,6 @@ namespace gui::option
{
    class OptionBellMenu : public option::Base
    {

      protected:
        UTF8 text;
        std::function<bool(Item &)> activatedCallback    = nullptr;

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

#pragma once


@@ 7,11 7,11 @@

namespace gui
{

    class BellSideListItemWithCallbacks : public BellSideListItem
    {
      public:
        explicit BellSideListItemWithCallbacks(const std::string &description);
        explicit BellSideListItemWithCallbacks(
            const std::string &description, BellBaseLayout::LayoutType type = BellBaseLayout::LayoutType::WithArrows);
        /// Fetch value from the list item and perform custom action.
        std::function<void()> getValue;
        /// Set list item's value and perform custom action.


@@ 26,5 26,4 @@ namespace gui
        void OnFocusChangedCallback();
        bool OnInputCallback(const InputEvent &inputEvent);
    };

} // namespace gui

M products/BellHybrid/apps/common/include/common/widgets/ListViewWithLabels.hpp => products/BellHybrid/apps/common/include/common/widgets/ListViewWithLabels.hpp +0 -1
@@ 40,5 40,4 @@ namespace gui
        std::uint32_t itemsOnPage{0};
        bool labelAdded{false};
    };

} // namespace gui

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

#pragma once


@@ 11,8 11,6 @@ namespace app::list_items
{
    class NumericWithBar : public details::ListItemBaseWithBar<gui::U8IntegerSpinner>
    {
        gui::ArcProgressBar *progress = nullptr;

      public:
        NumericWithBar(gui::U8IntegerSpinner::range &&range,
                       gui::AbstractSettingsModel<gui::U8IntegerSpinner::value_type> &model,

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

#include <module-gui/gui/input/InputEvent.hpp>


@@ 7,8 7,9 @@

namespace gui
{

    gui::BellSideListItemWithCallbacks::BellSideListItemWithCallbacks(const std::string &description)
    gui::BellSideListItemWithCallbacks::BellSideListItemWithCallbacks(const std::string &description,
                                                                      BellBaseLayout::LayoutType type)
        : BellSideListItem(type)
    {
        setupTopTextBox(description);
        focusChangedCallback = [&](Item &) {

M products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutClassic.cpp => products/BellHybrid/apps/common/src/layouts/HomeScreenLayoutClassic.cpp +2 -1
@@ 33,7 33,8 @@ namespace gui
{
    HomeScreenLayoutClassic::HomeScreenLayoutClassic(std::string name)
        : BaseHomeScreenLayoutProvider(std::move(name)),
          BellBaseLayout(nullptr, 0, 0, style::window_width, style::window_height, false)
          BellBaseLayout(
              nullptr, 0, 0, style::window_width, style::window_height, BellBaseLayout::LayoutType::WithoutArrows)
    {
        buildInterface();
    }

M products/BellHybrid/apps/common/src/models/SongsModel.cpp => products/BellHybrid/apps/common/src/models/SongsModel.cpp +16 -14
@@ 16,10 16,10 @@ namespace app
          application(application), songsRepository{std::move(soundsRepository)}, pathPrefixes{pathPrefixes}
    {}

    void SongsModel::createData(OnActivateCallback callback)
    void SongsModel::createData(OnActivateCallback onActivate, OnFocusAcquireCallback onFocusAcquire)
    {
        activateCallback = callback;

        activateCallback    = std::move(onActivate);
        focusAcquireCallback = std::move(onFocusAcquire);
        songsRepository->init();
    }



@@ 40,30 40,33 @@ namespace app

    bool SongsModel::nextRecordExist(gui::Order order)
    {
        const auto getOppositeOrder = [order]() {
            return order == gui::Order::Next ? gui::Order::Previous : gui::Order::Next;
        };

        auto exist = getRecord(order) != nullptr;
        getRecord(getOppositeOrder());
        getRecord(~order);
        return exist;
    }

    gui::ListItem *SongsModel::getItem(gui::Order order)
    {
        const auto sound = getRecord(order);
        if (!sound) {
        if (sound == nullptr) {
            return nullptr;
        }

        auto item = gui::option::LabelOption{getLabelFromPath(sound->fileInfo.path),
                                             sound->tags.title,
                                             [=]([[maybe_unused]] gui::Item &item) {
                                                 activateCallback(*sound);
                                             [this, sound]([[maybe_unused]] gui::Item &item) {
                                                 if (activateCallback) {
                                                     return activateCallback(*sound);
                                                 }
                                                 return true;
                                             },
                                             [this, sound](gui::Item &item) {
                                                 if (focusAcquireCallback && item.focus) {
                                                     return focusAcquireCallback(*sound);
                                                 }
                                                 return true;
                                             },
                                             []([[maybe_unused]] gui::Item &item) { return true; },
                                             nullptr};

        return item.build();
    }



@@ 101,5 104,4 @@ namespace app
        }
        return std::nullopt;
    }

} // namespace app

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

#include "common/options/BellOptionWithDescriptionWindow.hpp"


@@ 44,7 44,8 @@ namespace gui
        header->setTitleVisibility(false);
        navBar->setVisible(false);

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

        optionsList = new gui::ListView(body->lastBox, 0, 0, 0, 0, optionsModel, listview::ScrollBarType::None);

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

#include "common/options/BellShortOptionWindow.hpp"


@@ 35,7 35,8 @@ namespace gui
        header->setTitleVisibility(false);
        navBar->setVisible(false);

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

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

M products/BellHybrid/apps/common/src/widgets/LabelListItem.cpp => products/BellHybrid/apps/common/src/widgets/LabelListItem.cpp +1 -2
@@ 11,7 11,7 @@ namespace

namespace gui
{
    LabelListItem::LabelListItem(ListLabel label) : label{label}
    LabelListItem::LabelListItem(ListLabel label) : label{std::move(label)}
    {}

    ListLabel LabelListItem::getLabel()


@@ 47,5 47,4 @@ namespace gui
        };
        activeItem = false;
    }

} // namespace gui

M products/BellHybrid/apps/common/src/widgets/LabelOption.cpp => products/BellHybrid/apps/common/src/widgets/LabelOption.cpp +2 -3
@@ 7,13 7,13 @@

namespace gui::option
{

    LabelOption::LabelOption(ListLabel label,
                             const UTF8 &text,
                             std::function<bool(Item &)> activatedCallback,
                             std::function<bool(Item &)> focusChangedCallback,
                             gui::AppWindow *app)
        : OptionBellMenu(text, std::move(activatedCallback), std::move(focusChangedCallback), app), label(label)
        : OptionBellMenu(text, std::move(activatedCallback), std::move(focusChangedCallback), app),
          label(std::move(label))
    {}

    auto LabelOption::build() const -> ListItem *


@@ 22,5 22,4 @@ namespace gui::option
        OptionBellMenu::prepareListItem(labelItem);
        return labelItem;
    }

} // namespace gui::option

M products/BellHybrid/apps/common/src/widgets/ListViewWithLabels.cpp => products/BellHybrid/apps/common/src/widgets/ListViewWithLabels.cpp +5 -5
@@ 29,7 29,7 @@ namespace gui
        itemsOnPage     = 0;
        labelAdded      = false;

        ListItem *item = nullptr;
        ListItem *item;
        while ((item = provider->getItem(getOrderFromDirection())) != nullptr) {
            /* If direction is top-to-bottom, add label mark before adding relaxation item. */
            if (direction == listview::Direction::Bottom) {


@@ 64,7 64,7 @@ namespace gui
    LabelMarkerItem *ListViewWithLabels::createMarkerItem(ListLabel label)
    {
        if (label.has_value()) {
            const auto labelString = UTF8(utils::translate(label.value()));
            const auto &labelString = UTF8(utils::translate(label.value()));
            return new LabelMarkerItem(labelString);
        }
        return new LabelMarkerItem(UTF8(""));


@@ 106,7 106,8 @@ namespace gui
                }
            }
            else {
                const auto songsProvider = dynamic_cast<app::SongsModel *>(provider.get());
                /* This is bad, as it limits usage of this widget to just SongsModel */
                const auto songsProvider = std::dynamic_pointer_cast<app::SongsModel>(provider);
                if (songsProvider == nullptr) {
                    break;
                }


@@ 138,9 139,8 @@ namespace gui

    void ListViewWithLabels::updateState(ListLabel marker)
    {
        currentMarker = marker;
        currentMarker = std::move(marker);
        itemsOnPage++;
        labelAdded = true;
    }

} // namespace gui

M products/BellHybrid/apps/common/src/windows/BellBatteryStatusWindow.cpp => products/BellHybrid/apps/common/src/windows/BellBatteryStatusWindow.cpp +2 -1
@@ 49,7 49,8 @@ namespace gui
        header->setTitleVisibility(false);
        navBar->setVisible(false);

        body = new BellBaseLayout(this, 0, 0, style::window_width, style::window_height, false);
        body = new BellBaseLayout(
            this, 0, 0, style::window_width, style::window_height, BellBaseLayout::LayoutType::WithoutArrows);

        topDescription = new TextFixedSize(body->firstBox);
        topDescription->setMinimumSize(style::bell_base_layout::outer_layouts_w,

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

#include "windows/BellWelcomeWindow.hpp"


@@ 28,7 28,8 @@ namespace gui
        header->setTitleVisibility(false);
        navBar->setVisible(false);

        body = new BellBaseLayout(this, 0, 0, style::window_width, style::window_height, false);
        body = new BellBaseLayout(
            this, 0, 0, style::window_width, style::window_height, BellBaseLayout::LayoutType::WithoutArrows);

        auto muditaLogo = new ImageBox(body->firstBox, new Image(this->icon, ImageTypeSpecifier::W_G));
        muditaLogo->setMinimumSizeToFitImage();