~aleteoryx/muditaos

53e2fae8fbf21cd87194a0ba39b37dbe36761231 — Lefucjusz 2 years ago 028229a
[MOS-178] Add input mode displaying timeout

Added timeout for displaying selected input
mode - now it automatically disappears
after 3 seconds since last change was made.
25 files changed, 252 insertions(+), 94 deletions(-)

M module-apps/application-desktop/windows/MmiPullWindow.cpp
M module-apps/application-messages/widgets/SMSInputWidget.cpp
M module-apps/application-messages/windows/NewMessage.cpp
M module-apps/application-messages/windows/SearchStart.cpp
M module-apps/application-notes/windows/NoteEditWindow.cpp
M module-apps/application-notes/windows/SearchEngineWindow.cpp
M module-apps/application-phonebook/models/NewContactModel.cpp
M module-apps/application-phonebook/models/NewContactModel.hpp
M module-apps/application-phonebook/widgets/InputLinesWithLabelWidget.cpp
M module-apps/application-phonebook/widgets/InputLinesWithLabelWidget.hpp
M module-apps/application-phonebook/windows/PhonebookMainWindow.cpp
M module-apps/application-phonebook/windows/PhonebookNewContact.cpp
M module-apps/application-phonebook/windows/PhonebookSearch.cpp
M module-apps/application-settings/models/network/NewApnModel.cpp
M module-apps/application-settings/widgets/network/ApnInputWidget.cpp
M module-apps/application-settings/widgets/network/ApnInputWidget.hpp
M module-apps/application-settings/windows/advanced/UITestWindow.cpp
M module-apps/application-settings/windows/bluetooth/PhoneNameWindow.cpp
M module-apps/application-settings/windows/display-keypad/QuotesAddWindow.cpp
M module-apps/apps-common/windows/AppWindow.cpp
M module-apps/apps-common/windows/AppWindow.hpp
M module-apps/apps-common/windows/AppWindowConstants.hpp
M module-gui/gui/widgets/text/modes/InputMode.cpp
M module-gui/gui/widgets/text/modes/InputMode.hpp
M pure_changelog.md
M module-apps/application-desktop/windows/MmiPullWindow.cpp => module-apps/application-desktop/windows/MmiPullWindow.cpp +4 -1
@@ 60,7 60,10 @@ MmiPullWindow::MmiPullWindow(app::ApplicationCommon *app, const std::string &nam
        {InputMode::digit, InputMode::Abc, InputMode::ABC, InputMode::abc},
        [=](const UTF8 &text1) { navBarTemporaryMode(text1); },
        [=]() { navBarRestoreFromTemporaryMode(); },
        [=]() { selectSpecialCharacter(); }));
        [=]() { selectSpecialCharacter(); },
        [=](std::function<void()> restoreFunction) {
            application->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
        }));

    addWidget(InputBox);
}

M module-apps/application-messages/widgets/SMSInputWidget.cpp => module-apps/application-messages/widgets/SMSInputWidget.cpp +4 -1
@@ 57,7 57,10 @@ namespace gui
            {InputMode::Abc, InputMode::ABC, InputMode::abc, InputMode::digit},
            [=](const UTF8 &Text) { application->getCurrentWindow()->navBarTemporaryMode(Text); },
            [=]() { application->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
            [=]() { application->getCurrentWindow()->selectSpecialCharacter(); }));
            [=]() { application->getCurrentWindow()->selectSpecialCharacter(); },
            [=](std::function<void()> restoreFunction) {
                application->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
            }));

        inputText->inputCallback = [this, application]([[maybe_unused]] Item &, const InputEvent &event) {
            if (event.isShortRelease(KeyCode::KEY_LF)) {

M module-apps/application-messages/windows/NewMessage.cpp => module-apps/application-messages/windows/NewMessage.cpp +4 -1
@@ 264,7 264,10 @@ namespace gui
            {InputMode::Abc, InputMode::ABC, InputMode::abc, InputMode::digit},
            [=](const UTF8 &text) { navBarTemporaryMode(text); },
            [=]() { navBarRestoreFromTemporaryMode(); },
            [=]() { selectSpecialCharacter(); }));
            [=]() { selectSpecialCharacter(); },
            [=](std::function<void()> restoreFunction) {
                application->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
            }));
        message->setPenFocusWidth(style::window::default_border_focus_w);
        message->setPenWidth(style::window::default_border_rect_no_focus);
        message->setFont(style::window::font::medium);

M module-apps/application-messages/windows/SearchStart.cpp => module-apps/application-messages/windows/SearchStart.cpp +7 -3
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ApplicationMessages.hpp"


