~aleteoryx/muditaos

2abfbc74d69b9da99ee46f12d3a1395f0d928877 — tomaszkrosnowski 4 years ago 46e097b
[EGD-6041] Fix unlock windows behaviour

Fixed behaviour so the window acts as in Miro requirements and has 2
seconds timeout.
M image/assets/lang/English.json => image/assets/lang/English.json +1 -0
@@ 253,6 253,7 @@
  "sim_card_cant_connect": "<text>Cannot connect to <token>$SIM</token> card.<br></br>Please insert card.</text>",
  "sim_card_not_ready": "<text>Waiting for Modem to start.<br></br>This may take a moment.</text>",
  "app_desktop_press_to_unlock": "<text font='gt_pressura' size='27'>Press <b>Unlock</b> and then <b>#</b></text>",
  "app_desktop_press_to_complete_unlock": "<text font='gt_pressura' size='27'>Press <b>#</b> to unlock</text>",
  "app_desktop_unread_messages": "<text>Unread <b>messages</b></text>",
  "app_desktop_missed_calls": "<text>Missed <b>calls</b></text>",
  "app_desktop_menu_phone": "CALLS",

M module-apps/apps-common/popups/CMakeLists.txt => module-apps/apps-common/popups/CMakeLists.txt +1 -0
@@ 35,6 35,7 @@ target_sources(apps-common
		VolumeWindow.hpp
		WindowWithTimer.hpp
		data/PopupData.hpp
		lock-popups/PhoneLockedInfoData.hpp
		lock-popups/PhoneLockedInfoWindow.hpp
		lock-popups/PhoneLockedWindow.hpp
		lock-popups/PhoneLockInputWindow.hpp

M module-apps/apps-common/popups/WindowWithTimer.hpp => module-apps/apps-common/popups/WindowWithTimer.hpp +5 -3
@@ 8,13 8,11 @@

namespace gui
{
    inline constexpr auto defautTimeout = std::chrono::milliseconds{3000};
    inline constexpr auto defautTimeout = std::chrono::seconds{3};
    class WindowWithTimer : public gui::AppWindow
    {
      private:
        sys::TimerHandle popupTimer;
        void resetTimer();
        void detachTimerIfExists();

      public:
        explicit WindowWithTimer(app::Application *app,


@@ 24,5 22,9 @@ namespace gui
        ~WindowWithTimer() override;
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        bool onInput(const gui::InputEvent &inputEvent) override;

      protected:
        void detachTimerIfExists();
        void resetTimer();
    };
} // namespace gui

A module-apps/apps-common/popups/lock-popups/PhoneLockedInfoData.hpp => module-apps/apps-common/popups/lock-popups/PhoneLockedInfoData.hpp +39 -0
@@ 0,0 1,39 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <module-gui/gui/SwitchData.hpp>

///  @brief Switch data for PhoneLockedInfoWindow to specify the
///  proper init window stage of unlocking process
class PhoneLockedInfoData : public gui::SwitchData
{
  public:
    /// Enum descriging two possible unlocing stages:\n
    /// Idle stage means user has not started unlocking The device waits for
    /// user to press UNLOCK (Enter) button to start unlocking procedure.\n
    /// Waiting stage occurs when UNLOCK button is pressed and device
    /// waits for some time for the # button to be pressed to complete unlock.
    enum class Stage
    {
        Idle,
        Waiting
    };

    /// Constructor
    /// @param stage stage of unlocking carried in this switch data
    explicit PhoneLockedInfoData(Stage stage) : currentStage(std::move(stage))
    {}

    /// Returns the stage of unlocking carried in this switch data
    /// @return information carried by this switch data
    Stage getStage() const noexcept
    {
        return currentStage;
    }

  private:
    /// Current unlocking stage
    Stage currentStage;
};

M module-apps/apps-common/popups/lock-popups/PhoneLockedInfoWindow.cpp => module-apps/apps-common/popups/lock-popups/PhoneLockedInfoWindow.cpp +62 -8
@@ 10,28 10,80 @@

using namespace gui;

PhoneLockedInfoWindow::PhoneLockedInfoWindow(app::Application *app, const std::string &name) : AppWindow(app, name)
PhoneLockedInfoWindow::PhoneLockedInfoWindow(app::Application *app, const std::string &name)
    : WindowWithTimer(app, name, std::chrono::seconds(2))
{
    buildInterface();
}

void PhoneLockedInfoWindow::onBeforeShow(ShowMode mode, SwitchData *data)
void PhoneLockedInfoWindow::onBeforeShow([[maybe_unused]] ShowMode mode, SwitchData *data)
{
    bottomBar->setActive(BottomBar::Side::LEFT, true);
    bottomBar->setActive(BottomBar::Side::CENTER, false);
    bottomBar->setActive(BottomBar::Side::RIGHT, true);
    auto info = dynamic_cast<PhoneLockedInfoData *>(data);

    mStage = (info && info->getStage() == PhoneLockedInfoData::Stage::Waiting) ? PhoneLockedInfoData::Stage::Waiting
                                                                               : PhoneLockedInfoData::Stage::Idle;

    if (mStage == PhoneLockedInfoData::Stage::Waiting) {
        bottomBar->setActive(BottomBar::Side::LEFT, true);
        bottomBar->setActive(BottomBar::Side::CENTER, false);
        bottomBar->setActive(BottomBar::Side::RIGHT, true);
        infoIcon->text->setRichText(utils::translate("app_desktop_press_to_complete_unlock"));
    }
    else {
        bottomBar->setActive(BottomBar::Side::LEFT, true);
        bottomBar->setActive(BottomBar::Side::CENTER, true);
        bottomBar->setActive(BottomBar::Side::RIGHT, true);
        infoIcon->text->setRichText(utils::translate("app_desktop_press_to_unlock"));
    }

    WindowWithTimer::onBeforeShow(mode, data);
}

bool PhoneLockedInfoWindow::onInput(const InputEvent &inputEvent)
{
    if (inputEvent.isShortRelease(KeyCode::KEY_LF) && bottomBar->isActive(BottomBar::Side::LEFT)) {
    // Right key = go back
    if (inputEvent.isShortRelease(KeyCode::KEY_RF)) {
        detachTimerIfExists();
        application->returnToPreviousWindow();
        return true;
    }

    // Left key = SOS call, it should work all the time
    else if (inputEvent.isShortRelease(KeyCode::KEY_LF) && bottomBar->isActive(BottomBar::Side::LEFT)) {
        app::manager::Controller::sendAction(application,
                                             app::manager::actions::EmergencyDial,
                                             std::make_unique<SwitchData>(),
                                             app::manager::OnSwitchBehaviour::RunInBackground);
        return true;
    }
    return AppWindow::onInput(inputEvent);

    // Pnd key = go to PIN code screen
    else if (inputEvent.isShortRelease(KeyCode::KEY_PND) && mStage == PhoneLockedInfoData::Stage::Waiting) {
        detachTimerIfExists();
        application->returnToPreviousWindow();
        application->getPhoneLockSubject().unlock();
        return true;
    }

    // Enter key = start unlocking if we are in STARTING stage
    else if (inputEvent.isShortRelease(KeyCode::KEY_ENTER) && mStage == PhoneLockedInfoData::Stage::Idle) {
        mStage = PhoneLockedInfoData::Stage::Waiting;
        bottomBar->setActive(BottomBar::Side::CENTER, false);
        infoIcon->text->setRichText(utils::translate("app_desktop_press_to_complete_unlock"));
        resetTimer();
        return true;
    }

    // Any other key - reset timers and go to STARTING stage
    else if (inputEvent.isShortRelease() && mStage == PhoneLockedInfoData::Stage::Waiting) {
        mStage = PhoneLockedInfoData::Stage::Idle;
        bottomBar->setActive(BottomBar::Side::CENTER, true);
        infoIcon->text->setRichText(utils::translate("app_desktop_press_to_unlock"));
        resetTimer();
        return true;
    }

    return WindowWithTimer::onInput(inputEvent);
}

status_bar::Configuration PhoneLockedInfoWindow::configureStatusBar(status_bar::Configuration appConfiguration)


@@ 48,9 100,10 @@ status_bar::Configuration PhoneLockedInfoWindow::configureStatusBar(status_bar::

void PhoneLockedInfoWindow::buildInterface()
{
    AppWindow::buildInterface();
    WindowWithTimer::buildInterface();

    bottomBar->setText(BottomBar::Side::LEFT, utils::translate("app_desktop_emergency"));
    bottomBar->setText(BottomBar::Side::CENTER, utils::translate("app_desktop_unlock"));
    bottomBar->setText(BottomBar::Side::RIGHT, utils::translate("common_back"));

    infoIcon = new gui::Icon(this,


@@ 60,5 113,6 @@ void PhoneLockedInfoWindow::buildInterface()
                             style::window::default_body_height,
                             "unlock_icon_W_G",
                             utils::translate("app_desktop_press_to_unlock"));

    infoIcon->setAlignment(Alignment::Horizontal::Center);
}

M module-apps/apps-common/popups/lock-popups/PhoneLockedInfoWindow.hpp => module-apps/apps-common/popups/lock-popups/PhoneLockedInfoWindow.hpp +7 -4
@@ 3,22 3,25 @@

#pragma once

#include "PhoneLockedInfoData.hpp"
#include <module-apps/apps-common/popups/WindowWithTimer.hpp>
#include <AppWindow.hpp>
#include <Text.hpp>
#include <gui/widgets/Icon.hpp>

namespace gui
{
    class PhoneLockedInfoWindow : public AppWindow
    class PhoneLockedInfoWindow : public WindowWithTimer
    {
        Icon *infoIcon = nullptr;

      public:
        PhoneLockedInfoWindow(app::Application *app, const std::string &name);
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
        bool onInput(const InputEvent &inputEvent) override;

        void buildInterface() override;
        status_bar::Configuration configureStatusBar(status_bar::Configuration appConfiguration) override;

      private:
        PhoneLockedInfoData::Stage mStage = PhoneLockedInfoData::Stage::Idle;
        Icon *infoIcon                    = nullptr;
    };
} /* namespace gui */

M module-apps/apps-common/popups/lock-popups/PhoneLockedWindow.cpp => module-apps/apps-common/popups/lock-popups/PhoneLockedWindow.cpp +6 -49
@@ 2,6 2,7 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "PhoneLockedWindow.hpp"
#include "PhoneLockedInfoData.hpp"

#include <application-desktop/data/DesktopStyle.hpp>
#include <module-services/service-appmgr/service-appmgr/Controller.hpp>


@@ 10,26 11,6 @@

namespace gui
{
    bool PhoneLockedWindow::LockingTimer::storeEnter(const InputEvent &evt)
    {
        enterPressed    = evt.is(KeyCode::KEY_ENTER);
        unLockStartTime = xTaskGetTickCount();
        return enterPressed;
    }

    void PhoneLockedWindow::LockingTimer::clear() noexcept
    {
        enterPressed = false;
    }

    bool PhoneLockedWindow::LockingTimer::cached() noexcept
    {
        if (xTaskGetTickCount() - unLockStartTime >= unLockTime) {
            clear();
        }
        return enterPressed;
    }

    PhoneLockedWindow::PhoneLockedWindow(app::Application *app, const std::string &name)
        : AppWindow(app, name), notificationsModel(std::make_shared<NotificationsModel>())
    {


@@ 104,41 85,17 @@ namespace gui
        return AppWindow::onInput(inputEvent);
    }

    bool PhoneLockedWindow::processShortReleaseEvent(const InputEvent &inputEvent)
    {
        // if enter was pressed
        if (lockingTimer.cached() && inputEvent.is(KeyCode::KEY_PND)) {
            // if interval between enter and pnd keys is less than time defined for unlocking
            // display pin lock screen or simply refresh current window to update labels

            application->getPhoneLockSubject().unlock();
            return true;
        }
        else if (lockingTimer.storeEnter(inputEvent)) {
            return true;
        }
        // back not allowed on blocked screen
        else if (inputEvent.is(KeyCode::KEY_RF)) {
            application->switchWindow(gui::popup::window::phone_lock_info_window);
            return true;
        }
        // check if any of the lower inheritance onInput methods catch the event
        else if (AppWindow::onInput(inputEvent)) {
            return true;
        }

        application->switchWindow(gui::popup::window::phone_lock_info_window);

        return true;
    }

    bool PhoneLockedWindow::onInput(const InputEvent &inputEvent)
    {
        if (inputEvent.isLongRelease()) {
            return processLongReleaseEvent(inputEvent);
        }
        else if (inputEvent.isShortRelease()) {
            return processShortReleaseEvent(inputEvent);
            const auto requiredStage = (inputEvent.is(KeyCode::KEY_ENTER)) ? PhoneLockedInfoData::Stage::Waiting
                                                                           : PhoneLockedInfoData::Stage::Idle;
            application->switchWindow(gui::popup::window::phone_lock_info_window,
                                      std::make_unique<PhoneLockedInfoData>(requiredStage));
            return true;
        }
        return AppWindow::onInput(inputEvent);
    }

M module-apps/apps-common/popups/lock-popups/PhoneLockedWindow.hpp => module-apps/apps-common/popups/lock-popups/PhoneLockedWindow.hpp +0 -14
@@ 24,21 24,7 @@ namespace gui
        gui::ListView *notificationsList                            = nullptr;
        std::shared_ptr<gui::NotificationsModel> notificationsModel = nullptr;

        /// Locking timer on pressing enter
        class LockingTimer
        {
            bool enterPressed        = false;
            uint32_t unLockStartTime = 0;
            uint32_t unLockTime      = 3000;

          public:
            bool storeEnter(const InputEvent &evt);
            void clear() noexcept;
            bool cached() noexcept;
        } lockingTimer;

        bool processLongReleaseEvent(const InputEvent &inputEvent);
        bool processShortReleaseEvent(const InputEvent &inputEvent);

      public:
        PhoneLockedWindow(app::Application *app, const std::string &name);