~aleteoryx/muditaos

8856a6564170dcb8714e2865f56d7fa93950d8d2 — Mateusz Grzegorzek 5 years ago 4a82614
[EGD-4995] Add changing passcode windows flow

Implement changing passcode windows flow
31 files changed, 843 insertions(+), 317 deletions(-)

A image/assets/images/big_circle_placeholder.vpi
M image/assets/lang/English.json
M image/user/db/settings_v2_002.sql
M module-apps/Application.cpp
M module-apps/Application.hpp
M module-apps/application-desktop/CMakeLists.txt
M module-apps/application-desktop/data/AppDesktopStyle.hpp
M module-apps/application-desktop/widgets/PinHash.hpp
M module-apps/application-desktop/widgets/PinLock.hpp
M module-apps/application-desktop/widgets/PinLockHandler.cpp
A module-apps/application-desktop/windows/LockWindow.cpp
A module-apps/application-desktop/windows/LockWindow.hpp
M module-apps/application-desktop/windows/PinLockBaseWindow.cpp
M module-apps/application-desktop/windows/PinLockBaseWindow.hpp
A module-apps/application-desktop/windows/ScreenLockBaseBox.cpp
A module-apps/application-desktop/windows/ScreenLockBaseBox.hpp
M module-apps/application-desktop/windows/ScreenLockBox.cpp
M module-apps/application-desktop/windows/ScreenLockBox.hpp
M module-apps/application-phonebook/ApplicationPhonebook.hpp
M module-apps/application-settings-new/ApplicationSettings.cpp
M module-apps/application-settings-new/ApplicationSettings.hpp
M module-apps/application-settings-new/CMakeLists.txt
A module-apps/application-settings-new/data/ChangePasscodeData.hpp
A module-apps/application-settings-new/widgets/ChangePasscodeLockHandler.cpp
A module-apps/application-settings-new/widgets/ChangePasscodeLockHandler.hpp
A module-apps/application-settings-new/windows/ChangePasscodeWindow.cpp
A module-apps/application-settings-new/windows/ChangePasscodeWindow.hpp
M module-apps/application-settings-new/windows/SecurityMainWindow.cpp
M module-apps/application-settings-new/windows/SecurityMainWindow.hpp
M module-apps/windows/Dialog.hpp
M module-services/service-db/agents/settings/SystemSettings.hpp
A image/assets/images/big_circle_placeholder.vpi => image/assets/images/big_circle_placeholder.vpi +0 -0
M image/assets/lang/English.json => image/assets/lang/English.json +6 -0
@@ 348,6 348,12 @@
  "app_settings_toggle_off": "OFF",
  "app_settings_security_lock_screen_passcode": "Lock screen passcode",
  "app_settings_security_change_passcode": "Change passcode",
  "app_settings_security_type_current_passcode": "Type current passcode",
  "app_settings_security_enter_new_passcode": "Enter new passcode",
  "app_settings_security_confirm_new_passcode": "Confirm new passcode",
  "app_settings_security_wrong_passcode": "Wrong passcode!",
  "app_settings_security_passcode_changed_successfully": "Passcode changed successfully!",
  "app_settings_security_passcode_disabled": "Passcode disabled!",
  "app_phonebook_title_main": "Contacts",
  "app_phonebook_search_win_contacts": "Contacts",
  "common_search_uc": "Search",

M image/user/db/settings_v2_002.sql => image/user/db/settings_v2_002.sql +1 -0
@@ 11,6 11,7 @@ INSERT OR IGNORE INTO settings_tab (path, value) VALUES
    ('gs_time_date_format', '1'),
    ('gs_active_sim', 'SIM1'),
    ('gs_lock_pass_hash', '3333'),
    ('gs_lock_screen_passcode_on', '1'),
    ('gs_lock_time', '30000'),
    ('gs_display_language', 'English'),
    ('gs_input_language', 'English');

M module-apps/Application.cpp => module-apps/Application.cpp +15 -0
@@ 494,6 494,10 @@ namespace app
        if (startInBackground) {
            setState(State::ACTIVE_BACKGROUND);
        }

        settings->registerValueChange(
            settings::SystemProperties::lockScreenPasscodeIsOn,
            [this](const std::string &value) { setLockScreenPasscodeOn(utils::getNumericValue<bool>(value)); });
        return sys::ReturnCodes::Success;
    }



@@ 709,4 713,15 @@ namespace app
    {
        callbackStorage->removeAll(receiver);
    }

    void Application::setLockScreenPasscodeOn(bool screenPasscodeOn) noexcept
    {
        lockScreenPasscodeIsOn = screenPasscodeOn;
        settings->setValue(settings::SystemProperties::lockScreenPasscodeIsOn, std::to_string(lockScreenPasscodeIsOn));
    }

    bool Application::isLockScreenPasscodeOn() const noexcept
    {
        return lockScreenPasscodeIsOn;
    }
} /* namespace app */

M module-apps/Application.hpp => module-apps/Application.hpp +3 -0
@@ 161,6 161,7 @@ namespace app
      private:
        std::string default_window;
        State state = State::DEACTIVATED;
        bool lockScreenPasscodeIsOn;

        sys::MessagePointer handleSignalStrengthUpdate(sys::Message *msgl);
        sys::MessagePointer handleNetworkAccessTechnologyUpdate(sys::Message *msgl);


@@ 375,6 376,8 @@ namespace app

      public:
        bool isTimeFormat12() const noexcept;
        void setLockScreenPasscodeOn(bool screenPasscodeOn) noexcept;
        bool isLockScreenPasscodeOn() const noexcept;
    };

    /// Parameter pack used by application launch action.

M module-apps/application-desktop/CMakeLists.txt => module-apps/application-desktop/CMakeLists.txt +4 -0
@@ 33,6 33,8 @@ target_sources( ${PROJECT_NAME}
		"${CMAKE_CURRENT_LIST_DIR}/windows/MmiPullWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/MmiPushWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/MmiInternalMsgWindow.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/ScreenLockBaseBox.cpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/LockWindow.cpp"
	PUBLIC
		"${CMAKE_CURRENT_LIST_DIR}/ApplicationDesktop.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/data/LockPhoneData.hpp"


@@ 59,6 61,8 @@ target_sources( ${PROJECT_NAME}
		"${CMAKE_CURRENT_LIST_DIR}/windows/MmiPullWindow.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/MmiPushWindow.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/MmiInternalMsgWindow.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/ScreenLockBaseBox.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/windows/LockWindow.hpp"
)

target_link_libraries(${PROJECT_NAME}

M module-apps/application-desktop/data/AppDesktopStyle.hpp => module-apps/application-desktop/data/AppDesktopStyle.hpp +15 -0
@@ 3,6 3,8 @@

#pragma once

#include "gui/widgets/Style.hpp"

namespace style::window::pin_lock
{
    namespace image


@@ 62,3 64,16 @@ namespace style::window::pin_lock
    } // namespace secondary_text

} // namespace style::window::pin_lock

namespace style::window::screen_pin_lock
{
    namespace pin_label
    {
        constexpr inline auto y = 248;
    } // namespace pin_label

    namespace primary_text
    {
        constexpr inline auto y = 160;
    } // namespace primary_text
} // namespace style::window::screen_pin_lock

M module-apps/application-desktop/widgets/PinHash.hpp => module-apps/application-desktop/widgets/PinHash.hpp +6 -0
@@ 19,3 19,9 @@ template <> struct std::hash<std::vector<unsigned int>>
        return value;
    }
};