@@ 23,12 23,16 @@ namespace gui
        body = new gui::Item();
        body->setBoundingBox(bodySize());
        addWidget(body);
        auto text = inputBox(this, utils::translate("common_search_uc"), "search_32px_W_G");

        const auto text = inputBox(this, utils::translate("common_search_uc"), "search_32px_W_G");
        text->setInputMode(new InputMode(
            {InputMode::Abc, InputMode::ABC, InputMode::abc, InputMode::digit},
            [=](const UTF8 &Text) { application->getCurrentWindow()->navBarTemporaryMode(Text); },
            [=]() { application->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
            [=]() { application->getCurrentWindow()->selectSpecialCharacter(); }));
            [=]() { application->getCurrentWindow()->selectSpecialCharacter(); },
            [=](std::function<void()> restoreFunction) {
                application->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
            }));

        inputCallback = [=](Item &, const InputEvent &inputEvent) -> bool {
            auto app = dynamic_cast<app::ApplicationMessages *>(application);

M module-apps/application-notes/windows/NoteEditWindow.cpp => module-apps/application-notes/windows/NoteEditWindow.cpp +5 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "NoteEditWindow.hpp"


@@ 75,7 75,10 @@ namespace app::notes
            {InputMode::Abc, InputMode::ABC, InputMode::abc, InputMode::digit},
            [=](const UTF8 &text) { navBarTemporaryMode(text); },
            [=]() { navBarRestoreFromTemporaryMode(); },
            [=]() { selectSpecialCharacter(); }));
            [=]() { selectSpecialCharacter(); },
            [=](std::function<void()> restoreFunction) {
                application->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
            }));
        edit->setTextChangedCallback([this](Item &, const UTF8 &text) {
            const auto count = text.length();
            setCharactersCount(count);

M module-apps/application-notes/windows/SearchEngineWindow.cpp => module-apps/application-notes/windows/SearchEngineWindow.cpp +9 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "SearchEngineWindow.hpp"


@@ 35,6 35,14 @@ namespace app::notes
        navBar->setText(gui::nav_bar::Side::Right, utils::translate(style::strings::common::back));

        input = gui::inputBox(this, utils::translate("common_search_uc"), "search_32px_W_G");
        input->setInputMode(new InputMode(
            {InputMode::Abc, InputMode::ABC, InputMode::abc, InputMode::digit},
            [=](const UTF8 &text) { application->getCurrentWindow()->navBarTemporaryMode(text); },
            [=]() { application->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
            [=]() { application->getCurrentWindow()->selectSpecialCharacter(); },
            [=](std::function<void()> restoreFunction) {
                application->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
            }));
        setFocusItem(input);
    }


M module-apps/application-phonebook/models/NewContactModel.cpp => module-apps/application-phonebook/models/NewContactModel.cpp +58 -8
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "NewContactModel.hpp"


@@ 24,7 24,7 @@ auto NewContactModel::getMinimalItemSpaceRequired() const -> unsigned int
    return phonebookStyle::inputLinesWithLabelWidget::h;
}

void NewContactModel::requestRecords(const uint32_t offset, const uint32_t limit)
void NewContactModel::requestRecords(const std::uint32_t offset, const std::uint32_t limit)
{
    setupModel(offset, limit);
    list->onProviderDataUpdate();


@@ 37,41 37,77 @@ auto NewContactModel::getItem(gui::Order order) -> gui::ListItem *

void NewContactModel::createData()
{
    constexpr auto navBarOptionsLabelSide = gui::nav_bar::Side::Left;
    auto app = application;

    internalData.push_back(new gui::InputLinesWithLabelWidget(
        phonebookInternals::ListItemName::FirstName,
        [app](const UTF8 &text, bool emptyOthers) { app->getCurrentWindow()->navBarTemporaryMode(text, emptyOthers); },
        [app]() { app->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
        [app](const UTF8 &text, bool active) {
            app->getCurrentWindow()->setNavBarText(text, navBarOptionsLabelSide);
            app->getCurrentWindow()->setNavBarActive(navBarOptionsLabelSide, active);
        },
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); },
        [app](std::function<void()> restoreFunction) {
            app->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
        },
        [&](gui::Text *text) { openTextOptions(text); }));

    internalData.push_back(new gui::InputLinesWithLabelWidget(
        phonebookInternals::ListItemName::SecondName,
        [app](const UTF8 &text, bool emptyOthers) { app->getCurrentWindow()->navBarTemporaryMode(text, emptyOthers); },
        [app]() { app->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
        [app](const UTF8 &text, bool active) {
            app->getCurrentWindow()->setNavBarText(text, navBarOptionsLabelSide);
            app->getCurrentWindow()->setNavBarActive(navBarOptionsLabelSide, active);
        },
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); },
        [app](std::function<void()> restoreFunction) {
            app->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
        },
        [&](gui::Text *text) { openTextOptions(text); }));

    internalData.push_back(new gui::InputLinesWithLabelWidget(
        phonebookInternals::ListItemName::Number,
        [app](const UTF8 &text, bool emptyOthers) { app->getCurrentWindow()->navBarTemporaryMode(text, emptyOthers); },
        [app]() { app->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
        [app](const UTF8 &text, bool active) {
            app->getCurrentWindow()->setNavBarText(text, navBarOptionsLabelSide);
            app->getCurrentWindow()->setNavBarActive(navBarOptionsLabelSide, active);
        },
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); },
        [app](std::function<void()> restoreFunction) {
            app->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
        },
        [&](gui::Text *text) { openTextOptions(text); }));

    internalData.push_back(new gui::InputLinesWithLabelWidget(
        phonebookInternals::ListItemName::SecondNumber,
        [app](const UTF8 &text, bool emptyOthers) { app->getCurrentWindow()->navBarTemporaryMode(text, emptyOthers); },
        [app]() { app->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
        [app](const UTF8 &text, bool active) {
            app->getCurrentWindow()->setNavBarText(text, navBarOptionsLabelSide);
            app->getCurrentWindow()->setNavBarActive(navBarOptionsLabelSide, active);
        },
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); },
        [app](std::function<void()> restoreFunction) {
            app->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
        },
        [&](gui::Text *text) { openTextOptions(text); }));

    internalData.push_back(new gui::InputLinesWithLabelWidget(
        phonebookInternals::ListItemName::Email,
        [app](const UTF8 &text, bool emptyOthers) { app->getCurrentWindow()->navBarTemporaryMode(text, emptyOthers); },
        [app]() { app->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
        [app](const UTF8 &text, bool active) {
            app->getCurrentWindow()->setNavBarText(text, navBarOptionsLabelSide);
            app->getCurrentWindow()->setNavBarActive(navBarOptionsLabelSide, active);
        },
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); },
        [app](std::function<void()> restoreFunction) {
            app->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
        },
        [&](gui::Text *text) { openTextOptions(text); }));

    internalData.push_back(new gui::InputBoxWithLabelAndIconWidget(


@@ 93,7 129,14 @@ void NewContactModel::createData()
        phonebookInternals::ListItemName::Address,
        [app](const UTF8 &text, bool emptyOthers) { app->getCurrentWindow()->navBarTemporaryMode(text, emptyOthers); },
        [app]() { app->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
        [app](const UTF8 &text, bool active) {
            app->getCurrentWindow()->setNavBarText(text, navBarOptionsLabelSide);
            app->getCurrentWindow()->setNavBarActive(navBarOptionsLabelSide, active);
        },
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); },
        [app](std::function<void()> restoreFunction) {
            app->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
        },
        [&](gui::Text *text) { openTextOptions(text); },
        2));



