~aleteoryx/muditaos

91e67f4865415c27487a3e49c4a044caad4a6369 — Adam 5 years ago 02fa0f5
EGD-4102 (#871)

* EGD-4102 Added log to refreshed window and null check

* EGD-4102 Fixed messages crash

* EGD-4102 Fixed calendar crash and some funky code
M changelog.md => changelog.md +1 -0
@@ 17,6 17,7 @@
* `[audio]` Fix headphones autodetection.
* `[audio]` Cumulative set of minor fixes and improvements.
* `[db][vfs]` Fixed database corruption issues on abrupt phone reset.
* `[calendar]` add event crash

### Other


M image/assets/lang/lang_en.json => image/assets/lang/lang_en.json +1 -1
@@ 84,7 84,7 @@
    "app_calendar_event_detail": "Event",
    "app_calendar_event_detail_repeat": "Repeat",
    "app_calendar_event_detail_reminder": "Reminder",
    "app_calendar_no_events_information": "No events yet.\nPress left arrow to add new.",
    "app_calendar_no_events_information": "<text align='center' color='9'>No events yet.<p>Press <b>left arrow</b> to add new.</p></text>",
    "app_calendar_repeat_never": "Never",
    "app_calendar_repeat_daily": "Daily",
    "app_calendar_repeat_weekly": "Weekly",

M module-apps/Application.cpp => module-apps/Application.cpp +2 -0
@@ 113,6 113,8 @@ namespace app
            return;
        }

        LOG_DEBUG("Rendering %s", getCurrentWindow()->getName().c_str());

        // send drawing commands only when if application is in active and visible.
        if (state == State::ACTIVE_FORGROUND) {
            auto currwin = getCurrentWindow();

M module-apps/application-calendar/ApplicationCalendar.cpp => module-apps/application-calendar/ApplicationCalendar.cpp +10 -12
@@ 2,6 2,7 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "ApplicationCalendar.hpp"
#include "DialogMetadataMessage.hpp"
#include "windows/CalendarMainWindow.hpp"
#include "windows/DayEventsWindow.hpp"
#include "windows/CalendarEventsOptionsWindow.hpp"


@@ 125,7 126,7 @@ namespace app
            return std::make_unique<gui::DayEventsWindow>(app);
        });
        windowsFactory.attach(no_events_window, [](Application *app, const std::string &name) {
            return std::make_unique<gui::NoEvents>(app, name, gui::NoEvents::Meta());
            return std::make_unique<gui::NoEvents>(app, name);
        });
        windowsFactory.attach(style::window::calendar::name::events_options,
                              [](Application *app, const std::string &name) {


@@ 156,14 157,15 @@ namespace app

    void ApplicationCalendar::switchToNoEventsWindow(const std::string &title, const TimePoint &dateFilter)
    {
        if (equivalentWindow == EquivalentWindow::DayEventsWindow) {
            popToWindow(gui::name::window::main_window);
            return;
        }

        auto dialog = dynamic_cast<gui::NoEvents *>(windowsStack.get(style::window::calendar::name::no_events_window));
        assert(dialog != nullptr);
        auto meta  = dialog->meta;
        meta.text  = "app_calendar_no_events_information";
        gui::DialogMetadata meta;
        meta.text   = utils::localize.get("app_calendar_no_events_information");
        meta.title = title;
        meta.icon  = "phonebook_empty_grey_circle_W_G";

        meta.action = [=]() -> bool {
            LOG_DEBUG("Switch to new event window");
            std::unique_ptr<EventRecordData> eventData = std::make_unique<EventRecordData>();


@@ 178,13 180,9 @@ namespace app
            return true;
        };

        if (equivalentWindow == EquivalentWindow::DayEventsWindow) {
            popToWindow(gui::name::window::main_window);
        }

        dialog->update(meta);
        switchWindow(dialog->getName());
        LOG_DEBUG("Switch to no events window");
        switchWindow(style::window::calendar::name::no_events_window,
                     std::make_unique<gui::DialogMetadataMessage>(meta));
    }

} /* namespace app */

M module-apps/application-calendar/data/CalendarData.hpp => module-apps/application-calendar/data/CalendarData.hpp +7 -0
@@ 38,6 38,13 @@ class WeekDaysRepeatData : public gui::SwitchData
    virtual void setData(const uint32_t weekDay);
};