static inline uint32_t GetPinHash(const std::vector<unsigned int> &pin)
{
    static std::hash<std::vector<unsigned int>> hashEngine;
    return hashEngine(pin);
}

M module-apps/application-desktop/widgets/PinLock.hpp => module-apps/application-desktop/widgets/PinLock.hpp +5 -1
@@ 5,6 5,7 @@
#include <vector>
#include <string>
#include <functional>
#include <limits>

#include <module-utils/common_data/EventStore.hpp>



@@ 28,6 29,7 @@ namespace gui
            PasscodeInvalidRetryRequired,
            Blocked,
            NewPasscodeRequired,
            NewPasscodeInvalidRetryRequired,
            NewPasscodeConfirmRequired,
            NewPasscodeInvalid,
            ErrorOccurred


@@ 90,7 92,7 @@ namespace gui
        /// calls
        void activate();

        PinLock(Store::GSM::SIM sim, LockState state, LockType type, unsigned int value)
        PinLock(Store::GSM::SIM sim, LockState state, LockType type, unsigned int value = unlimitedNumOfAttempts)
            : sim{sim}, lockState{state}, lockType{type}, value{value}
        {}
        PinLock(const PinLock &other) = default;


@@ 109,6 111,7 @@ namespace gui
        bool autoActivate       = false;

        static constexpr unsigned int defaultPasscodeSize = 4;
        static constexpr unsigned int unlimitedNumOfAttempts = std::numeric_limits<unsigned int>::max();

        void setAutoActivate(bool _autoActivate)
        {


@@ 121,6 124,7 @@ namespace gui
        }

        friend class PinLockHandler;
        friend class ChangePasscodeLockHandler;
    };

} // namespace gui

M module-apps/application-desktop/widgets/PinLockHandler.cpp => module-apps/application-desktop/widgets/PinLockHandler.cpp +4 -8
@@ 32,13 32,13 @@ namespace gui
          simLock(Store::GSM::SIM::NONE, PinLock::LockState::Unlocked, PinLock::LockType::SimPin, default_attempts)
    {
        simLock.setPinSizeBounds(sim_min_passcode_size, sim_max_passcode_size);
        screenLock.setPinSizeBounds(default_screen_pin_size, default_screen_pin_size);
        screenLock.setAutoActivate(true);
    }

    void PinLockHandler::handleScreenPin(const std::vector<unsigned int> &pin)
    {
        std::hash<std::vector<unsigned int>> hashEngine;
        uint32_t hash = hashEngine(pin);
        const uint32_t hash = GetPinHash(pin);
        screenLock.value--;
        if (hash == app->getLockPassHash()) {
            screenLock.lockState = gui::PinLock::LockState::Unlocked;


@@ 255,12 255,8 @@ namespace gui

    void PinLockHandler::unlockScreen()
    {
        if (getStrongestLock().isType(PinLock::LockType::Screen)) {
            unsigned int pinSize = app->getLockPassHash() == 0 ? screen_nopin_size : default_screen_pin_size;
            screenLock.setPinSizeBounds(pinSize, pinSize);
            if (screenLock.getMaxPinSize() == screen_nopin_size) {
                screenLock.lockState = gui::PinLock::LockState::Unlocked;
            }
        if (getStrongestLock().isType(PinLock::LockType::Screen) && !app->isLockScreenPasscodeOn()) {
            screenLock.lockState = gui::PinLock::LockState::Unlocked;
        }
        unlock();
    }

A module-apps/application-desktop/windows/LockWindow.cpp => module-apps/application-desktop/windows/LockWindow.cpp +120 -0
@@ 0,0 1,120 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "application-desktop/data/AppDesktopStyle.hpp"
#include "application-desktop/widgets/PinLock.hpp"
#include "FontManager.hpp"
#include <i18n/i18n.hpp>
#include "LockWindow.hpp"

namespace lock_style = style::window::pin_lock;

namespace gui
{
    void LockWindow::build()
    {
        buildBottomBar();
        buildTopBar();
        buildTitleBar();
        buildInfoTexts();
    }

    void LockWindow::buildInfoTexts()
    {
        using namespace style::window::pin_lock;

        primaryText = new Text(this, primary_text::x, primary_text::y, primary_text::w, primary_text::h);
        primaryText->setFont(style::window::font::medium);
        primaryText->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));

        secondaryText = new Text(this, secondary_text::x, secondary_text::y, secondary_text::w, secondary_text::h);
        secondaryText->setFont(style::window::font::medium);
        secondaryText->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));
    }

    void LockWindow::buildPinLabels(std::function<Rect *()> itemBuilder,
                                    unsigned int pinSize,
                                    unsigned int offsetX,
                                    unsigned int offsetY,
                                    unsigned int boxWidth)
    {
        pinLabelsBox = new gui::HBox(this, offsetX, offsetY, boxWidth, lock_style::pin_label::size);
        pinLabelsBox->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));

        if (pinSize == 0) {
            return;
        }

        for (uint32_t i = 0; i < pinSize; i++) {
            auto label = itemBuilder();
            label->setFilled(false);
            label->setBorderColor(gui::ColorFullBlack);
            label->setPenWidth(2);
            label->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
            label->setVisible(true);
            label->activeItem = false;
            pinLabelsBox->addWidget(label);
        }
    }

    void LockWindow::restore() noexcept
    {
        primaryText->setVisible(false);
        secondaryText->setVisible(false);
        pinLabelsBox->setVisible(false);
    }

    void LockWindow::setBottomBarWidgetsActive(bool left, bool center, bool right)
    {
        bottomBar->setActive(BottomBar::Side::LEFT, left);
        bottomBar->setActive(BottomBar::Side::CENTER, center);
        bottomBar->setActive(BottomBar::Side::RIGHT, right);
    }

    void LockWindow::setText(const std::string &value,
                             TextType type,
                             bool isReach,
                             text::RichTextParser::TokenMap tokens)
    {
        auto text = getText(type);
        text->setVisible(true);
        if (isReach) {
            TextFormat format(FontManager::getInstance().getFont(style::window::font::medium));
            text::RichTextParser rtParser;
            auto parsedText = rtParser.parse(utils::localize.get(value), &format, std::move(tokens));
            text->setText(std::move(parsedText));
        }
        else {
            text->setText(utils::localize.get(value));
        }
    }

    void LockWindow::setTitleBar(bool isVisible)
    {
        title->setVisible(isVisible);
        if (isVisible) {
            title->setEdges(RectangleEdge::Bottom);
        }
        else {
            title->clear();
            title->setEdges(RectangleEdge::None);
        }
    }

    void LockWindow::buildBottomBar()
    {
        bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get(style::strings::common::confirm));
        bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get(style::strings::common::back));
    }

    auto LockWindow::getText(TextType type) noexcept -> gui::Text *
    {
        if (type == TextType::Title) {
            return title;
        }
        else if (type == TextType::Primary) {
            return primaryText;
        }
        return secondaryText;
    }
} // namespace gui

A module-apps/application-desktop/windows/LockWindow.hpp => module-apps/application-desktop/windows/LockWindow.hpp +66 -0
@@ 0,0 1,66 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "AppWindow.hpp"
#include "RichTextParser.hpp"
#include "Text.hpp"

namespace gui
{
    class PinLock;
}

namespace gui
{
    class LockWindow : public AppWindow
    {
      public:
        enum class TextType
        {
            Title,
            Primary,
            Secondary
        };