@@ 101,7 144,14 @@ void NewContactModel::createData()
        phonebookInternals::ListItemName::Note,
        [app](const UTF8 &text, bool emptyOthers) { app->getCurrentWindow()->navBarTemporaryMode(text, emptyOthers); },
        [app]() { app->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
        [app](const UTF8 &text, bool active) {
            app->getCurrentWindow()->setNavBarText(text, navBarOptionsLabelSide);
            app->getCurrentWindow()->setNavBarActive(navBarOptionsLabelSide, active);
        },
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); },
        [app](std::function<void()> restoreFunction) {
            app->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
        },
        [&](gui::Text *text) { openTextOptions(text); },
        2));



@@ 118,7 168,7 @@ void NewContactModel::clearData()

bool NewContactModel::verifyData()
{
    for (auto item : internalData) {
    for (const auto &item : internalData) {
        if (item->onVerifyCallback) {
            std::string errorMessage;
            if (!item->onVerifyCallback(errorMessage)) {


@@ 143,7 193,7 @@ bool NewContactModel::verifyData()

void NewContactModel::saveData(std::shared_ptr<ContactRecord> contactRecord)
{
    for (auto item : internalData) {
    for (const auto &item : internalData) {
        if (item->onSaveCallback) {
            item->onSaveCallback(contactRecord);
        }


@@ 152,20 202,20 @@ void NewContactModel::saveData(std::shared_ptr<ContactRecord> contactRecord)

void NewContactModel::loadData(std::shared_ptr<ContactRecord> contactRecord, gui::SwitchData *data)
{
    for (auto item : internalData) {
    for (const auto &item : internalData) {
        if (item->onLoadCallback) {
            item->onLoadCallback(contactRecord);
        }
    }

    if (auto message = dynamic_cast<PhonebookItemData *>(data); message != nullptr) {
    if (const auto message = dynamic_cast<PhonebookItemData *>(data); message != nullptr) {
        requestType = message->getRequestType();
    }
}

bool NewContactModel::emptyData()
{
    for (auto item : internalData) {
    for (const auto &item : internalData) {
        if (item->onEmptyCallback) {
            if (!item->onEmptyCallback()) {
                return false;


@@ 182,6 232,6 @@ bool NewContactModel::emptyData()

void NewContactModel::openTextOptions(gui::Text *text)
{
    std::unique_ptr<gui::SwitchData> data = std::make_unique<PhonebookInputOptionData>(text);
    auto data = std::make_unique<PhonebookInputOptionData>(text);
    application->switchWindow(gui::window::name::input_options, std::move(data));
}

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

#pragma once


@@ 34,5 34,5 @@ class NewContactModel : public app::InternalModel<gui::ContactListItem *>, publi
    [[nodiscard]] auto getMinimalItemSpaceRequired() const -> unsigned int override;
    auto getItem(gui::Order order) -> gui::ListItem * override;

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

M module-apps/application-phonebook/widgets/InputLinesWithLabelWidget.cpp => module-apps/application-phonebook/widgets/InputLinesWithLabelWidget.cpp +16 -8
@@ 14,11 14,14 @@ namespace gui
        phonebookInternals::ListItemName listItemName,
        const std::function<void(const UTF8 &text, bool emptyOthers)> &navBarTemporaryMode,
        const std::function<void()> &navBarRestoreFromTemporaryMode,
        const std::function<void(const UTF8 &text, bool active)> &navBarSetOptionsLabel,
        const std::function<void()> &selectSpecialCharacter,
        const std::function<void(std::function<void()> restoreFunction)> &restoreInputMode,
        const std::function<void(Text *text)> &inputOptions,
        unsigned int lines)
        : listItemName(listItemName), navBarTemporaryMode(navBarTemporaryMode),
          navBarRestoreFromTemporaryMode(navBarRestoreFromTemporaryMode), inputOptions(inputOptions)
          navBarRestoreFromTemporaryMode(navBarRestoreFromTemporaryMode), navBarSetOptionsLabel(navBarSetOptionsLabel),
          inputOptions(inputOptions)
    {
        setMinimumSize(phonebookStyle::inputLinesWithLabelWidget::w,
                       phonebookStyle::inputLinesWithLabelWidget::title_label_h +


@@ 55,7 58,8 @@ namespace gui
            {InputMode::Abc, InputMode::ABC, InputMode::abc, InputMode::digit},
            [=](const UTF8 &text) { this->navBarTemporaryMode(text, true); },
            [=]() { this->navBarRestoreFromTemporaryMode(); },
            [=]() { selectSpecialCharacter(); }));
            [=]() { selectSpecialCharacter(); },
            [=](std::function<void()> restoreFunction) { restoreInputMode(std::move(restoreFunction)); }));
        inputText->setPenFocusWidth(style::window::default_border_focus_w);
        inputText->setPenWidth(style::window::default_border_no_focus_w);
        inputText->setEditMode(EditMode::Edit);


@@ 70,8 74,9 @@ namespace gui
                inputText->setUnderlineThickness(style::window::default_border_focus_w);
                inputText->setFont(style::window::font::mediumbold);

                if (!inputText->isEmpty() || Clipboard::getInstance().gotData()) {
                    this->navBarTemporaryMode(utils::translate(style::strings::common::options), false);
                if (this->navBarSetOptionsLabel) {
                    const auto optionsLabelState = !inputText->isEmpty() || Clipboard::getInstance().gotData();
                    this->navBarSetOptionsLabel(utils::translate(style::strings::common::options), optionsLabelState);
                }
            }
            else {


@@ 79,16 84,19 @@ namespace gui
                inputText->setUnderlineThickness(style::window::default_border_rect_no_focus);
                inputText->setFont(style::window::font::medium);

                this->navBarRestoreFromTemporaryMode();
                if (this->navBarSetOptionsLabel) {
                    this->navBarSetOptionsLabel(utils::translate(style::strings::common::options), false);
                }
            }
            return true;
        };

        inputCallback = [&](Item &item, const InputEvent &event) {
            auto result = inputText->onInput(event);
            const auto result = inputText->onInput(event);

            if (!event.is(KeyCode::KEY_AST) && (!inputText->isEmpty() || Clipboard::getInstance().gotData())) {
                this->navBarTemporaryMode(utils::translate(style::strings::common::options), false);
            if (!event.is(KeyCode::KEY_AST) && this->navBarSetOptionsLabel) {
                const auto optionsLabelState = !inputText->isEmpty() || Clipboard::getInstance().gotData();
                this->navBarSetOptionsLabel(utils::translate(style::strings::common::options), optionsLabelState);
            }

            if (event.isShortRelease(gui::KeyCode::KEY_LF) &&

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

#pragma once


@@ 20,7 20,9 @@ namespace gui
            phonebookInternals::ListItemName listItemName,
            const std::function<void(const UTF8 &text, bool emptyOthers)> &navBarTemporaryMode = nullptr,
            const std::function<void()> &navBarRestoreFromTemporaryMode                        = nullptr,
            const std::function<void(const UTF8 &text, bool active)> &navBarSetOptionsLabel    = nullptr,
            const std::function<void()> &selectSpecialCharacter                                = nullptr,
            const std::function<void(std::function<void()> restoreFunction)> &restoreInputMode = nullptr,
            const std::function<void(Text *text)> &inputOptions                                = nullptr,
            unsigned int lines                                                                 = 1);



@@ 34,6 36,7 @@ namespace gui

        std::function<void(const UTF8 &text, bool emptyOthers)> navBarTemporaryMode = nullptr;
        std::function<void()> navBarRestoreFromTemporaryMode                        = nullptr;
        std::function<void(const UTF8 &text, bool active)> navBarSetOptionsLabel    = nullptr;
        std::function<void(Text *text)> inputOptions                                = nullptr;

        void firstNameHandler();

M module-apps/application-phonebook/windows/PhonebookMainWindow.cpp => module-apps/application-phonebook/windows/PhonebookMainWindow.cpp +7 -5
@@ 11,7 11,6 @@
#include <header/AddElementAction.hpp>
#include <header/SearchAction.hpp>
#include <service-appmgr/Controller.hpp>
#include <service-db/QueryMessage.hpp>
#include <service-db/DBNotificationMessage.hpp>

namespace gui


@@ 64,15 63,18 @@ namespace gui
        contactsList->emptyListCallback    = [this]() { onEmptyList(); };
        contactsList->notEmptyListCallback = [this]() { onListFilled(); };

        phonebookModel->setDisplayMode(static_cast<uint32_t>(ContactDisplayMode::SortedByLetter));
        phonebookModel->setDisplayMode(static_cast<std::uint32_t>(ContactDisplayMode::SortedByLetter));
        contactsList->rebuildList(gui::listview::RebuildType::Full);

        auto app  = application;
        inputMode = std::make_unique<InputMode>(
        const auto app = application;
        inputMode      = std::make_unique<InputMode>(
            std::list<InputMode::Mode>{InputMode::ABC, InputMode::abc},
            [app](const UTF8 &text) { app->getCurrentWindow()->navBarTemporaryMode(text); },
            [app]() { app->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
            [app]() { app->getCurrentWindow()->selectSpecialCharacter(); });
            [app]() { app->getCurrentWindow()->selectSpecialCharacter(); },
            [app](std::function<void()> restoreFunction) {
                app->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
            });
    }

    void PhonebookMainWindow::destroyInterface()

M module-apps/application-phonebook/windows/PhonebookNewContact.cpp => module-apps/application-phonebook/windows/PhonebookNewContact.cpp +3 -6
@@ 90,7 90,7 @@ namespace gui
            return false;
        }

        auto *item = dynamic_cast<PhonebookItemData *>(data);
        const auto item = dynamic_cast<PhonebookItemData *>(data);
        if (item == nullptr) {
            return false;
        }


@@ 146,7 146,6 @@ namespace gui

    auto PhonebookNewContact::verifyAndSave() -> bool
    {
        LOG_DEBUG("%s", __FUNCTION__);
        if (!contact->isTemporary()) {
            auto result = DBServiceAPI::verifyContact(application, *contact);
            switch (result) {


@@ 194,8 193,7 @@ namespace gui
            }
        }

        std::unique_ptr<gui::SwitchData> data =
            std::make_unique<PhonebookItemData>(contact, newContactModel->getRequestType());
        auto data = std::make_unique<PhonebookItemData>(contact, newContactModel->getRequestType());
        data->ignoreCurrentWindowOnStack = true;
        application->switchWindow(gui::window::name::contact, std::move(data));
        return true;


@@ 273,8 271,7 @@ namespace gui

        auto metaData = std::make_unique<gui::DialogMetadataMessage>(gui::DialogMetadata{
            contact->getFormattedName(ContactRecord::NameFormatType::Title), icon, text, "", [=]() -> bool {
                std::unique_ptr<gui::SwitchData> data =
                    std::make_unique<PhonebookItemData>(contact, newContactModel->getRequestType());
                auto data = std::make_unique<PhonebookItemData>(contact, newContactModel->getRequestType());
                this->application->switchWindow(gui::name::window::main_window, std::move(data));

                return true;

M module-apps/application-phonebook/windows/PhonebookSearch.cpp => module-apps/application-phonebook/windows/PhonebookSearch.cpp +4 -1
@@ 24,7 24,10 @@ namespace gui
            {InputMode::Abc, InputMode::ABC, InputMode::abc, InputMode::digit},
            [=](const UTF8 &Text) { application->getCurrentWindow()->navBarTemporaryMode(Text); },
            [=]() { application->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
            [=]() { application->getCurrentWindow()->selectSpecialCharacter(); }));
            [=]() { application->getCurrentWindow()->selectSpecialCharacter(); },
            [=](std::function<void()> restoreFunction) {
                application->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
            }));

        navBar->setActive(nav_bar::Side::Left, false);
        navBar->setActive(nav_bar::Side::Center, true);

M module-apps/application-settings/models/network/NewApnModel.cpp => module-apps/application-settings/models/network/NewApnModel.cpp +28 -7
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "NewApnModel.hpp"


@@ 43,43 43,64 @@ void NewApnModel::createData()
        [app](const UTF8 &text) { app->getCurrentWindow()->navBarTemporaryMode(text); },
        [app]() { app->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); },
        [app](std::function<void()> restoreFunction) {
            app->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
        },
        [this](const std::string &text) { this->apnNameChanged(text); }));

    internalData.emplace_back(new gui::ApnInputWidget(
        settingsInternals::ListItemName::APN,
        [app](const UTF8 &text) { app->getCurrentWindow()->navBarTemporaryMode(text); },
        [app]() { app->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); }));
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); },
        [app](std::function<void()> restoreFunction) {
            app->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
        }));

    internalData.emplace_back(new gui::ApnInputWidget(
        settingsInternals::ListItemName::Username,
        [app](const UTF8 &text) { app->getCurrentWindow()->navBarTemporaryMode(text); },
        [app]() { app->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); }));
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); },
        [app](std::function<void()> restoreFunction) {
            app->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
        }));

    internalData.emplace_back(new gui::ApnInputWidget(
        settingsInternals::ListItemName::Password,
        [app](const UTF8 &text) { app->getCurrentWindow()->navBarTemporaryMode(text); },
        [app]() { app->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); }));
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); },
        [app](std::function<void()> restoreFunction) {
            app->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
        }));

    internalData.emplace_back(new gui::ApnInputWidget(
        settingsInternals::ListItemName::AuthType,
        [app](const UTF8 &text) { app->getCurrentWindow()->navBarTemporaryMode(text); },
        [app]() { app->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); }));
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); },
        [app](std::function<void()> restoreFunction) {
            app->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
        }));

    internalData.emplace_back(new gui::ApnInputWidget(
        settingsInternals::ListItemName::ApnType,
        [app](const UTF8 &text) { app->getCurrentWindow()->navBarTemporaryMode(text); },
        [app]() { app->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); }));
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); },
        [app](std::function<void()> restoreFunction) {
            app->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
        }));

    internalData.emplace_back(new gui::ApnInputWidget(
        settingsInternals::ListItemName::ApnProtocol,
        [app](const UTF8 &text) { app->getCurrentWindow()->navBarTemporaryMode(text); },
        [app]() { app->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); }));
        [app]() { app->getCurrentWindow()->selectSpecialCharacter(); },
        [app](std::function<void()> restoreFunction) {
            app->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
        }));

    for (auto item : internalData) {
        item->deleteByList = false;

M module-apps/application-settings/widgets/network/ApnInputWidget.cpp => module-apps/application-settings/widgets/network/ApnInputWidget.cpp +9 -7
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ApnInputWidget.hpp"


@@ 11,12 11,13 @@
namespace gui
{
    ApnInputWidget::ApnInputWidget(settingsInternals::ListItemName listItemName,
                                   std::function<void(const UTF8 &)> navBarTemporaryMode,
                                   std::function<void()> navBarRestoreFromTemporaryMode,
                                   std::function<void()> selectSpecialCharacter,
                                   std::function<void(const std::string &text)> contentChanged,
                                   const std::function<void(const UTF8 &)> &navBarTemporaryMode,
                                   const std::function<void()> &navBarRestoreFromTemporaryMode,
                                   const std::function<void()> &selectSpecialCharacter,
                                   const std::function<void(std::function<void()> restoreFunction)> &restoreInputMode,
                                   const std::function<void(const std::string &text)> &contentChanged,
                                   unsigned int lines)
        : listItemName(listItemName), checkTextContent(std::move(contentChanged))
        : listItemName(listItemName), checkTextContent(contentChanged)
    {
        setMinimumSize(style::settings::widget::apnInputWidget::w,
                       style::settings::widget::apnInputWidget::title_label_h +


@@ 49,7 50,8 @@ namespace gui
            {InputMode::Abc, InputMode::ABC, InputMode::abc, InputMode::digit},
            [=](const UTF8 &text) { navBarTemporaryMode(text); },
            [=]() { navBarRestoreFromTemporaryMode(); },
            [=]() { selectSpecialCharacter(); }));
            [=]() { selectSpecialCharacter(); },
            [=](std::function<void()> restoreFunction) { restoreInputMode(std::move(restoreFunction)); }));
        inputText->setPenFocusWidth(style::window::default_border_focus_w);
        inputText->setPenWidth(style::window::default_border_no_focus_w);
        inputText->setEditMode(EditMode::Edit);