class DayEventsWindowMessage : public gui::SwitchData
{
  public:
    std::unique_ptr<std::vector<EventsRecord>> records;
    ~DayEventsWindowMessage() = default;
};

class DayMonthData : public gui::SwitchData
{
  protected:

M module-apps/application-calendar/widgets/DayLabel.cpp => module-apps/application-calendar/widgets/DayLabel.cpp +28 -1
@@ 7,6 7,8 @@
#include "application-calendar/widgets/MonthBox.hpp"
#include "application-calendar/data/CalendarData.hpp"
#include <time/time_conversion.hpp>
#include <module-db/queries/calendar/QueryEventsGetFiltered.hpp>
#include <module-services/service-db/api/DBServiceAPI.hpp>

namespace gui
{


@@ 76,7 78,32 @@ namespace gui
                auto filter = TimePointFromYearMonthDay(dateFilter);
                data->setData(number + " " + month, filter);
                LOG_DEBUG("Switch to DayEventsWindow");
                app->switchWindow(style::window::calendar::name::day_events_window, std::move(data));

                /////
                auto filterTill = filter + std::chrono::hours(style::window::calendar::time::max_hour_24H_mode + 1);
                auto query      = std::make_unique<db::query::events::GetFiltered>(filter, filterTill);
                query->setQueryListener(
                    db::QueryCallback::fromFunction([app, filter, number, month](db::QueryResult *result) {
                        if (const auto response = dynamic_cast<db::query::events::GetFilteredResult *>(result)) {
                            std::unique_ptr<std::vector<EventsRecord>> records = response->getResult();
                            auto application = dynamic_cast<app::ApplicationCalendar *>(app);
                            assert(application != nullptr);
                            if (records->empty()) {
                                auto name = number + " " + month;
                                application->switchToNoEventsWindow(name, filter);
                                return true;
                            }
                            /// aaaand here switch to DauEventsWindow!
                            auto message     = std::make_unique<DayEventsWindowMessage>();
                            message->records = std::move(records);
                            app->switchWindow(style::window::calendar::name::day_events_window, std::move(message));
                            return true;
                        }
                        return false;
                    }));
                DBServiceAPI::GetQuery(app, db::Interface::Name::Events, std::move(query));
                /////

                return true;
            };
            this->setPenWidth(style::window::default_border_no_focus_w);

M module-apps/application-calendar/windows/DayEventsWindow.cpp => module-apps/application-calendar/windows/DayEventsWindow.cpp +6 -19
@@ 3,6 3,7 @@

#include "DayEventsWindow.hpp"
#include "application-calendar/data/CalendarData.hpp"
#include "log/log.hpp"
#include "module-apps/application-calendar/ApplicationCalendar.hpp"
#include <gui/widgets/Window.hpp>
#include <gui/widgets/Label.hpp>


@@ 32,11 33,6 @@ namespace gui
    }
    void DayEventsWindow::onBeforeShow(ShowMode mode, SwitchData *data)
    {
        auto filterTill = filterFrom + std::chrono::hours(style::window::calendar::time::max_hour_24H_mode + 1);
        auto query      = std::make_unique<db::query::events::GetFiltered>(filterFrom, filterTill);
        query->setQueryListener(
            db::QueryCallback::fromFunction([this](auto response) { return handleQueryResponse(response); }));
        DBServiceAPI::GetQuery(application, db::Interface::Name::Events, std::move(query));
        setTitle(dayMonthTitle);
    }



@@ 46,6 42,11 @@ namespace gui
            return false;
        }

        auto message = dynamic_cast<DayEventsWindowMessage *>(data);
        if (message != nullptr) {
            dayEventsModel->loadData(std::move(message->records));
        }

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