        enum class Token
        {
            Sim,
            Attempts,
            Mins,
            CmeCode
        };

        LockWindow(app::Application *app, std::string name) : AppWindow(app, std::move(name))
        {}
        void build();
        void buildInfoTexts();
        void buildPinLabels(std::function<Rect *()> itemBuilder,
                            unsigned int pinSize,
                            unsigned int offsetX,
                            unsigned int offsetY,
                            unsigned int boxWidth);
        virtual void restore() noexcept;
        void setBottomBarWidgetsActive(bool left, bool center, bool right);
        void setText(const std::string &value,
                     TextType type,
                     bool isReach                          = false,
                     text::RichTextParser::TokenMap tokens = text::RichTextParser::TokenMap{});
        void setTitleBar(bool isVisible);

        std::unique_ptr<PinLock> lock = nullptr;
        gui::HBox *pinLabelsBox       = nullptr;
        gui::Text *primaryText        = nullptr;
        gui::Text *secondaryText      = nullptr;
        gui::Text *title              = nullptr;

      protected:
        virtual void buildBottomBar();
        virtual void buildTitleBar() = 0;
        virtual void buildTopBar()   = 0;

      private:
        [[nodiscard]] auto getText(TextType type) noexcept -> gui::Text *;
    };
} // namespace gui

M module-apps/application-desktop/windows/PinLockBaseWindow.cpp => module-apps/application-desktop/windows/PinLockBaseWindow.cpp +48 -133
@@ 1,37 1,65 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "PinLockBaseWindow.hpp"
#include "application-desktop/data/AppDesktopStyle.hpp"
#include "application-desktop/widgets/PinLock.hpp"
#include <i18n/i18n.hpp>

#include "FontManager.hpp"
#include "PinLockBaseWindow.hpp"

namespace lock_style = style::window::pin_lock;

namespace gui
{
    void PinLockBaseWindow::buildImages(const std::string &lockImg, const std::string &infoImg)
    {
        lockImage = new gui::Image(this, lock_style::image::x, lock_style::image::y, 0, 0, lockImg);
        infoImage = new gui::Image(this, lock_style::image::x, lock_style::image::y, 0, 0, infoImg);
    }

    void PinLockBaseWindow::build()
    auto PinLockBaseWindow::getToken(Token token) const -> std::string
    {
        buildBottomBar();
        buildTopBar();
        buildTitleBar();
        buildInfoTexts();
        if (token == Token::Sim) {
            return "$SIM";
        }
        else if (token == Token::Attempts) {
            return "$ATTEMPTS";
        }
        else if (token == Token::Mins) {
            return "$MINUTES";
        }
        else if (token == Token::CmeCode) {
            return "$CMECODE";
        }
        return std::string{};
    }

    void PinLockBaseWindow::restore() noexcept
    {
        LockWindow::restore();
        lockImage->setVisible(false);
        infoImage->setVisible(false);
        iceBox->setVisible(false);
    }

    void PinLockBaseWindow::setImagesVisible(bool lockImg, bool infoImg)
    {
        lockImage->setVisible(lockImg);
        infoImage->setVisible(infoImg);
    }

    void PinLockBaseWindow::setTitleBar(bool isVisible, bool isIceActive)
    {
        iceBox->setVisible(isIceActive);
        LockWindow::setTitleBar(isVisible);
    }

    void PinLockBaseWindow::buildBottomBar()
    {
        LockWindow::buildBottomBar();
        setBottomBarWidgetsActive(false, false, false);
        bottomBar->setText(BottomBar::Side::LEFT, utils::localize.get("app_desktop_emergency"));
        bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get(style::strings::common::confirm));
        bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get(style::strings::common::back));
    }
    void PinLockBaseWindow::buildTopBar()
    {
        topBar->setActive(TopBar::Elements::SIGNAL, true);
        topBar->setActive(TopBar::Elements::BATTERY, true);
        topBar->setActive(TopBar::Elements::LOCK, true);
    }

    void PinLockBaseWindow::buildTitleBar()
    {
        using namespace style::window::pin_lock;


@@ 62,124 90,11 @@ namespace gui
        title->setVisible(false);
        title->setPenWidth(2);
    }
    void PinLockBaseWindow::buildInfoTexts()
    {
        using namespace style::window::pin_lock;

        primaryText = new Text(this, primary_text::x, primary_text::y, primary_text::w, primary_text::h);
        primaryText->setFont(style::window::font::medium);
        primaryText->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));

        secondaryText = new Text(this, secondary_text::x, secondary_text::y, secondary_text::w, secondary_text::h);
        secondaryText->setFont(style::window::font::medium);
        secondaryText->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));
    }
    void PinLockBaseWindow::buildPinLabels(std::function<Rect *()> itemBuilder,
                                           unsigned int pinSize,
                                           unsigned int offsetX,
                                           unsigned int offsetY,
                                           unsigned int boxWidth)
    {
        pinLabelsBox = new gui::HBox(this, offsetX, offsetY, boxWidth, lock_style::pin_label::size);
        pinLabelsBox->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));

        if (pinSize == 0) {
            return;
        }

        for (uint32_t i = 0; i < pinSize; i++) {
            auto label = itemBuilder();
            label->setFilled(false);
            label->setBorderColor(gui::ColorFullBlack);
            label->setPenWidth(2);
            label->setAlignment(gui::Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
            label->setVisible(true);
            label->activeItem = false;
            pinLabelsBox->addWidget(label);
        }
    }
    void PinLockBaseWindow::buildImages(const std::string &lockImg, const std::string &infoImg)
    {
        lockImage = new gui::Image(this, lock_style::image::x, lock_style::image::y, 0, 0, lockImg);
        infoImage = new gui::Image(this, lock_style::image::x, lock_style::image::y, 0, 0, infoImg);
    }
    void PinLockBaseWindow::setBottomBarWidgetsActive(bool left, bool center, bool right)
    {
        bottomBar->setActive(BottomBar::Side::LEFT, left);
        bottomBar->setActive(BottomBar::Side::CENTER, center);
        bottomBar->setActive(BottomBar::Side::RIGHT, right);
    }
    void PinLockBaseWindow::setImagesVisible(bool lockImg, bool infoImg)
    {
        lockImage->setVisible(lockImg);
        infoImage->setVisible(infoImg);
    }

    void PinLockBaseWindow::setTitleBar(bool isVisible, bool isIceActive)
    {
        iceBox->setVisible(isIceActive);
        title->setVisible(isVisible);
        if (isVisible) {
            title->setEdges(RectangleEdge::Bottom);
        }
        else {
            title->clear();
            title->setEdges(RectangleEdge::None);
        }
    }

    void PinLockBaseWindow::setText(const std::string &value,
                                    TextType type,
                                    bool isReach,
                                    text::RichTextParser::TokenMap tokens)
    {
        auto text = getText(type);
        text->setVisible(true);
        if (isReach) {
            TextFormat format(FontManager::getInstance().getFont(style::window::font::medium));
            text::RichTextParser rtParser;
            auto parsedText = rtParser.parse(utils::localize.get(value), &format, std::move(tokens));
            text->setText(std::move(parsedText));
        }
        else {
            text->setText(utils::localize.get(value));
        }
    }

    auto PinLockBaseWindow::getText(TextType type) noexcept -> gui::Text *
    {
        if (type == TextType::Title) {
            return title;
        }
        else if (type == TextType::Primary) {
            return primaryText;
        }
        return secondaryText;
    }

    void PinLockBaseWindow::restore() noexcept
    {
        primaryText->setVisible(false);
        secondaryText->setVisible(false);
        lockImage->setVisible(false);
        infoImage->setVisible(false);
        pinLabelsBox->setVisible(false);
    }

    auto PinLockBaseWindow::getToken(Token token) const -> std::string
    void PinLockBaseWindow::buildTopBar()
    {
        if (token == Token::Sim) {
            return "$SIM";
        }
        else if (token == Token::Attempts) {
            return "$ATTEMPTS";
        }
        else if (token == Token::Mins) {
            return "$MINUTES";
        }
        else if (token == Token::CmeCode) {
            return "$CMECODE";
        }
        return std::string{};
        topBar->setActive(TopBar::Elements::SIGNAL, true);
        topBar->setActive(TopBar::Elements::BATTERY, true);
        topBar->setActive(TopBar::Elements::LOCK, true);
    }
} // namespace gui