M module-apps/application-settings/widgets/network/ApnInputWidget.hpp => module-apps/application-settings/widgets/network/ApnInputWidget.hpp +9 -7
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once


@@ 16,12 16,14 @@ namespace gui
        settingsInternals::ListItemName listItemName;

      public:
        ApnInputWidget(settingsInternals::ListItemName listItemName,
                       std::function<void(const UTF8 &text)> navBarTemporaryMode   = nullptr,
                       std::function<void()> navBarRestoreFromTemporaryMode        = nullptr,
                       std::function<void()> selectSpecialCharacter                = nullptr,
                       std::function<void(const std::string &text)> contentChanged = nullptr,
                       unsigned int lines                                          = 1);
        explicit ApnInputWidget(
            settingsInternals::ListItemName listItemName,
            const std::function<void(const UTF8 &)> &navBarTemporaryMode                       = nullptr,
            const std::function<void()> &navBarRestoreFromTemporaryMode                        = nullptr,
            const std::function<void()> &selectSpecialCharacter                                = nullptr,
            const std::function<void(std::function<void()> restoreFunction)> &restoreInputMode = nullptr,
            const std::function<void(const std::string &text)> &contentChanged                 = nullptr,
            unsigned int lines                                                                 = 1);

      private:
        VBox *vBox                                                    = nullptr;

