~aleteoryx/muditaos

cf6c377776d21e1b33d3e79bd3f623a0386f5091 — Lefucjusz 2 years ago df7535f
[MOS-1028] Fix possibility to copy text from empty note

Fix of the issue that in Notes app 'Copy text'
option was shown in 'Options' menu even if
the note didn't contain any text.
M module-apps/application-messages/windows/OptionsMessages.cpp => module-apps/application-messages/windows/OptionsMessages.cpp +2 -2
@@ 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 "SMSdata.hpp"


@@ 113,7 113,7 @@ std::list<gui::Option> newMessageWindowOptions(app::ApplicationMessages *app,
        return true;
    });

    if (Clipboard::getInstance().gotData()) {
    if (Clipboard::getInstance().hasData()) {
        options.emplace_back(utils::translate("sms_paste"), [=](gui::Item &item) {
            text->addText(Clipboard::getInstance().paste(), gui::AdditionType::perBlock);
            app->returnToPreviousWindow();

M module-apps/application-notes/ApplicationNotes.cpp => module-apps/application-notes/ApplicationNotes.cpp +8 -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 <application-notes/ApplicationNotes.hpp>


@@ 20,18 20,19 @@

#include <utility>

namespace app
namespace
{
    namespace
    {
        constexpr auto NotesStackSize = 4096U;
    } // namespace
    constexpr auto applicationNotesStackSize = 1024 * 4;
}

namespace app
{
    ApplicationNotes::ApplicationNotes(std::string name,
                                       std::string parent,
                                       StatusIndicators statusIndicators,
                                       StartInBackground startInBackground)
        : Application(std::move(name), std::move(parent), statusIndicators, startInBackground, NotesStackSize)
        : Application(
              std::move(name), std::move(parent), statusIndicators, startInBackground, applicationNotesStackSize)
    {
        bus.channels.push_back(sys::BusChannel::ServiceDBNotifications);
    }

M module-apps/application-notes/windows/NoteCreateWindow.cpp => module-apps/application-notes/windows/NoteCreateWindow.cpp +2 -2
@@ 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 "NoteCreateWindow.hpp"


@@ 25,6 25,6 @@ namespace app::notes
    void NoteCreateWindow::onCharactersCountChanged(std::uint32_t count)
    {
        NoteEditWindow::onCharactersCountChanged(count);
        navBar->setActive(gui::nav_bar::Side::Center, count != 0U);
        navBar->setActive(gui::nav_bar::Side::Center, count != 0);
    }
} // namespace app::notes

M module-apps/application-notes/windows/NoteEditWindow.cpp => module-apps/application-notes/windows/NoteEditWindow.cpp +13 -9
@@ 18,6 18,8 @@

#include <ctime>

#include <Clipboard.hpp>

namespace app::notes
{
    namespace


@@ 80,9 82,12 @@ namespace app::notes
                application->getCurrentWindow()->startInputModeRestoreTimer(std::move(restoreFunction));
            }));
        edit->setTextChangedCallback([this](Item &, const UTF8 &text) {
            const auto count = text.length();
            setCharactersCount(count);
            onCharactersCountChanged(count);
            const auto textLength        = text.length();
            const auto optionsLabelState = (textLength != 0) || Clipboard::getInstance().hasData();
            navBar->setActive(gui::nav_bar::Side::Left, optionsLabelState);

            setCharactersCount(textLength);
            onCharactersCountChanged(textLength);
        });
        edit->setTextLimitType(gui::TextLimitType::MaxSignsCount, MaxCharactersCount);



@@ 117,9 122,9 @@ namespace app::notes
        edit              = nullptr;
    }

    void NoteEditWindow::onBeforeShow(gui::ShowMode mode, gui::SwitchData *data)
    void NoteEditWindow::onBeforeShow([[maybe_unused]] gui::ShowMode mode, gui::SwitchData *data)
    {
        auto editData = dynamic_cast<NoteSwitchData *>(data);
        const auto editData = dynamic_cast<NoteSwitchData *>(data);
        if (editData == nullptr) {
            return;
        }


@@ 144,10 149,10 @@ namespace app::notes
                switchData->ignoreCurrentWindowOnStack = true;
                application->switchWindow(gui::name::window::note_preview, std::move(switchData));
            }
            if (inputEvent.is(gui::KeyCode::KEY_LF)) {
            if (inputEvent.is(gui::KeyCode::KEY_LF) && navBar->isActive(gui::nav_bar::Side::Left)) {
                application->switchWindow(
                    window::name::option_window,
                    std::make_unique<gui::OptionsWindowOptions>(noteEditOptions(application, *notesRecord, edit)));
                    std::make_unique<gui::OptionsWindowOptions>(noteEditOptions(application, edit)));
            }
        }
        return AppWindow::onInput(inputEvent);


