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