M module-apps/application-settings/windows/advanced/UITestWindow.cpp => module-apps/application-settings/windows/advanced/UITestWindow.cpp +7 -7
@@ 1,16 1,13 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "UITestWindow.hpp"

#include <application-settings/windows/WindowNames.hpp>

#include <Font.hpp>
#include <i18n/i18n.hpp>
#include <Application.hpp>

namespace gui
{

    UiTestWindow::UiTestWindow(app::ApplicationCommon *app) : AppWindow(app, "TEST_UI")
    {
        AppWindow::buildInterface();


@@ 55,9 52,12 @@ namespace gui
        text->addText(TextBlock("special chars too", Font(27).raw(), TextBlock::End::None));
        text->setInputMode(new InputMode(
            {InputMode::Abc, InputMode::ABC, InputMode::abc, InputMode::digit},
            [=](const UTF8 &text) { navBarTemporaryMode(text); },
            [=](const UTF8 &temporaryText) { navBarTemporaryMode(temporaryText); },
            [=]() { navBarRestoreFromTemporaryMode(); },
            [=]() { selectSpecialCharacter(); }));
            [=]() { selectSpecialCharacter(); },
            [=](std::function<void()> restoreFunction) {
                application->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
            }));
        text->setPenFocusWidth(0);
        setFocusItem(text);
    }