M module-apps/application-desktop/windows/PinLockBaseWindow.hpp => module-apps/application-desktop/windows/PinLockBaseWindow.hpp +9 -51
@@ 3,70 3,28 @@

#pragma once

#include "AppWindow.hpp"
#include "Text.hpp"

#include "RichTextParser.hpp"
#include "LockWindow.hpp"

namespace gui
{
    class PinLock;
}

namespace gui
{
    class PinLockBaseWindow : public AppWindow
    class PinLockBaseWindow : public LockWindow
    {
      public:
        enum class TextType
        {
            Title,
            Primary,
            Secondary
        };

        enum class Token
        {
            Sim,
            Attempts,
            Mins,
            CmeCode
        };

        PinLockBaseWindow(app::Application *app, std::string name) : AppWindow(app, name)
        PinLockBaseWindow(app::Application *app, std::string name) : LockWindow(app, name)
        {}
        void build();
        void buildInfoTexts();
        void buildPinLabels(std::function<Rect *()> itemBuilder,
                            unsigned int pinSize,
                            unsigned int offsetX,
                            unsigned int offsetY,
                            unsigned int boxWidth);
        void buildImages(const std::string &lockImg, const std::string &infoImg);
        void setBottomBarWidgetsActive(bool left, bool center, bool right);
        [[nodiscard]] auto getToken(Token token) const -> std::string;
        void restore() noexcept override;
        void setImagesVisible(bool lockImg, bool infoImg);
        void setTitleBar(bool isVisible, bool isIceActive);
        void setText(const std::string &value,
                     TextType type,
                     bool isReach                          = false,
                     text::RichTextParser::TokenMap tokens = text::RichTextParser::TokenMap{});
        void restore() noexcept;
        [[nodiscard]] auto getToken(Token token) const -> std::string;

        gui::HBox *iceBox        = nullptr;
        gui::Text *title         = nullptr;
        gui::Text *primaryText   = nullptr;
        gui::Text *secondaryText = nullptr;
        gui::Image *lockImage = nullptr;
        gui::Image *infoImage = nullptr;
        gui::HBox *pinLabelsBox = nullptr;

        std::unique_ptr<PinLock> lock = nullptr;
        gui::Image *lockImage    = nullptr;

      private:
        void buildBottomBar();
        void buildTopBar();
        void buildTitleBar();
        [[nodiscard]] auto getText(TextType type) noexcept -> gui::Text *;
        void buildBottomBar() override;
        void buildTitleBar() override;
        void buildTopBar() override;
    };
} // namespace gui

A module-apps/application-desktop/windows/ScreenLockBaseBox.cpp => module-apps/application-desktop/windows/ScreenLockBaseBox.cpp +84 -0
@@ 0,0 1,84 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "application-desktop/data/AppDesktopStyle.hpp"
#include "application-desktop/widgets/PinLock.hpp"
#include "PinLockBaseWindow.hpp"
#include "ScreenLockBaseBox.hpp"

namespace label_style = style::window::pin_lock::pin_label;

namespace gui
{
    void ScreenLockBaseBox::buildLockBox(unsigned int pinSize)
    {
        buildPinLabels(pinSize);
    }

    void ScreenLockBaseBox::clear()
    {
        for (unsigned i = 0; i < pinLabels.size(); i++) {
            popChar(i);
        }
    }

    void ScreenLockBaseBox::popChar(unsigned int charNum)
    {
        if (charNum < pinLabels.size()) {
            pinLabels[charNum]->setVisibleState(false);
        }
    }

    void ScreenLockBaseBox::putChar(unsigned int charNum)
    {
        if (charNum < pinLabels.size()) {
            pinLabels[charNum]->setVisibleState(true);
        }
    }

    void ScreenLockBaseBox::buildPinLabels(unsigned int pinSize)
    {
        constexpr auto pinLabelWidth = style::window::default_body_width;
        pinLabels.clear();

        if (pinSize == 0) {
            return;
        }

        unsigned int singleLabelWidth        = label_style::size;
        unsigned int maxNoMarginsLabelsWidth = pinLabelWidth - pinSize * 2 * label_style::margin;

        if (pinSize * singleLabelWidth > maxNoMarginsLabelsWidth) {
            singleLabelWidth = maxNoMarginsLabelsWidth / pinSize;
        }

        auto itemBuilder = [this, singleLabelWidth]() {
            auto label = new PinLabel(nullptr, singleLabelWidth, label_style::size);
            label->setEdges(RectangleEdge::Bottom);
            label->setMargins(Margins(label_style::margin, 0, label_style::margin, 0));
            pinLabels.push_back(label);
            return label;
        };

        lockWindow->buildPinLabels(
            itemBuilder, pinSize, style::window::default_left_margin, label_style::y, pinLabelWidth);
        lockWindow->pinLabelsBox->setEdges(RectangleEdge::None);
    }

    ScreenLockBaseBox::PinLabel::PinLabel(Item *parent, uint32_t w, uint32_t h) : HBox(parent, 0, 0, w, h)
    {}

    void ScreenLockBaseBox::PinLabel::setVisibleState(bool isImageVisible)
    {
        if (isImageVisible && image == nullptr) {
            image = new gui::Image("dot_12px_hard_alpha_W_G");
            image->setVisible(true);
            image->activeItem = false;
            addWidget(image);
        }
        else if (!isImageVisible && image != nullptr) {
            erase(image);
            image = nullptr;
        }
    }
} // namespace gui

A module-apps/application-desktop/windows/ScreenLockBaseBox.hpp => module-apps/application-desktop/windows/ScreenLockBaseBox.hpp +43 -0
@@ 0,0 1,43 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "Image.hpp"
#include "PinLockBox.hpp"
#include "LockWindow.hpp"

namespace gui
{
    class ScreenLockBaseBox : public PinLockBox
    {
      public:
        ScreenLockBaseBox(LockWindow *lockBaseWindow) : lockWindow(lockBaseWindow)
        {}

        void buildLockBox(unsigned int pinSize) override;
        void clear() final;
        void popChar(unsigned int charNum) final;
        void putChar(unsigned int charNum) final;

      private:
        void buildPinLabels(unsigned int pinSize);
        void setVisibleStateBlocked()
        {}
        void setVisibleStateEnterPin(EnterPasscodeType type)
        {}
        void setVisibleStateInvalidPin(PasscodeErrorType type, unsigned int value)
        {}

        struct PinLabel : public HBox
        {
            PinLabel(Item *parent, uint32_t w, uint32_t h);
            void setVisibleState(bool isImageVisible);

