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 => +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 => +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 => +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 => +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 => +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 => +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 => +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);