M module-apps/application-settings/windows/bluetooth/PhoneNameWindow.cpp => module-apps/application-settings/windows/bluetooth/PhoneNameWindow.cpp +9 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "PhoneNameWindow.hpp"


@@ 25,6 25,14 @@ namespace gui
        setTitle(utils::translate("app_settings_bluetooth_phone_name"));

        inputField = inputBox(this, utils::translate("app_settings_bluetooth_phone_name"));
        inputField->setInputMode(new InputMode(
            {InputMode::Abc, InputMode::ABC, InputMode::abc, InputMode::digit},
            [=](const UTF8 &text) { application->getCurrentWindow()->navBarTemporaryMode(text); },
            [=]() { application->getCurrentWindow()->navBarRestoreFromTemporaryMode(); },
            nullptr,
            [=](std::function<void()> restoreFunction) {
                application->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
            }));
        navBar->setActive(nav_bar::Side::Left, false);
        navBar->setActive(nav_bar::Side::Center, true);
        navBar->setActive(nav_bar::Side::Right, true);

M module-apps/application-settings/windows/display-keypad/QuotesAddWindow.cpp => module-apps/application-settings/windows/display-keypad/QuotesAddWindow.cpp +5 -2
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "QuotesAddWindow.hpp"


@@ 78,7 78,10 @@ namespace gui
            {InputMode::Abc, InputMode::ABC, InputMode::abc, InputMode::digit},
            [=](const UTF8 &text) { navBarTemporaryMode(text); },
            [=]() { navBarRestoreFromTemporaryMode(); },
            [=]() { selectSpecialCharacter(); }));
            [=]() { selectSpecialCharacter(); },
            [=](std::function<void()> restoreFunction) {
                application->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
            }));
        authorText->setTextLimitType(gui::TextLimitType::MaxSignsCount, maxAuthorCharactersCount);

        auto quoteHeader = new HBox(vBox, 0, 0, 0, 0);