            gui::Image *image = nullptr;
        };

        LockWindow *lockWindow;
        std::vector<PinLabel *> pinLabels;
    };
} // namespace gui

M module-apps/application-desktop/windows/ScreenLockBox.cpp => module-apps/application-desktop/windows/ScreenLockBox.cpp +16 -87
@@ 1,87 1,30 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ScreenLockBox.hpp"

#include "PinLockBaseWindow.hpp"
#include "application-desktop/widgets/PinLock.hpp"
#include "application-desktop/data/AppDesktopStyle.hpp"
#include "gui/widgets/Label.hpp"
#include "gui/widgets/Image.hpp"
#include <i18n/i18n.hpp>

namespace label_style = style::window::pin_lock::pin_label;
#include "ScreenLockBox.hpp"

namespace gui
{

    constexpr auto timeToUnlock = 10;

    ScreenLockBox::PinLabel::PinLabel(Item *parent, uint32_t w, uint32_t h) : HBox(parent, 0, 0, w, h)
    {}
    void ScreenLockBox::PinLabel::setVisibleState(bool isImageVisible)
    {
        if (isImageVisible && image == nullptr) {
            image = new gui::Image("dot_12px_hard_alpha_W_G");
            image->setVisible(true);
            image->activeItem = false;
            addWidget(image);
        }
        else if (!isImageVisible && image != nullptr) {
            erase(image);
            image = nullptr;
        }
    }

    void ScreenLockBox::popChar(unsigned int charNum)
    {
        if (charNum < pinLabels.size()) {
            pinLabels[charNum]->setVisibleState(false);
        }
    }
    void ScreenLockBox::putChar(unsigned int charNum)
    {
        if (charNum < pinLabels.size()) {
            pinLabels[charNum]->setVisibleState(true);
        }
    }
    void ScreenLockBox::buildLockBox(unsigned int pinSize)
    {
        LockWindow->buildImages("pin_lock", "pin_lock_info");
        ScreenLockBox::buildPinLabels(pinSize);
        ScreenLockBaseBox::buildLockBox(pinSize);
    }
    void ScreenLockBox::buildPinLabels(unsigned int pinSize)
    {
        constexpr auto pinLabelWidth = style::window::default_body_width;
        pinLabels.clear();

        if (pinSize == 0) {
            return;
        }

        unsigned int singleLabelWidth        = label_style::size;
        unsigned int maxNoMarginsLabelsWidth = pinLabelWidth - pinSize * 2 * label_style::margin;

        if (pinSize * singleLabelWidth > maxNoMarginsLabelsWidth) {
            singleLabelWidth = maxNoMarginsLabelsWidth / pinSize;
        }

        auto itemBuilder = [this, singleLabelWidth]() {
            auto label = new PinLabel(nullptr, singleLabelWidth, label_style::size);
            label->setEdges(RectangleEdge::Bottom);
            label->setMargins(Margins(label_style::margin, 0, label_style::margin, 0));
            pinLabels.push_back(label);
            return label;
        };

        LockWindow->buildPinLabels(
            itemBuilder, pinSize, style::window::default_left_margin, label_style::y, pinLabelWidth);
        LockWindow->pinLabelsBox->setEdges(RectangleEdge::None);
    void ScreenLockBox::setVisibleStateBlocked()
    {
        LockWindow->setText("app_desktop_screen_blocked_info", LockWindow::TextType::Primary);
        LockWindow->setImagesVisible(false, true);
        LockWindow->setBottomBarWidgetsActive(false, true, false);
    }

    void ScreenLockBox::setVisibleStateEnterPin(EnterPasscodeType type)
    {
        LockWindow->pinLabelsBox->setVisible(true);
        LockWindow->setText("app_desktop_screen_enter_passcode_to_unlock", PinLockBaseWindow::TextType::Primary, true);
        LockWindow->setText("app_desktop_screen_enter_passcode_to_unlock", LockWindow::TextType::Primary, true);
        LockWindow->setImagesVisible(true, false);
        LockWindow->setBottomBarWidgetsActive(true, false, true);
    }


@@ 93,18 36,17 @@ namespace gui
            LockWindow->setTitleBar(false, false);
            if (value == 1) {
                LockWindow->setText(
                    "app_desktop_screen_wrong_passcode_last_attempt", PinLockBaseWindow::TextType::Primary, true);
                    "app_desktop_screen_wrong_passcode_last_attempt", LockWindow::TextType::Primary, true);
                LockWindow->setText("app_desktop_screen_wrong_passcode_last_attempt_warning",
                                    PinLockBaseWindow::TextType::Secondary,
                                    LockWindow::TextType::Secondary,
                                    true,
                                    {{LockWindow->getToken(PinLockBaseWindow::Token::Mins), timeToUnlock}});
                                    {{LockWindow->getToken(LockWindow::Token::Mins), timeToUnlock}});
            }
            else {
                LockWindow->setText(
                    "app_desktop_screen_wrong_passcode",
                    PinLockBaseWindow::TextType::Primary,
                    true,
                    {{LockWindow->getToken(PinLockBaseWindow::Token::Attempts), static_cast<int>(value)}});
                LockWindow->setText("app_desktop_screen_wrong_passcode",
                                    LockWindow::TextType::Primary,
                                    true,
                                    {{LockWindow->getToken(LockWindow::Token::Attempts), static_cast<int>(value)}});
            }
            break;



@@ 118,17 60,4 @@ namespace gui
        LockWindow->setImagesVisible(false, true);
        LockWindow->setBottomBarWidgetsActive(false, true, true);
    }
    void ScreenLockBox::setVisibleStateBlocked()
    {
        LockWindow->setText("app_desktop_screen_blocked_info", PinLockBaseWindow::TextType::Primary);
        LockWindow->setImagesVisible(false, true);
        LockWindow->setBottomBarWidgetsActive(false, true, false);
    }

    void ScreenLockBox::clear()
    {
        for (unsigned i = 0; i < pinLabels.size(); i++) {
            popChar(i);
        }
    }
} // namespace gui

M module-apps/application-desktop/windows/ScreenLockBox.hpp => module-apps/application-desktop/windows/ScreenLockBox.hpp +7 -26
@@ 3,42 3,23 @@

#pragma once

#include "PinLockBox.hpp"
#include "BoxLayout.hpp"
#include "Image.hpp"
namespace gui
{
    class PinLockBaseWindow;
}
#include "PinLockBaseWindow.hpp"
#include "ScreenLockBaseBox.hpp"

namespace gui
{
    class ScreenLockBox : public PinLockBox
    class ScreenLockBox : public ScreenLockBaseBox
    {
      public:
        ScreenLockBox(PinLockBaseWindow *LockBaseWindow) : LockWindow(LockBaseWindow)
        ScreenLockBox(PinLockBaseWindow *LockBaseWindow) : ScreenLockBaseBox(LockBaseWindow), LockWindow(LockBaseWindow)
        {}

      private:
        struct PinLabel : public HBox
        {
            gui::Image *image = nullptr;
            PinLabel(Item *parent, uint32_t w, uint32_t h);
            void setVisibleState(bool isImageVisible);
        };

        std::vector<PinLabel *> pinLabels;

        PinLockBaseWindow *LockWindow;
        void popChar(unsigned int charNum) final;
        void putChar(unsigned int charNum) final;
        void clear() final;