@@ 158,11 163,10 @@ namespace app::notes
        notesRecord->date    = std::time(nullptr);
        notesRecord->snippet = edit->getText();
        presenter->save(notesRecord);
        LOG_INFO("Note saved.");
    }

    bool NoteEditWindow::isNoteEmpty() const noexcept
    {
        return edit != nullptr ? edit->isEmpty() : true;
        return (edit != nullptr) ? edit->isEmpty() : true;
    }
} // namespace app::notes

M module-apps/application-notes/windows/NoteEditWindow.hpp => module-apps/application-notes/windows/NoteEditWindow.hpp +3 -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

#pragma once


@@ 45,7 45,7 @@ namespace app::notes

        std::unique_ptr<NoteEditWindowContract::Presenter> presenter;
        std::shared_ptr<NotesRecord> notesRecord;
        gui::Label *charactersCounter;
        gui::Text *edit;
        gui::Label *charactersCounter = nullptr;
        gui::Text *edit               = nullptr;
    };
} // namespace app::notes

M module-apps/application-notes/windows/NotesOptions.cpp => module-apps/application-notes/windows/NotesOptions.cpp +22 -20
@@ 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 "NotesOptions.hpp"


@@ 22,7 22,7 @@ namespace app::notes
                       std::function<bool(gui::Item &)> onClickCallback,
                       std::list<gui::Option> &options)
        {
            options.emplace_back(utils::translate(translationId), onClickCallback);
            options.emplace_back(utils::translate(translationId), std::move(onClickCallback));
        }

        void removeNote(const NotesRecord &record,


@@ 52,7 52,7 @@ namespace app::notes
        std::list<gui::Option> options;
        addOption(
            {"app_notes_delete_note"},
            [application, record, &notesRepository](gui::Item &item) {
            [application, record, &notesRepository]([[maybe_unused]] gui::Item &item) {
                removeNote(record, application, notesRepository);
                return true;
            },


@@ 68,7 68,7 @@ namespace app::notes
        std::list<gui::Option> options;
        addOption(
            {"common_text_copy"},
            [application, textWidget](gui::Item &item) {
            [application, textWidget]([[maybe_unused]] gui::Item &item) {
                if (textWidget != nullptr) {
                    Clipboard::getInstance().copy(textWidget->getText());
                }


@@ 78,7 78,7 @@ namespace app::notes
            options);
        addOption(
            {"app_notes_delete_note"},
            [application, record, &notesRepository](gui::Item &item) {
            [application, record, &notesRepository]([[maybe_unused]] gui::Item &item) {
                removeNote(record, application, notesRepository);
                return true;
            },


@@ 86,26 86,28 @@ namespace app::notes
        return options;
    }

    std::list<gui::Option> noteEditOptions(ApplicationCommon *application,
                                           const NotesRecord &record,
                                           gui::Text *textWidget)
    std::list<gui::Option> noteEditOptions(ApplicationCommon *application, gui::Text *textWidget)
    {
        std::list<gui::Option> options;
        addOption(
            {"common_text_copy"},
            [application, textWidget](gui::Item &item) {
                if (textWidget != nullptr) {
                    Clipboard::getInstance().copy(textWidget->getText());
                }
                application->returnToPreviousWindow();
                return true;
            },
            options);

        if (Clipboard::getInstance().gotData()) {
        if (textWidget != nullptr) {
            const auto &noteText = textWidget->getText();
            if (!noteText.empty()) {
                addOption(
                    {"common_text_copy"},
                    [application, noteText]([[maybe_unused]] gui::Item &item) {
                        Clipboard::getInstance().copy(noteText);
                        application->returnToPreviousWindow();
                        return true;
                    },
                    options);
            }
        }

        if (Clipboard::getInstance().hasData()) {
            addOption(
                {"common_text_paste"},
                [application, textWidget](gui::Item &item) {
                [application, textWidget]([[maybe_unused]] gui::Item &item) {
                    if (textWidget != nullptr) {
                        textWidget->addText(Clipboard::getInstance().paste(), gui::AdditionType::perBlock);
                    }

M module-apps/application-notes/windows/NotesOptions.hpp => module-apps/application-notes/windows/NotesOptions.hpp +2 -4
@@ 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


@@ 22,7 22,5 @@ namespace app::notes
                                              const NotesRecord &record,
                                              AbstractNotesRepository &notesRepository,
                                              gui::Text *textWidget);
    std::list<gui::Option> noteEditOptions(ApplicationCommon *application,
                                           const NotesRecord &record,
                                           gui::Text *textWidget);
    std::list<gui::Option> noteEditOptions(ApplicationCommon *application, gui::Text *textWidget);
} // namespace app::notes

M module-apps/application-phonebook/widgets/InputLinesWithLabelWidget.cpp => module-apps/application-phonebook/widgets/InputLinesWithLabelWidget.cpp +3 -3
@@ 75,7 75,7 @@ namespace gui
                inputText->setFont(style::window::font::mediumbold);

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


@@ 95,12 95,12 @@ namespace gui
            const auto result = inputText->onInput(event);

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

            if (event.isShortRelease(gui::KeyCode::KEY_LF) &&
                (!inputText->isEmpty() || Clipboard::getInstance().gotData())) {
                (!inputText->isEmpty() || Clipboard::getInstance().hasData())) {
                if (this->inputOptions) {
                    this->inputOptions(inputText);
                }

M module-apps/application-phonebook/windows/PhonebookInputOptions.cpp => module-apps/application-phonebook/windows/PhonebookInputOptions.cpp +1 -1
@@ 33,7 33,7 @@ namespace gui
            });
        }

        if (Clipboard::getInstance().gotData()) {
        if (Clipboard::getInstance().hasData()) {
            options.emplace_back(utils::translate("common_text_paste"), [=](gui::Item &item) {
                /* Single line text ellipsis implementation doesn't properly support
                 * text that consists of multiple blocks - use character addition

M module-utils/Clipboard/Clipboard.cpp => module-utils/Clipboard/Clipboard.cpp +5 -5
@@ 1,21 1,21 @@
// 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 "Clipboard.hpp"

cpp_freertos::MutexStandard Clipboard::mutex;

Clipboard &Clipboard::getInstance()
{
    static Clipboard clipboard;

    return clipboard;
}

void Clipboard::copy(const std::string &data)
void Clipboard::copy(const std::string &newData)
{
    cpp_freertos::LockGuard lock(mutex);
    this->data      = data;
    this->validData = true;
    data      = newData;
    validData = true;
}

std::string Clipboard::paste()

M module-utils/Clipboard/Clipboard.hpp => module-utils/Clipboard/Clipboard.hpp +2 -3
@@ 1,10 1,9 @@
// 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

#include <mutex.hpp>

#include <string>

class Clipboard


@@ 25,7 24,7 @@ class Clipboard
    void copy(const std::string &);
    std::string paste();

    bool gotData() const
    bool hasData() const
    {
        return validData;
    }

M module-utils/Clipboard/test/unittest_clipboard.cpp => module-utils/Clipboard/test/unittest_clipboard.cpp +9 -9
@@ 9,17 9,17 @@ TEST_CASE("Clipboard")
    SECTION("No data")
    {
        // It is guaranted to have no data only during 1st call to singleton getInstance()
        REQUIRE(Clipboard::getInstance().gotData() == false);
        REQUIRE(Clipboard::getInstance().paste() == "");
        REQUIRE(Clipboard::getInstance().hasData() == false);
        REQUIRE(Clipboard::getInstance().paste().empty() == true);
    }

    SECTION("Single copy")
    {
        const std::string test1 = "test1";
        Clipboard::getInstance().copy(test1);
        REQUIRE(Clipboard::getInstance().gotData() == true);
        REQUIRE(Clipboard::getInstance().hasData() == true);
        REQUIRE(Clipboard::getInstance().paste() == test1);
        REQUIRE(Clipboard::getInstance().gotData() == true);
        REQUIRE(Clipboard::getInstance().hasData() == true);
    }

    SECTION("Double copy")


@@ 27,19 27,19 @@ TEST_CASE("Clipboard")
        const std::string test1 = "test1";
        const std::string test2 = "test2";
        Clipboard::getInstance().copy(test1);
        REQUIRE(Clipboard::getInstance().gotData() == true);
        REQUIRE(Clipboard::getInstance().hasData() == true);
        Clipboard::getInstance().copy(test2);
        REQUIRE(Clipboard::getInstance().gotData() == true);
        REQUIRE(Clipboard::getInstance().hasData() == true);
        REQUIRE(Clipboard::getInstance().paste() == test2);
        REQUIRE(Clipboard::getInstance().gotData() == true);
        REQUIRE(Clipboard::getInstance().hasData() == true);
    }

    SECTION("Copy empty string")
    {
        const std::string test1 = "";
        Clipboard::getInstance().copy(test1);
        REQUIRE(Clipboard::getInstance().gotData() == true);
        REQUIRE(Clipboard::getInstance().hasData() == true);
        REQUIRE(Clipboard::getInstance().paste() == test1);
        REQUIRE(Clipboard::getInstance().gotData() == true);
        REQUIRE(Clipboard::getInstance().hasData() == true);
    }
}

M pure_changelog.md => pure_changelog.md +1 -0
@@ 35,6 35,7 @@
* Fixed Alarm disappearance during end of call window
* Fixed passcode behavior when blocked from Mudita Center
* Fixed missing tethering icon on "Tethering is on" window
* Fixed showing "Copy text" option in empty note

## [1.7.2 2023-07-28]