M module-apps/apps-common/windows/AppWindow.cpp => module-apps/apps-common/windows/AppWindow.cpp +12 -0
@@ 309,4 309,16 @@ namespace gui
        return application->GetName() + separator + getName();
    }

    void AppWindow::startInputModeRestoreTimer(std::function<void()> inputModeRestoreFunction)
    {
        if (inputModeRestoreFunction == nullptr) {
            return;
        }

        inputModeRestoreTimer = sys::TimerFactory::createSingleShotTimer(
            application, gui::name::timer::input_mode_timer, inputModeRestoreTimeout, [=](sys::Timer &) {
                inputModeRestoreFunction();
            });
        inputModeRestoreTimer.start();
    }
} /* namespace gui */

M module-apps/apps-common/windows/AppWindow.hpp => module-apps/apps-common/windows/AppWindow.hpp +7 -1
@@ 10,6 10,7 @@
#include <Service/Service.hpp>
#include <Service/Message.hpp>
#include "AppWindowConstants.hpp"
#include <Timers/TimerFactory.hpp>

namespace app
{


@@ 53,6 54,9 @@ namespace gui
        bool preventsAutoLock      = false;
        bool preventsLongPressLock = false;

        const std::chrono::milliseconds inputModeRestoreTimeout = std::chrono::seconds{3};
        sys::TimerHandle inputModeRestoreTimer;

      public:
        AppWindow() = delete;
        AppWindow(app::ApplicationCommon *app, std::string name);


@@ 73,7 77,7 @@ namespace gui
        bool updateSignalStrength();
        bool updateNetworkAccessTechnology();
        void updatePhoneMode(sys::phone_modes::PhoneMode mode);
        bool updateTethering(const sys::phone_modes::Tethering state);
        bool updateTethering(sys::phone_modes::Tethering state);
        [[nodiscard]] bool preventsAutoLocking() const noexcept;
        virtual RefreshModes updateTime();



@@ 115,6 119,8 @@ namespace gui
        /// @note it would be much better to just have "body item" instead
        /// but it would mean not insignificant refactor
        BoundingBox bodySize();