        void buildLockBox(unsigned int pinSize) final;
        void setVisibleStateBlocked() final;
        void setVisibleStateEnterPin(EnterPasscodeType type) final;
        void setVisibleStateInvalidPin(PasscodeErrorType type, unsigned int value) final;
        void setVisibleStateBlocked() final;

        void buildLockBox(unsigned int pinSize) final;
        void buildPinLabels(unsigned int pinSize);
        PinLockBaseWindow *LockWindow;
    };
} // namespace gui

M module-apps/application-phonebook/ApplicationPhonebook.hpp => module-apps/application-phonebook/ApplicationPhonebook.hpp +0 -1
@@ 16,7 16,6 @@ namespace gui::window::name
    inline constexpr auto search                 = "Search";
    inline constexpr auto search_results         = "SearchResults";
    inline constexpr auto dialog_yes_no          = "DialogYesNo";
    inline constexpr auto dialog_confirm         = "DialogConfirm";
    inline constexpr auto dialog                 = "Dialog";
    inline constexpr auto dialog_yes_no_icon_txt = "DialogYesNoIconTxt";
    inline constexpr auto ice_contacts           = "IceContacts";

M module-apps/application-settings-new/ApplicationSettings.cpp => module-apps/application-settings-new/ApplicationSettings.cpp +17 -0
@@ 25,6 25,7 @@
#include "windows/QuotesMainWindow.hpp"
#include "windows/QuotesAddWindow.hpp"
#include "windows/SecurityMainWindow.hpp"
#include "windows/ChangePasscodeWindow.hpp"

#include "Dialog.hpp"



@@ 38,6 39,7 @@
#include <application-settings-new/data/BondedDevicesData.hpp>
#include <service-db/agents/settings/SystemSettings.hpp>
#include <application-settings-new/data/PhoneNameData.hpp>
#include <module-services/service-db/agents/settings/SystemSettings.hpp>

namespace app
{


@@ 145,6 147,10 @@ namespace app

        setActiveWindow(gui::name::window::main_window);

        settings->registerValueChange(::settings::SystemProperties::lockPassHash, [this](std::string value) {
            lockPassHash = utils::getNumericValue<unsigned int>(value);
        });

        return ret;
    }



@@ 221,6 227,12 @@ namespace app
        windowsFactory.attach(gui::window::name::security, [](Application *app, const std::string &name) {
            return std::make_unique<gui::SecurityMainWindow>(app);
        });
        windowsFactory.attach(gui::window::name::change_passcode, [](Application *app, const std::string &name) {
            return std::make_unique<gui::ChangePasscodeWindow>(app);
        });
        windowsFactory.attach(gui::window::name::dialog_confirm, [](Application *app, const std::string &name) {
            return std::make_unique<gui::DialogConfirm>(app, gui::window::name::dialog_confirm);
        });
    }

    void ApplicationSettingsNew::destroyUserInterface()


@@ 275,4 287,9 @@ namespace app
        }
    }

    void ApplicationSettingsNew::setLockPassHash(unsigned int value)
    {
        lockPassHash = value;
        settings->setValue(::settings::SystemProperties::lockPassHash, std::to_string(value));
    }
} /* namespace app */

M module-apps/application-settings-new/ApplicationSettings.hpp => module-apps/application-settings-new/ApplicationSettings.hpp +7 -0
@@ 42,6 42,7 @@ namespace gui::window::name
    inline constexpr auto all_operators      = "AllOperators";
    inline constexpr auto import_contacts    = "ImportContacts";
    inline constexpr auto dialog_settings    = "DialogSettings";
    inline constexpr auto change_passcode    = "ChangePasscode";

} // namespace gui::window::name



@@ 99,6 100,11 @@ namespace app
        void setVoLTEOn(bool value) override;
        bool getVoLTEOn() const noexcept override;
        void volteChanged(const std::string &value);
        [[nodiscard]] auto getLockPassHash() const noexcept -> unsigned int
        {
            return lockPassHash;
        }
        void setLockPassHash(unsigned int value);

      private:
        Store::GSM::SIM selectedSim   = Store::GSM::get()->selected;


@@ 106,6 112,7 @@ namespace app
        bsp::Board board              = bsp::Board::none;
        bool operatorsOn              = false;
        bool voLteStateOn             = false;
        unsigned int lockPassHash     = 0;
    };

    template <> struct ManifestTraits<ApplicationSettingsNew>