@@ 114,20 115,6 @@ namespace gui

    auto DayEventsWindow::handleQueryResponse(db::QueryResult *queryResult) -> bool
    {
        if (const auto response = dynamic_cast<db::query::events::GetFilteredResult *>(queryResult)) {
            std::unique_ptr<std::vector<EventsRecord>> records = response->getResult();
            auto app                                           = dynamic_cast<app::ApplicationCalendar *>(application);
            assert(application != nullptr);
            app->setEquivalentToEmptyWindow(EquivalentWindow::DayEventsWindow);
            if (records->empty()) {
                auto name = dayMonthTitle;
                app->switchToNoEventsWindow(name, filterFrom);
                return true;
            }
            dayEventsModel->loadData(std::move(records));
            application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
            return true;
        }
        LOG_DEBUG("Response False");
        return false;
    }

M module-apps/application-messages/ApplicationMessages.cpp => module-apps/application-messages/ApplicationMessages.cpp +1 -3
@@ 289,9 289,7 @@ namespace app

    bool ApplicationMessages::showSearchResults(const UTF8 &title, const UTF8 &search_text)
    {
        auto name = gui::name::window::search_results;
        windowsStack.get(name)->setTitle(title);
        switchWindow(name, std::make_unique<SMSTextToSearch>(search_text));
        switchWindow(gui::name::window::search_results, std::make_unique<SMSTextToSearch>(search_text, title));
        return true;
    }


M module-apps/application-messages/data/SMSTextToSearch.cpp => module-apps/application-messages/data/SMSTextToSearch.cpp +2 -1
@@ 3,7 3,8 @@

#include "SMSTextToSearch.hpp"

SMSTextToSearch::SMSTextToSearch(const std::string text_to_search) : text_to_search(text_to_search)
SMSTextToSearch::SMSTextToSearch(const std::string text_to_search, const std::string title)
    : text_to_search(text_to_search), title(title)
{}

auto SMSTextToSearch::getTextToSearch() const -> std::string

M module-apps/application-messages/data/SMSTextToSearch.hpp => module-apps/application-messages/data/SMSTextToSearch.hpp +6 -1
@@ 8,8 8,13 @@
class SMSTextToSearch : public gui::SwitchData
{
    std::string text_to_search;
    std::string title;

  public:
    SMSTextToSearch(const std::string text_to_search);
    SMSTextToSearch(const std::string text_to_search, const std::string title);
    [[nodiscard]] auto getTextToSearch() const -> std::string;
    [[nodiscard]] auto getTitle() const -> std::string
    {
        return title;
    }
};

M module-apps/windows/AppWindow.cpp => module-apps/windows/AppWindow.cpp +4 -1
@@ 78,7 78,10 @@ namespace gui
    {
        // get old value of battery level, calcualte new level and comapre both
        // if they are different make a change and return true, otherwise return false;
        return topBar->setBatteryLevel(percentage);
        if (topBar != nullptr) {
            return topBar->setBatteryLevel(percentage);
        }
        return false;
    }
    // updates battery level in the window
    bool AppWindow::updateSignalStrength()

M module-apps/windows/NoEvents.cpp => module-apps/windows/NoEvents.cpp +15 -75
@@ 2,6 2,9 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "NoEvents.hpp"
#include "Dialog.hpp"
#include "DialogMetadataMessage.hpp"
#include "log/log.hpp"
#include <service-appmgr/ApplicationManager.hpp>
#include <i18/i18.hpp>
#include <module-services/service-db/messages/QueryMessage.hpp>


@@ 26,83 29,20 @@ namespace style
    } // namespace cross
} // namespace style

NoEvents::NoEvents(app::Application *app, const std::string &name, const NoEvents::Meta &meta)
    : gui::AppWindow(app, name), meta(meta)
NoEvents::NoEvents(app::Application *app, const std::string &name) : gui::Dialog(app, name)
{}