        void startInputModeRestoreTimer(std::function<void()> inputModeRestoreFunction = nullptr);
    };

} /* namespace gui */

M module-apps/apps-common/windows/AppWindowConstants.hpp => module-apps/apps-common/windows/AppWindowConstants.hpp +12 -4
@@ 1,9 1,17 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

namespace gui::name::window
namespace gui::name
{
    inline constexpr auto main_window = "MainWindow";
} // namespace gui::name::window
    namespace window
    {
        inline constexpr auto main_window = "MainWindow";
    }

    namespace timer
    {
        inline constexpr auto input_mode_timer = "InputModeTimer";
    }
} // namespace gui::name

M module-gui/gui/widgets/text/modes/InputMode.cpp => module-gui/gui/widgets/text/modes/InputMode.cpp +17 -11
@@ 34,12 34,14 @@ static std::string getInputName(InputMode::Mode m)
}

InputMode::InputMode(std::list<InputMode::Mode> mode_list,
                     std::function<void(const UTF8 &text)> show_type_cb,
                     std::function<void()> restore_after_show_type_cb,
                     std::function<void()> show_special_char_selector)
    : input_mode_list(std::move(mode_list)), show_type_cb(std::move(show_type_cb)),
      restore_after_show_type_cb(std::move(restore_after_show_type_cb)),
      show_special_char_selector(std::move(show_special_char_selector))
                     std::function<void(const UTF8 &text)> show_type_callback,
                     std::function<void()> restore_after_show_type_callback,
                     std::function<void()> show_special_char_selector,
                     std::function<void(std::function<void()> restore_function)> restore_timer_callback)
    : input_mode_list(std::move(mode_list)), show_type_callback(std::move(show_type_callback)),
      restore_after_show_type_callback(std::move(restore_after_show_type_callback)),
      show_special_char_selector(std::move(show_special_char_selector)),
      restore_timer_callback(std::move(restore_timer_callback))
{
    // failsafe
    if (input_mode_list.empty()) {


@@ 82,22 84,26 @@ const std::string &InputMode::get(InputMode::Mode mode)
void InputMode::show_input_type()
{
    LOG_INFO("Mode: %d", modeNow());
    if (show_type_cb) {
        show_type_cb(getInputName(modeNow()));
    if (show_type_callback) {
        show_type_callback(getInputName(modeNow()));
    }

    if (restore_timer_callback) {
        restore_timer_callback([this]() { show_restore(); });
    }
}

void InputMode::show_restore()
{
    if (restore_after_show_type_cb) {
        restore_after_show_type_cb();
    if (restore_after_show_type_callback) {
        restore_after_show_type_callback();
    }
}

void InputMode::select_special_char()
{
    LOG_INFO("Special character selector");
    if (show_special_char_selector) {
        LOG_INFO("Special character selector");
        show_special_char_selector();
    }
}

M module-gui/gui/widgets/text/modes/InputMode.hpp => module-gui/gui/widgets/text/modes/InputMode.hpp +9 -7
@@ 25,20 25,22 @@ class InputMode
    InputMode() = delete;
    // list of enabled input modes
    std::list<Mode> input_mode_list                    = {};
    uint32_t input_mode_list_pos                       = 0;
    std::function<void(const UTF8 &text)> show_type_cb = nullptr;
    std::function<void()> restore_after_show_type_cb   = nullptr;
    std::uint32_t input_mode_list_pos                                                  = 0;
    std::function<void(const UTF8 &text)> show_type_callback                           = nullptr;
    std::function<void()> restore_after_show_type_callback                             = nullptr;
    std::function<void()> show_special_char_selector   = nullptr;
    std::function<void(std::function<void()> restore_function)> restore_timer_callback = nullptr;
    Mode modeNow() const;

    void show_input_type();

  public:
    void show_restore();
    InputMode(std::list<InputMode::Mode> mode_list,
              std::function<void(const UTF8 &text)> show_type_cb = nullptr,
              std::function<void()> restore_after_show_type_cb   = nullptr,
              std::function<void()> show_special_char_selector   = nullptr);
    explicit InputMode(std::list<InputMode::Mode> mode_list,
                       std::function<void(const UTF8 &text)> show_type_callback                           = nullptr,
                       std::function<void()> restore_after_show_type_callback                             = nullptr,
                       std::function<void()> show_special_char_selector                                   = nullptr,
                       std::function<void(std::function<void()> restore_function)> restore_timer_callback = nullptr);

    void next();
    const std::string &get();

M pure_changelog.md => pure_changelog.md +1 -0
@@ 9,6 9,7 @@
* Added date formatting of received/sent SMS
* Added meditation parameters to non-volatile memory
* Added missing translations for EULA in French, Spanish and Swedish
* Added input mode selection display timeout

### Changed / Improved