M module-apps/application-settings-new/CMakeLists.txt => module-apps/application-settings-new/CMakeLists.txt +4 -0
@@ 16,6 16,7 @@ target_sources( ${PROJECT_NAME}
    PRIVATE
        ApplicationSettings.cpp
        widgets/timeWidget.cpp
        widgets/ChangePasscodeLockHandler.cpp
        windows/SettingsMainWindow.cpp
        windows/AddDeviceWindow.cpp
        windows/AllDevicesWindow.cpp


@@ 39,9 40,11 @@ target_sources( ${PROJECT_NAME}
        windows/QuotesMainWindow.cpp
        windows/QuotesAddWindow.cpp
        windows/SecurityMainWindow.cpp
        windows/ChangePasscodeWindow.cpp

    PUBLIC
        ApplicationSettings.hpp
        widgets/ChangePasscodeLockHandler.hpp
        windows/SettingsMainWindow.hpp
        windows/BaseSettingsWindow.hpp
        windows/FontSizeWindow.hpp


@@ 55,6 58,7 @@ target_sources( ${PROJECT_NAME}
        widgets/SettingsStyle.hpp
        windows/AutolockWindow.hpp
        windows/WallpaperWindow.hpp
        windows/ChangePasscodeWindow.hpp
)

add_dependencies(${PROJECT_NAME} version)

A module-apps/application-settings-new/data/ChangePasscodeData.hpp => module-apps/application-settings-new/data/ChangePasscodeData.hpp +20 -0
@@ 0,0 1,20 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

enum class ChangePasscodeAction
{
    OnlyCheckCurrentPasscode,
    OnlyProvideNewPasscode,
    ChangeCurrentPasscode
};

class ChangePasscodeData : public gui::SwitchData
{
  public:
    explicit ChangePasscodeData(ChangePasscodeAction passcodeAction) : changePasscodeAction{passcodeAction}
    {}

    const ChangePasscodeAction changePasscodeAction;
};

A module-apps/application-settings-new/widgets/ChangePasscodeLockHandler.cpp => module-apps/application-settings-new/widgets/ChangePasscodeLockHandler.cpp +57 -0
@@ 0,0 1,57 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ChangePasscodeLockHandler.hpp"
#include "application-desktop/widgets/PinHash.hpp"

namespace gui
{
    ChangePasscodeLockHandler::ChangePasscodeLockHandler()
        : lock(Store::GSM::SIM::NONE, PinLock::LockState::PasscodeRequired, PinLock::LockType::Screen)
    {}

    PinLock::LockState ChangePasscodeLockHandler::checkPasscode(unsigned int currentLockPassHash)
    {
        return activateLock([this, currentLockPassHash](PinLock::LockType, const std::vector<unsigned int> &pin) {
            const auto hash = GetPinHash(pin);
            if (hash == currentLockPassHash) {
                lock.lockState = PinLock::LockState::NewPasscodeRequired;
            }
            else {
                lock.lockState = PinLock::LockState::PasscodeInvalidRetryRequired;
            }
        });
    }

    PinLock::LockState ChangePasscodeLockHandler::newPasscodeConfirmed()
    {
        return activateLock([this](PinLock::LockType, const std::vector<unsigned int> &pin) {
            const auto newPasscodeConfirmedHash = GetPinHash(pin);
            if (newPasscodeHash == newPasscodeConfirmedHash) {
                lock.lockState = PinLock::LockState::Unlocked;
            }
            else {
                lock.lockState = PinLock::LockState::NewPasscodeInvalid;
            }
        });
    }

    PinLock::LockState ChangePasscodeLockHandler::newPasscodeProvided()
    {
        return activateLock([this](PinLock::LockType, const std::vector<unsigned int> &pin) {
            if (pin.size() < lock.getMaxPinSize()) {
                lock.lockState = PinLock::LockState::NewPasscodeInvalidRetryRequired;
                return;
            }
            newPasscodeHash = GetPinHash(pin);
            lock.lockState  = PinLock::LockState::NewPasscodeConfirmRequired;
        });
    }

    PinLock::LockState ChangePasscodeLockHandler::activateLock(OnActivatedCallback onActivatedCallback)
    {
        lock.onActivatedCallback = onActivatedCallback;
        lock.activate();
        return lock.lockState;
    }
} // namespace gui

A module-apps/application-settings-new/widgets/ChangePasscodeLockHandler.hpp => module-apps/application-settings-new/widgets/ChangePasscodeLockHandler.hpp +34 -0
@@ 0,0 1,34 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "application-desktop/widgets/PinLock.hpp"

namespace gui
{
    class ChangePasscodeLockHandler
    {
      public:
        ChangePasscodeLockHandler();

        auto checkPasscode(unsigned int currentLockPassHash) -> PinLock::LockState;
        [[nodiscard]] auto getLock() -> PinLock &
        {
            return lock;
        }
        [[nodiscard]] auto getNewPasscodeHash() const noexcept -> unsigned int
        {
            return newPasscodeHash;
        }
        auto newPasscodeConfirmed() -> PinLock::LockState;
        auto newPasscodeProvided() -> PinLock::LockState;

      private:
        using OnActivatedCallback = std::function<void(PinLock::LockType type, const std::vector<unsigned int> &)>;
        auto activateLock(OnActivatedCallback onActivatedCallback) -> PinLock::LockState;

        PinLock lock;
        unsigned int newPasscodeHash;
    };
} // namespace gui

A module-apps/application-settings-new/windows/ChangePasscodeWindow.cpp => module-apps/application-settings-new/windows/ChangePasscodeWindow.cpp +191 -0
@@ 0,0 1,191 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "application-desktop/data/AppDesktopStyle.hpp"
#include "application-settings-new/ApplicationSettings.hpp"
#include "ChangePasscodeWindow.hpp"
#include "DialogMetadata.hpp"
#include "DialogMetadataMessage.hpp"
#include "windows/Dialog.hpp"

namespace lock_style        = style::window::pin_lock;
namespace screen_lock_style = style::window::screen_pin_lock;

namespace gui
{
    ChangePasscodeWindow::ChangePasscodeWindow(app::Application *app)
        : LockWindow(app, gui::window::name::change_passcode)
    {
        buildInterface();
    }

    auto ChangePasscodeWindow::onInput(const InputEvent &inputEvent) -> bool
    {
        auto &lock = lockHandler.getLock();
        if (lock.isState(PinLock::LockState::Unlocked) && inputEvent.isShortPress()) {
            application->returnToPreviousWindow();
        }
        if (!inputEvent.isShortPress()) {
            return AppWindow::onInput(inputEvent);
        }

        auto keyCodeNum = gui::toNumeric(inputEvent.keyCode);
        if (0 <= keyCodeNum && keyCodeNum <= 9 && lock.canPut()) {
            lockBox->putChar(lock.getCharCount());
            lock.putNextChar(keyCodeNum);
            return true;
        }
        else if (inputEvent.is(KeyCode::KEY_PND)) {
            lock.popChar();
            lockBox->popChar(lock.getCharCount());
            return true;
        }
        else if (inputEvent.is(KeyCode::KEY_ENTER)) {
            processPasscode();
            setVisibleState();
            return true;
        }
        return AppWindow::onInput(inputEvent);
    }

    void ChangePasscodeWindow::rebuild()
    {
        destroyInterface();
        buildInterface();
    }

    void ChangePasscodeWindow::buildBottomBar()
    {
        LockWindow::buildBottomBar();
        setBottomBarWidgetsActive(false, true, true);
    }

    void ChangePasscodeWindow::buildInterface()
    {
        AppWindow::buildInterface();
        LockWindow::build();

        lockBox = std::make_unique<ScreenLockBaseBox>(this);
        lockBox->buildLockBox(lockHandler.getLock().getMaxPinSize());
        primaryText->setPosition(screen_lock_style::primary_text::y, gui::Axis::Y);
        pinLabelsBox->setPosition(screen_lock_style::pin_label::y, gui::Axis::Y);
    }

    void ChangePasscodeWindow::buildTitleBar()
    {
        setTitle(utils::localize.get("app_settings_security_change_passcode"));
    }

    void ChangePasscodeWindow::buildTopBar()
    {
        topBar->setActive(TopBar::Elements::SIM, false);
        topBar->setActive(TopBar::Elements::LOCK, false);
        topBar->setActive(TopBar::Elements::BATTERY, false);
        topBar->setActive(TopBar::Elements::TIME, true);
    }

    void ChangePasscodeWindow::destroyInterface()
    {
        erase();
    }

    void ChangePasscodeWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        if (data != nullptr) {
            auto changePasscodeData = static_cast<ChangePasscodeData *>(data);
            changePasscodeAction    = changePasscodeData->changePasscodeAction;
            if (ChangePasscodeAction::OnlyProvideNewPasscode == changePasscodeAction) {
                lockState = PinLock::LockState::NewPasscodeRequired;
            }
        }
        setVisibleState();
    }

    void ChangePasscodeWindow::processPasscode()
    {
        switch (lockState) {
        case PinLock::LockState::PasscodeRequired:
        case PinLock::LockState::PasscodeInvalidRetryRequired: {
            auto app  = static_cast<app::ApplicationSettingsNew *>(application);
            lockState = lockHandler.checkPasscode(app->getLockPassHash());
            if (ChangePasscodeAction::OnlyCheckCurrentPasscode == changePasscodeAction &&
                lockState == PinLock::LockState::NewPasscodeRequired) {
                DialogMetadata meta;
                meta.icon   = "big_circle_placeholder";
                meta.text   = utils::localize.get("app_settings_security_passcode_disabled");
                meta.title  = utils::localize.get("app_settings_security_change_passcode");
                meta.action = [this]() {
                    application->switchWindow(gui::window::name::security);
                    return true;
                };
                application->setLockScreenPasscodeOn(false);
                application->switchWindow(gui::window::name::dialog_confirm,
                                          std::make_unique<gui::DialogMetadataMessage>(meta));
                return;
            }
            break;
        }
        case PinLock::LockState::NewPasscodeRequired:
        case PinLock::LockState::NewPasscodeInvalidRetryRequired: {
            lockState = lockHandler.newPasscodeProvided();
            break;
        }
        case PinLock::LockState::NewPasscodeConfirmRequired:
        case PinLock::LockState::NewPasscodeInvalid: {
            lockState = lockHandler.newPasscodeConfirmed();
            if (lockState == PinLock::LockState::Unlocked) {
                auto app = static_cast<app::ApplicationSettingsNew *>(application);
                app->setLockPassHash(lockHandler.getNewPasscodeHash());
            }
            break;
        }
        default:
            break;
        }
    }

    void ChangePasscodeWindow::setVisibleState()
    {
        lockBox->clear();
        switch (lockState) {
        case PinLock::LockState::PasscodeRequired: {
            setText("app_settings_security_type_current_passcode", LockWindow::TextType::Primary);
            secondaryText->setVisible(false);
            break;
        }
        case PinLock::LockState::NewPasscodeRequired: {
            setText("app_settings_security_enter_new_passcode", LockWindow::TextType::Primary);
            secondaryText->setVisible(false);
            break;
        }
        case PinLock::LockState::NewPasscodeConfirmRequired: {
            setText("app_settings_security_confirm_new_passcode", LockWindow::TextType::Primary);
            secondaryText->setVisible(false);
            break;
        }
        case PinLock::LockState::PasscodeInvalidRetryRequired:
        case PinLock::LockState::NewPasscodeInvalidRetryRequired:
        case PinLock::LockState::NewPasscodeInvalid: {
            setText("app_settings_security_wrong_passcode", LockWindow::TextType::Secondary);
            break;
        }
        case PinLock::LockState::Unlocked: {
            DialogMetadata meta;
            meta.icon   = "big_circle_placeholder";
            meta.text   = utils::localize.get("app_settings_security_passcode_changed_successfully");
            meta.title  = utils::localize.get("app_settings_security_change_passcode");
            meta.action = [this]() {
                application->switchWindow(gui::window::name::security);
                return true;
            };
            application->setLockScreenPasscodeOn(true);
            application->switchWindow(gui::window::name::dialog_confirm,
                                      std::make_unique<gui::DialogMetadataMessage>(meta));
            break;
        }
        default: {
            break;
        }
        }
    }
} // namespace gui

A module-apps/application-settings-new/windows/ChangePasscodeWindow.hpp => module-apps/application-settings-new/windows/ChangePasscodeWindow.hpp +35 -0
@@ 0,0 1,35 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include "application-desktop/windows/LockWindow.hpp"
#include "application-desktop/windows/ScreenLockBaseBox.hpp"
#include "application-settings-new/data/ChangePasscodeData.hpp"
#include "application-settings-new/widgets/ChangePasscodeLockHandler.hpp"

namespace gui
{
    class ChangePasscodeWindow : public LockWindow
    {
      public:
        explicit ChangePasscodeWindow(app::Application *app);
        bool onInput(const InputEvent &inputEvent) override;
        void rebuild() override;

      private:
        void buildBottomBar() override;
        void buildInterface() override;
        void buildTitleBar() override;
        void buildTopBar() override;
        void destroyInterface() override;
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        void processPasscode();
        void setVisibleState();

        ChangePasscodeAction changePasscodeAction;
        std::unique_ptr<ScreenLockBaseBox> lockBox = nullptr;
        PinLock::LockState lockState{PinLock::LockState::PasscodeRequired};
        ChangePasscodeLockHandler lockHandler;
    };
} /* namespace gui */

M module-apps/application-settings-new/windows/SecurityMainWindow.cpp => module-apps/application-settings-new/windows/SecurityMainWindow.cpp +19 -9
@@ 2,23 2,30 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "application-settings-new/ApplicationSettings.hpp"
#include "application-settings-new/data/ChangePasscodeData.hpp"
#include "module-apps/application-desktop/windows/Names.hpp"
#include "OptionSetting.hpp"
#include "SecurityMainWindow.hpp"

namespace gui
{
    SecurityMainWindow::SecurityMainWindow(app::Application *app) : BaseSettingsWindow(app, window::name::security)
    SecurityMainWindow::SecurityMainWindow(app::Application *app)
        : BaseSettingsWindow(app, window::name::security), lockScreenPasscodeIsOn(app->isLockScreenPasscodeOn())
    {}

    auto SecurityMainWindow::buildOptionsList() -> std::list<Option>
    {
        std::list<Option> optionList;

        optionList.emplace_back(std::make_unique<gui::option::OptionSettings>(
        optionList.emplace_back(std::make_unique<option::OptionSettings>(
            utils::translateI18("app_settings_security_lock_screen_passcode"),
            [=](Item &item) {
                lockScreenPasscodeOn = !lockScreenPasscodeOn;
                rebuildOptionList();
                lockScreenPasscodeIsOn = !lockScreenPasscodeIsOn;
                LOG_INFO("switching to %s page", window::name::change_passcode);
                auto data = lockScreenPasscodeIsOn
                                ? std::make_unique<ChangePasscodeData>(ChangePasscodeAction::OnlyProvideNewPasscode)
                                : std::make_unique<ChangePasscodeData>(ChangePasscodeAction::OnlyCheckCurrentPasscode);
                application->switchWindow(window::name::change_passcode, std::move(data));
                return true;
            },
            [=](Item &item) {


@@ 33,18 40,21 @@ namespace gui
                return true;
            },
            nullptr,
            lockScreenPasscodeOn ? gui::option::SettingRightItem::On : gui::option::SettingRightItem::Off));
            lockScreenPasscodeIsOn ? option::SettingRightItem::On : option::SettingRightItem::Off));

        if (lockScreenPasscodeOn) {
            optionList.emplace_back(std::make_unique<gui::option::OptionSettings>(
        if (lockScreenPasscodeIsOn) {
            optionList.emplace_back(std::make_unique<option::OptionSettings>(
                utils::translateI18("app_settings_security_change_passcode"),
                [=](Item &item) {
                    LOG_INFO("Not implemented");
                    LOG_INFO("switching to %s page", window::name::change_passcode);
                    application->switchWindow(
                        window::name::change_passcode,
                        std::make_unique<ChangePasscodeData>(ChangePasscodeAction::ChangeCurrentPasscode));
                    return true;
                },
                nullptr,
                nullptr,
                gui::option::SettingRightItem::ArrowWhite));
                option::SettingRightItem::ArrowWhite));
        }

        return optionList;

M module-apps/application-settings-new/windows/SecurityMainWindow.hpp => module-apps/application-settings-new/windows/SecurityMainWindow.hpp +1 -1
@@ 15,6 15,6 @@ namespace gui
      private:
        auto buildOptionsList() -> std::list<Option> override;

        bool lockScreenPasscodeOn = false;
        bool lockScreenPasscodeIsOn;
    };
} // namespace gui

M module-apps/windows/Dialog.hpp => module-apps/windows/Dialog.hpp +5 -0
@@ 8,6 8,11 @@
#include <functional>
#include <DialogMetadata.hpp>

namespace gui::window::name
{
    inline constexpr auto dialog_confirm = "DialogConfirm";
}; // namespace gui::window::name

namespace gui
{
    /// @brief base Dialog class

M module-services/service-db/agents/settings/SystemSettings.hpp => module-services/service-db/agents/settings/SystemSettings.hpp +1 -0
@@ 11,6 11,7 @@ namespace settings
        constexpr inline auto timeDateFormat  = "gs_time_date_format";
        constexpr inline auto activeSim       = "gs_active_sim";
        constexpr inline auto lockPassHash    = "gs_lock_pass_hash";
        constexpr inline auto lockScreenPasscodeIsOn = "gs_lock_screen_passcode_is_on";
        constexpr inline auto lockTime        = "gs_lock_time";
        constexpr inline auto displayLanguage = "gs_display_language";
        constexpr inline auto inputLanguage   = "gs_input_language";