// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md // application manager #include "InputEvent.hpp" #include "service-appmgr/Controller.hpp" // module-gui #include "gui/widgets/BottomBar.hpp" #include "PinLockWindow.hpp" #include "application-desktop/ApplicationDesktop.hpp" #include "locks/data/LockData.hpp" #include "locks/widgets/PhoneLockBox.hpp" #include "locks/widgets/SimLockBox.hpp" #include "locks/widgets/PukLockBox.hpp" #include namespace gui { PinLockWindow::PinLockWindow(app::Application *app, const std::string &window_name) : PinLockBaseWindow(app, window_name), this_window_name(window_name) { buildInterface(); } void PinLockWindow::rebuild() { // find which widget has focus destroyInterface(); buildInterface(); // set state focusItem = nullptr; } void PinLockWindow::buildInterface() { AppWindow::buildInterface(); PinLockBaseWindow::build(); } void PinLockWindow::destroyInterface() { erase(); } void PinLockWindow::setVisibleState() { restore(); if (lock->isState(Lock::LockState::InputRequired)) { lockBox->setVisibleStateInputRequired(LockBox::InputActionType::ProvideInput); } else if (lock->isState(Lock::LockState::InputInvalidRetryRequired)) { lockBox->setVisibleStateInputInvalid(LockBox::InputErrorType::InvalidInput, lock->getAttemptsLeft()); } else if (lock->isState(Lock::LockState::Blocked)) { lockBox->setVisibleStateBlocked(); } else if (lock->isState(Lock::LockState::NewInputRequired)) { lockBox->setVisibleStateInputRequired(LockBox::InputActionType::ProvideNewInput); } else if (lock->isState(Lock::LockState::NewInputConfirmRequired)) { lockBox->setVisibleStateInputRequired(LockBox::InputActionType::ConfirmNewInput); } else if (lock->isState(Lock::LockState::NewInputInvalid)) { lockBox->setVisibleStateInputInvalid(LockBox::InputErrorType::NewInputConfirmFailed, lock->getAttemptsLeft()); } else if (lock->isState(Lock::LockState::ErrorOccurred)) { lockBox->setVisibleStateInputInvalid(LockBox::InputErrorType::UnhandledError, lock->getAttemptsLeft()); } application->refreshWindow(RefreshModes::GUI_REFRESH_FAST); } void PinLockWindow::onBeforeShow(ShowMode mode, SwitchData *data) { if (auto lockData = dynamic_cast(data)) { rebuild(); lock = std::make_unique(lockData->getLock()); buildPinLockBox(); lockBox->buildLockBox(lock->getMaxInputSize()); if (lock->isState(Lock::LockState::InputRequired)) { currentPasscodeType = LockBox::InputActionType::ProvideInput; } else if (lock->isState(Lock::LockState::NewInputRequired)) { currentPasscodeType = LockBox::InputActionType::ProvideNewInput; } setVisibleState(); } } bool PinLockWindow::onInput(const InputEvent &inputEvent) { if (!inputEvent.isShortRelease()) { return AppWindow::onInput(inputEvent); } // accept only LF, enter, RF, #, and numeric values; if (inputEvent.is(KeyCode::KEY_LEFT) && iceBox->visible) { app::manager::Controller::sendAction(application, app::manager::actions::EmergencyDial); return true; } else if (inputEvent.is(KeyCode::KEY_RF) && bottomBar->isActive(BottomBar::Side::RIGHT)) { if (usesNumericKeys()) { lock->clearAttempt(); } else if (lock->isState(Lock::LockState::InputInvalidRetryRequired)) { lock->consumeState(); } application->returnToPreviousWindow(); return true; } else if (inputEvent.is(KeyCode::KEY_PND)) { if (usesNumericKeys()) { lock->popChar(); lockBox->popChar(lock->getCharCount()); bottomBar->setActive(BottomBar::Side::CENTER, lock->canVerify()); return true; } } else if (inputEvent.isDigit()) { if (usesNumericKeys() && lock->canPut()) { lockBox->putChar(lock->getCharCount()); lock->putNextChar(inputEvent.numericValue()); bottomBar->setActive(BottomBar::Side::CENTER, lock->canVerify()); return true; } } else if (inputEvent.is(KeyCode::KEY_ENTER) && bottomBar->isActive(BottomBar::Side::CENTER)) { lock->activate(); bottomBar->setActive(BottomBar::Side::CENTER, false); return true; } // check if any of the lower inheritance onInput methods catch the event return AppWindow::onInput(inputEvent); } void PinLockWindow::buildPinLockBox() { auto lockType = lock->getLockType(); if (lockType == Lock::LockType::Screen) { lockBox = std::make_unique(this); } else if (lockType == Lock::LockType::SimPuk) { lockBox = std::make_unique(this); setTitleBar(true, true); setText("app_desktop_header_sim_setup", TextType::Title, true, {{getToken(Token::Sim), utils::enumToString(lock->getSim())}}); } else if (lockType == Lock::LockType::SimPin) { lockBox = std::make_unique(this); setTitleBar(true, false); setText("app_desktop_header_sim_setup", TextType::Title, true, {{getToken(Token::Sim), utils::enumToString(lock->getSim())}}); } assert(lockBox != nullptr); } auto PinLockWindow::usesNumericKeys() const noexcept -> bool { return lock && (lock->isState(Lock::LockState::InputRequired) || lock->isState(Lock::LockState::NewInputRequired) || lock->isState(Lock::LockState::NewInputConfirmRequired)); } } /* namespace gui */