void NoEvents::buildInterface()
void NoEvents::onBeforeShow(ShowMode mode, SwitchData *data)
{
    AppWindow::buildInterface();

    topBar->setActive(gui::TopBar::Elements::TIME, true);
    bottomBar->setActive(gui::BottomBar::Side::RIGHT, true);
    bottomBar->setText(gui::BottomBar::Side::RIGHT, utils::localize.get(style::strings::common::back));

    auto app = dynamic_cast<app::ApplicationCalendar *>(application);
    assert(app != nullptr);
    if (app->getEquivalentToEmptyWindow() == EquivalentWindow::AllEventsWindow) {
        bottomBar->setText(gui::BottomBar::Side::LEFT, utils::localize.get("app_calendar_bar_month"));
    Dialog::onBeforeShow(mode, data);
    auto metadata = dynamic_cast<DialogMetadataMessage *>(data);
    if (metadata != nullptr) {
        auto foo      = metadata->get().action;
        inputCallback = [foo](Item &, const InputEvent &inputEvent) -> bool {
            if (foo && inputEvent.isShortPress() && inputEvent.is(KeyCode::KEY_LEFT)) {
                return foo();
            }
            return false;
        };
    }

    setTitle(meta.title);
    leftArrowImage = new gui::Image(this, style::arrow::x, style::arrow::y, 0, 0, "arrow_left");
    newEventImage  = new gui::Image(this, style::cross::x, style::cross::y, 0, 0, "cross");

    emptyListIcon = new gui::Icon(this,
                                  0,
                                  style::header::height,
                                  style::window_width,
                                  style::window_height - style::header::height - style::footer::height,
                                  meta.icon,
                                  utils::localize.get(meta.text));
}

void NoEvents::update(const Meta &meta)
{
    this->meta = meta;
    rebuild();
}

void NoEvents::rebuild()
{
    AppWindow::destroyInterface();
    erase();
    buildInterface();
}

bool NoEvents::onInput(const gui::InputEvent &inputEvent)
{
    auto app = dynamic_cast<app::ApplicationCalendar *>(application);
    assert(app != nullptr);

    if (inputEvent.keyCode == gui::KeyCode::KEY_RF && inputEvent.state == gui::InputEvent::State::keyReleasedShort) {
        if (app->getEquivalentToEmptyWindow() == EquivalentWindow::DayEventsWindow) {
            app->returnToPreviousWindow();
        }
        else if (app->getEquivalentToEmptyWindow() == EquivalentWindow::AllEventsWindow) {
            LOG_DEBUG("Switch to desktop");
            sapm::ApplicationManager::messageSwitchPreviousApplication(application);
        }
    }

    if (AppWindow::onInput(inputEvent)) {
        return true;
    }

    if (!inputEvent.isShortPress()) {
        return false;
    }

    if (inputEvent.keyCode == gui::KeyCode::KEY_LEFT) {
        return meta.action();
    }

    if (inputEvent.keyCode == gui::KeyCode::KEY_LF &&
        app->getEquivalentToEmptyWindow() == EquivalentWindow::AllEventsWindow) {
        application->switchWindow(gui::name::window::main_window);
        LOG_DEBUG("Switch to month view - main window");
        return true;
    }

    return false;
}
\ No newline at end of file

M module-apps/windows/NoEvents.hpp => module-apps/windows/NoEvents.hpp +4 -29
@@ 3,10 3,8 @@

#pragma once

#include "AppWindow.hpp"
#include <gui/widgets/Icon.hpp>
#include <Text.hpp>
#include <functional>
#include "Dialog.hpp"

/// Provides information witch window is equivalent to empty window (DayEvents window and AllEvents window may be empty)
enum class EquivalentWindow


@@ 18,34 16,11 @@ enum class EquivalentWindow

namespace gui
{
    /// @brief base NoEvents class
    ///
    /// Contain icon, text, Back action and switch to new/edit event window action
    class NoEvents : public AppWindow
    class NoEvents : public Dialog
    {
      protected:
        Image *leftArrowImage = nullptr;
        Image *newEventImage  = nullptr;
        Icon *emptyListIcon   = nullptr;

      public:
        struct Meta
        {
            std::string title;
            UTF8 text;
            UTF8 icon;
            std::function<bool()> action = []() -> bool { return false; };

            Meta() = default;
        } meta;

        NoEvents(app::Application *app, const std::string &name, const Meta &meta);
        ~NoEvents() override = default;

        virtual void update(const Meta &meta);
        bool onInput(const gui::InputEvent &inputEvent) override;
        void rebuild() override;
        void buildInterface() override;
        NoEvents(app::Application *app, const std::string &name);
        void onBeforeShow(ShowMode mode, SwitchData *data) override;
    };

}; // namespace gui