M changelog.md => changelog.md +2 -0
@@ 11,6 11,8 @@
* `[appmgr]` Application manager refactored.
### Fixed
+
+* `[desktop][messages]` Fixed notifications display and navigation
* `[cellular]` Fixed 32 bit UCS2 codes handling.
### Other
M image/assets/lang/lang_en.json => image/assets/lang/lang_en.json +3 -2
@@ 170,8 170,8 @@
"app_desktop_sim_blocked_info1": "Sorry, SIM card permanently blocked.",
"app_desktop_sim_blocked_info2": "Please contact your service provider",
- "app_desktop_unread_messages": "Unread messages",
- "app_desktop_missed_calls": "Missed calls",
+ "app_desktop_unread_messages": "<text>Unread <b>messages</b></text>",
+ "app_desktop_missed_calls": "<text>Missed <b>calls</b></text>",
"app_desktop_menu_phone": "PHONE",
"app_desktop_menu_contacts": "CONTACTS",
"app_desktop_menu_messages": "MESSAGES",
@@ 194,6 194,7 @@
"app_desktop_show": "SHOW",
"app_desktop_calls": "CALLS",
"app_desktop_clear": "CLEAR",
+ "app_desktop_clear_all": "CLEAR ALL",
"app_call_call": "CALL",
"app_call_clear": "CLEAR",
M module-apps/application-desktop/ApplicationDesktop.cpp => module-apps/application-desktop/ApplicationDesktop.cpp +10 -5
@@ 97,13 97,18 @@ namespace app
{
assert(msg);
auto records = *msg->getResult();
+
+ bool rebuildMainWindow = false;
+
for (auto record : records) {
switch (record.key) {
case NotificationsRecord::Key::Calls:
+ rebuildMainWindow |= record.value != notifications.notSeen.Calls;
notifications.notSeen.Calls = record.value;
break;
case NotificationsRecord::Key::Sms:
+ rebuildMainWindow |= record.value != notifications.notSeen.SMS;
notifications.notSeen.SMS = record.value;
break;
@@ 114,9 119,11 @@ namespace app
}
}
- /// TODO if current window is this one or was on stack -> requild it
- /// windowsFactory.build(this, app::window::name::desktop_menu);
- /// windowsFactory.build(this, app::window::name::desktop_main_window);
+ auto ptr = getCurrentWindow();
+ if (rebuildMainWindow && ptr->getName() == app::window::name::desktop_main_window) {
+ ptr->rebuild();
+ }
+
return true;
}
@@ 175,7 182,6 @@ namespace app
db::Interface::Name::Notifications,
std::make_unique<db::query::notifications::Clear>(NotificationsRecord::Key::Calls));
notifications.notSeen.Calls = 0;
- getCurrentWindow()->rebuild(); // triggers rebuild - shouldn't be needed, but is
return true;
}
@@ 186,7 192,6 @@ namespace app
db::Interface::Name::Notifications,
std::make_unique<db::query::notifications::Clear>(NotificationsRecord::Key::Sms));
notifications.notSeen.SMS = 0;
- getCurrentWindow()->rebuild(); // triggers rebuild - shouldn't be needed, but is
return true;
}
M module-apps/application-desktop/CMakeLists.txt => module-apps/application-desktop/CMakeLists.txt +3 -0
@@ 17,6 17,7 @@ target_sources( ${PROJECT_NAME}
"${CMAKE_CURRENT_LIST_DIR}/ApplicationDesktop.cpp"
"${CMAKE_CURRENT_LIST_DIR}/widgets/PinLock.cpp"
"${CMAKE_CURRENT_LIST_DIR}/widgets/PinLockHandler.cpp"
+ "${CMAKE_CURRENT_LIST_DIR}/widgets/NotificationsBox.cpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/DesktopMainWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/PinLockBaseWindow.cpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/ScreenLockBox.cpp"
@@ 31,9 32,11 @@ target_sources( ${PROJECT_NAME}
PUBLIC
"${CMAKE_CURRENT_LIST_DIR}/ApplicationDesktop.hpp"
"${CMAKE_CURRENT_LIST_DIR}/data/LockPhoneData.hpp"
+ "${CMAKE_CURRENT_LIST_DIR}/data/Style.hpp"
"${CMAKE_CURRENT_LIST_DIR}/widgets/PinHash.hpp"
"${CMAKE_CURRENT_LIST_DIR}/widgets/PinLock.hpp"
"${CMAKE_CURRENT_LIST_DIR}/widgets/PinLockHandler.hpp"
+ "${CMAKE_CURRENT_LIST_DIR}/widgets/NotificationsBox.hpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/DesktopMainWindow.hpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/PinLockBaseWindow.hpp"
"${CMAKE_CURRENT_LIST_DIR}/windows/PinLockBox.hpp"
A module-apps/application-desktop/data/Style.hpp => module-apps/application-desktop/data/Style.hpp +40 -0
@@ 0,0 1,40 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+namespace style::desktop
+{
+
+ namespace notifications
+ {
+ constexpr auto SpanSize = 8;
+ constexpr auto DigitSize = 14;
+ constexpr auto IconWidth = 35;
+ constexpr auto TextMaxWidth = 250;
+
+ constexpr auto X = 0;
+ constexpr auto Y = 284;
+ constexpr auto Width = style::window_width;
+
+ }; // namespace notifications
+
+ namespace timeLabel
+ {
+ constexpr auto X = 0;
+ constexpr auto Y = 106;
+ constexpr auto Width = style::window_width;
+ constexpr auto Hight = 96;
+
+ } // namespace timeLabel
+
+ namespace dayLabel
+ {
+ constexpr auto X = 0;
+ constexpr auto Y = 204;
+ constexpr auto Width = style::window_width;
+ constexpr auto Hight = 51;
+
+ } // namespace dayLabel
+
+} // namespace style::desktop
A module-apps/application-desktop/widgets/NotificationsBox.cpp => module-apps/application-desktop/widgets/NotificationsBox.cpp +189 -0
@@ 0,0 1,189 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "NotificationsBox.hpp"
+
+#include "application-desktop/data/Style.hpp"
+
+#include "TextFixedSize.hpp"
+#include "RichTextParser.hpp"
+#include "FontManager.hpp"
+
+using namespace gui;
+using namespace style::desktop;
+
+NotificationsBox::NotificationsBox(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
+ : VBox(parent, x, y, w, h)
+{
+ this->setAlignment(Alignment(gui::Alignment::Horizontal::Center));
+ this->setPenWidth(style::window::default_border_no_focus_w);
+ this->setPenFocusWidth(style::window::default_border_no_focus_w);
+
+ auto getNextNotification = [this]() -> Item * {
+ auto focusedItem = getFocusItem();
+ if (focusedItem == nullptr) {
+ return nullptr;
+ }
+ auto nextItem = focusedItem->getNavigationItem(NavigationDirection::UP);
+
+ if (nextItem == nullptr) {
+ nextItem = focusedItem->getNavigationItem(NavigationDirection::DOWN);
+ }
+ return nextItem;
+ };
+
+ auto setNextFocusedItemAfterErase = [this](Item *item) -> bool {
+ if (item == nullptr) {
+ setFocus(false);
+ }
+ else {
+ item->clearNavigationItem(NavigationDirection::DOWN);
+ item->clearNavigationItem(NavigationDirection::UP);
+ setNavigation();
+ setFocusItem(item);
+ }
+ return true;
+ };
+
+ inputCallback = [this, setNextFocusedItemAfterErase, getNextNotification](Item &, const InputEvent &event) -> bool {
+ if (event.isShortPress() && event.is(KeyCode::KEY_RF)) {
+ LOG_DEBUG("Removing single notification");
+ auto ptr = getFocusItem();
+ if (ptr == nullptr || focusItem == this) {
+ return false;
+ }
+ auto nextItem = getNextNotification();
+ ptr->inputCallback(*this, event);
+ erase(ptr);
+ return setNextFocusedItemAfterErase(nextItem);
+ }
+ return false;
+ };
+}
+
+namespace
+{
+ auto buildImageInactive(const UTF8 &img) -> gui::Image *
+ {
+ auto thumbnail = new gui::Image(img);
+ thumbnail->activeItem = false;
+ return thumbnail;
+ }
+
+ auto buildNotificationIcon(UTF8 icon) -> gui::Image *
+ {
+ auto thumbnail = buildImageInactive(icon);
+ thumbnail->setMinimumWidth(notifications::IconWidth);
+ thumbnail->setAlignment(Alignment(gui::Alignment::Horizontal::Right, gui::Alignment::Vertical::Center));
+ thumbnail->setMargins(
+ gui::Margins(style::window::default_left_margin, 0, style::window::default_right_margin, 0));
+ return thumbnail;
+ }
+
+ auto buildNotificationNameLabel(const UTF8 &name, uint32_t width) -> gui::TextFixedSize *
+ {
+ auto text = new gui::TextFixedSize(
+ nullptr, 0, 0, style::desktop::notifications::TextMaxWidth, style::window::label::default_h);
+ text->setMaximumSize(width, Axis::X);
+
+ TextFormat format(FontManager::getInstance().getFont(style::window::font::medium));
+ text::RichTextParser rtParser;
+ auto parsedText = rtParser.parse(name, &format);
+
+ text->setText(std::move(parsedText));
+ text->setAlignment(Alignment(gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center));
+ text->setPenWidth(style::window::default_border_no_focus_w);
+ text->setUnderline(false);
+ text->activeItem = false;
+ return text;
+ }
+
+ constexpr auto maxNotificationValue = "99+";
+
+ auto buildNotificationCountText(const UTF8 &indicator) -> gui::Text *
+ {
+ auto number = new gui::Text();
+ if (indicator.length() > 2) {
+ number->setText(maxNotificationValue);
+ number->setMinimumWidth(strlen(maxNotificationValue) * notifications::DigitSize);
+ }
+ else {
+ number->setText(indicator);
+ number->setMinimumWidth(indicator.length() * notifications::DigitSize);
+ }
+ number->setMinimumWidth(indicator.length() * notifications::DigitSize);
+ number->setFont(style::window::font::mediumbold);
+ number->setPenWidth(style::window::default_border_no_focus_w);
+ number->setMargins(gui::Margins(0, 0, style::window::default_right_margin, 0));
+ number->setAlignment(Alignment(gui::Alignment::Horizontal::Right, gui::Alignment::Vertical::Center));
+ number->activeItem = false;
+ return number;
+ }
+
+} // namespace
+
+auto NotificationsBox::addNotification(UTF8 icon,
+ UTF8 name,
+ UTF8 indicator,
+ std::function<bool()> showCallback,
+ std::function<bool()> clearCallback,
+ std::function<void(bool)> onFocus) -> bool
+{
+ // 1. create hbox for all elements
+ auto el = new gui::HBox(nullptr, 0, 0, style::window::default_body_width, style::window::label::default_h);
+
+ // 2. Add all elements to hbox layout
+ el->addWidget(buildNotificationIcon(icon));
+
+ el->addWidget(buildNotificationNameLabel(name, el->area().w));
+ el->addWidget(buildImageInactive("dot_12px_hard_alpha_W_G"));
+ el->addWidget(buildNotificationCountText(indicator));
+
+ // 3. Set hbox layout properties
+ el->setAlignment(Alignment(gui::Alignment::Vertical::Center));
+ el->setMargins(gui::Margins(0, 0, 0, 10));
+ el->setPenWidth(style::window::default_border_no_focus_w);
+ el->setPenFocusWidth(style::window::default_border_focus_w);
+ el->setEdges(RectangleEdge::Bottom | RectangleEdge::Top);
+
+ el->focusChangedCallback = [el, onFocus](Item &) -> bool {
+ onFocus(el->focus);
+ return true;
+ };
+ el->activatedCallback = [showCallback](Item &) { return showCallback(); };
+ el->inputCallback = [showCallback, clearCallback, this](Item &, const InputEvent &event) -> bool {
+ if (event.isShortPress() && event.is(KeyCode::KEY_RF) && clearCallback) {
+ return clearCallback();
+ }
+ return false;
+ };
+
+ this->addWidget(el);
+ return el->visible;
+}
+
+bool NotificationsBox::onInput(const InputEvent &inputEvent)
+{
+
+ if (inputEvent.isShortPress() && (inputEvent.is(KeyCode::KEY_UP) || inputEvent.is(KeyCode::KEY_DOWN))) {
+ auto handled = handleNavigation(inputEvent);
+ if (!handled) {
+ setFocus(false);
+ }
+ return true;
+ }
+ return VBox::onInput(inputEvent);
+}
+
+bool NotificationsBox::clearAll(const InputEvent &event)
+{
+ while (!children.empty()) {
+ inputCallback(*this, event);
+ }
+ return true;
+}
+
+void NotificationsBox::navigateToBottom()
+{
+ setFocusItem(children.back());
+}
A module-apps/application-desktop/widgets/NotificationsBox.hpp => module-apps/application-desktop/widgets/NotificationsBox.hpp +28 -0
@@ 0,0 1,28 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include "BoxLayout.hpp"
+#include "Icon.hpp"
+
+namespace gui
+{
+ class NotificationsBox : public VBox
+ {
+ public:
+ NotificationsBox(Item *parent, uint32_t x, uint32_t y, uint32_t w, uint32_t h);
+
+ auto addNotification(UTF8 icon,
+ UTF8 name,
+ UTF8 indicator,
+ std::function<bool()> showCallback,
+ std::function<bool()> clearCallback,
+ std::function<void(bool)> onFocus) -> bool;
+
+ bool onInput(const InputEvent &inputEvent) override;
+ bool clearAll(const InputEvent &event);
+
+ void navigateToBottom();
+ };
+} // namespace gui
M module-apps/application-desktop/windows/DesktopMainWindow.cpp => module-apps/application-desktop/windows/DesktopMainWindow.cpp +80 -139
@@ 10,6 10,8 @@
#include "GuiTimer.hpp"
#include "application-desktop/ApplicationDesktop.hpp"
#include "application-desktop/data/LockPhoneData.hpp"
+#include "application-desktop/data/Style.hpp"
+#include "application-desktop/widgets/NotificationsBox.hpp"
#include "application-messages/ApplicationMessages.hpp"
#include "gui/widgets/Image.hpp"
#include "service-appmgr/Controller.hpp"
@@ 19,26 21,12 @@
#include "i18/i18.hpp"
#include "log/log.hpp"
-#include <Span.hpp>
-#include <Style.hpp>
+
#include <application-settings-new/ApplicationSettings.hpp>
#include <application-settings/ApplicationSettings.hpp>
#include <cassert>
#include <time/time_conversion.hpp>
-namespace style
-{
- const auto design_time_offset = 106;
- const auto design_time_h = 96;
- const auto design_day_offset = 204;
- const auto design_day_h = 51;
- const auto design_border_offset = 20;
- const auto design_option_span = 8;
- const auto design_notifications_offset = 284;
- const auto digit_normal_size = 13;
- const auto notification_icon_unified_size = 35;
-}; // namespace style
-
namespace gui
{
void DesktopMainWindow::buildInterface()
@@ 50,20 38,27 @@ namespace gui
topBar->setActive(
{{TopBar::Elements::SIGNAL, true}, {TopBar::Elements::LOCK, true}, {TopBar::Elements::BATTERY, true}});
- time = new gui::Label(this, 0, style::design_time_offset, style::window_width, style::design_time_h);
+ using namespace style::desktop;
+
+ time = new gui::Label(this, timeLabel::X, timeLabel::Y, timeLabel::Width, timeLabel::Hight);
time->setFilled(false);
time->setBorderColor(gui::ColorNoColor);
time->setFont(style::window::font::supersizemelight);
time->setText(ttime);
time->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));
- dayText = new gui::Label(this, 0, style::design_day_offset, style::window_width, style::design_day_h);
+ dayText = new gui::Label(this, dayLabel::X, dayLabel::Y, dayLabel::Width, dayLabel::Hight);
dayText->setFilled(false);
dayText->setBorderColor(gui::ColorNoColor);
dayText->setFont(style::window::font::biglight);
dayText->setText(ttime.day() + ", " + ttime.str("%d %b"));
dayText->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Top));
+ activatedCallback = [this](Item &) {
+ application->switchWindow(app::window::name::desktop_menu);
+ return true;
+ };
+
setVisibleState();
}
@@ 90,12 85,12 @@ namespace gui
auto app = getAppDesktop();
if (app->lockHandler.lock.isLocked() && app->lockHandler.lock.getLockType() == PinLock::LockType::Screen) {
- bottomBar->restore();
+
bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get("app_desktop_unlock"));
topBar->setActive(TopBar::Elements::LOCK, true);
inputCallback = nullptr;
setFocusItem(nullptr);
- erase(notifications);
+ buildNotifications(app);
sys::Bus::SendUnicast(
std::make_shared<TimersProcessingStopMessage>(), service::name::service_time, application);
@@ 107,11 102,13 @@ namespace gui
std::make_shared<TimersProcessingStopMessage>(), service::name::service_time, application);
}
else {
- bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get("app_desktop_menu"));
topBar->setActive(TopBar::Elements::LOCK, false);
- if (!fillNotifications(app)) {
+
+ if (!buildNotifications(app)) {
LOG_ERROR("Couldn't fit in all notifications");
}
+ setActiveState(app);
+
if (app->need_sim_select && Store::GSM::get()->sim == Store::GSM::SIM::SIM_UNKNOWN) {
app::manager::Controller::switchApplication(
this->application, app::name_settings, app::sim_select, nullptr);
@@ 120,6 117,7 @@ namespace gui
sys::Bus::SendUnicast(
std::make_shared<TimersProcessingStartMessage>(), service::name::service_time, application);
}
+ application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
}
void DesktopMainWindow::onBeforeShow(ShowMode mode, SwitchData *data)
@@ 145,19 143,19 @@ namespace gui
{
auto *app = getAppDesktop();
- if ((inputEvent.keyCode == KeyCode::KEY_PND) && (!app->lockHandler.lock.isLocked())) {
+ if (inputEvent.is(KeyCode::KEY_PND) && (!app->lockHandler.lock.isLocked())) {
app->lockHandler.lock.lock();
setVisibleState();
application->refreshWindow(RefreshModes::GUI_REFRESH_FAST);
application->setSuspendFlag(true);
return true;
}
- else if (inputEvent.keyCode == KeyCode::KEY_RF) {
+ else if (inputEvent.is(KeyCode::KEY_RF)) {
application->switchWindow("PowerOffWindow");
return true;
}
// long press of '0' key is translated to '+'
- else if (inputEvent.keyCode == KeyCode::KEY_0) {
+ else if (inputEvent.is(KeyCode::KEY_0)) {
return app::prepareCall(application, "+");
}
// check if any of the lower inheritance onInput methods catch the event
@@ 167,14 165,19 @@ namespace gui
bool DesktopMainWindow::processShortPressEventOnUnlocked(const InputEvent &inputEvent)
{
auto code = translator.handle(inputEvent.key, InputMode({InputMode::phone}).get());
- if (inputEvent.keyCode == KeyCode::KEY_ENTER) {
- application->switchWindow(app::window::name::desktop_menu);
- return true;
- }
// if numeric key was pressed record that key and send it to call application
- else if (code != 0) {
+ if (code != 0) {
return app::prepareCall(application, std::string(1, static_cast<char>(code)));
}
+ else if (inputEvent.is(KeyCode::KEY_UP) && focusItem == nullptr) {
+ setFocusItem(notifications);
+ notifications->navigateToBottom();
+ return true;
+ }
+ else if (inputEvent.is(KeyCode::KEY_DOWN) && focusItem == nullptr) {
+ setFocusItem(notifications);
+ return true;
+ }
// check if any of the lower inheritance onInput methods catch the event
return AppWindow::onInput(inputEvent);
}
@@ 252,123 255,38 @@ namespace gui
return gui::AppWindow::buildDrawList();
}
- auto add_image_inactive(UTF8 img)
- {
- auto thumbnail = new gui::Image(img);
- thumbnail->activeItem = false;
- return thumbnail;
- }
-
- auto add_box_icon(UTF8 icon)
- {
- auto thumbnail = add_image_inactive(icon);
- thumbnail->setMinimumWidth(style::notification_icon_unified_size);
- thumbnail->setMargins(
- gui::Margins(style::window::default_left_margin, 0, style::window::default_right_margin, 0));
- return thumbnail;
- }
-
- /// for now notifications are like that: `^<span>[icon]<span>[dumb text] [dot image] [number of
- /// notifications]<span>$`
- auto add_notification(BoxLayout *layout,
- UTF8 icon,
- UTF8 name,
- UTF8 indicator,
- std::function<bool()> showCallback,
- std::function<bool()> clearCallback) -> bool
- {
- // 1. create hbox for all elements
- auto el = new gui::HBox(nullptr, 0, 0, style::window::default_body_width, style::window::label::default_h);
- el->setAlignment(Alignment(gui::Alignment::Vertical::Center));
-
- auto text = new gui::Label();
- text->setMaximumSize(el->area().w, Axis::X);
- text->setText(name);
- text->setFont(style::window::font::medium);
- text->setAlignment(Alignment(gui::Alignment::Horizontal::Left, gui::Alignment::Vertical::Center));
- text->setPenWidth(style::window::default_border_no_focus_w);
- text->activeItem = false;
-
- auto number = new gui::Text();
- if (indicator.length() > 2) {
- const UTF8 max_notification_value = "99+";
- number->setText(max_notification_value);
- number->setMinimumWidth(max_notification_value.length() * style::digit_normal_size);
- }
- else {
- number->setText(indicator);
- number->setMinimumWidth(indicator.length() * style::digit_normal_size);
- }
- number->setFont(style::window::font::mediumbold);
- number->setPenWidth(style::window::default_border_no_focus_w);
- number->setMargins(gui::Margins(0, 0, style::window::default_right_margin, 0));
- number->setAlignment(Alignment(gui::Alignment::Horizontal::Right, gui::Alignment::Vertical::Center));
- number->activeItem = false;
-
- // 2. Add all elements to hbox layout
- el->addWidget(add_box_icon(icon));
- el->addWidget(text);
- el->addWidget(add_image_inactive("dot_12px_hard_alpha_W_G"));
- el->addWidget(number);
-
- // 3. Set hbox layout properties
- el->setPenWidth(style::window::default_border_no_focus_w);
- el->setPenFocusWidth(style::window::default_border_focus_w);
- el->setEdges(RectangleEdge::Bottom | RectangleEdge::Top);
- el->inputCallback = [showCallback, clearCallback](Item &, const InputEvent &event) -> bool {
- if (event.state != InputEvent::State::keyReleasedShort) {
- return false;
- }
- if (event.keyCode == KeyCode::KEY_LF && showCallback) {
- return showCallback();
- }
- if (event.keyCode == KeyCode::KEY_RF && clearCallback) {
- return clearCallback();
- }
- return false;
- };
-
- layout->addWidget(el);
- if (el->visible) {
- // space between next notifications to show
- layout->addWidget(new gui::Span(Axis::Y, style::design_option_span));
- }
-
- return el->visible;
- }
-
- auto DesktopMainWindow::fillNotifications(app::ApplicationDesktop *app) -> bool
+ auto DesktopMainWindow::buildNotifications(app::ApplicationDesktop *app) -> bool
{
- bottomBar->restore();
erase(notifications);
- // 1. create notifications box
- notifications = new gui::VBox(nullptr,
- 0,
- style::design_notifications_offset,
- style::window_width,
- bottomBar->widgetArea.pos(Axis::Y) - style::design_notifications_offset);
- notifications->setAlignment(Alignment(gui::Alignment::Horizontal::Center));
- notifications->setPenWidth(style::window::default_border_no_focus_w);
- notifications->setPenFocusWidth(style::window::default_border_no_focus_w);
- this->addWidget(notifications);
+ using namespace style::desktop;
+ notifications = new NotificationsBox(this,
+ notifications::X,
+ notifications::Y,
+ notifications::Width,
+ bottomBar->widgetArea.pos(Axis::Y) - notifications::Y);
+
+ addWidget(notifications);
if (!notifications->visible) {
LOG_ERROR("Can't fit notifications box!");
return false;
}
- // 2. actually fill it in
+ auto onNotificationFocus = [this](bool isFocused) -> void {
+ bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get("app_desktop_show"), isFocused);
+ bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get("app_desktop_clear"), isFocused);
+ };
+
if (app->notifications.notSeen.Calls > 0) {
- add_notification(
- notifications,
+ notifications->addNotification(
"phone",
utils::localize.get("app_desktop_missed_calls"),
std::to_string(app->notifications.notSeen.Calls),
[app]() -> bool { return app->showCalls(); },
- [app]() -> bool { return app->clearCallsNotification(); });
+ [app]() -> bool { return app->clearCallsNotification(); },
+ onNotificationFocus);
}
if (app->notifications.notSeen.SMS > 0) {
- add_notification(
- notifications,
+ notifications->addNotification(
"mail",
utils::localize.get("app_desktop_unread_messages"),
std::to_string(app->notifications.notSeen.SMS),
@@ 376,19 294,42 @@ namespace gui
return app::manager::Controller::switchApplication(
application, app::name_messages, gui::name::window::main_window, nullptr);
},
- [app]() -> bool { return app->clearMessagesNotification(); });
+ [app, this]() -> bool { return app->clearMessagesNotification(); },
+ onNotificationFocus);
}
- bottomBar->store();
+
+ notifications->focusChangedCallback = [this, app](Item &) -> bool {
+ if (notifications->focus == false) {
+ LOG_DEBUG("All notifications removed, notification box lost focus");
+ bottomBar->setActive(BottomBar::Side::RIGHT, false);
+ setFocusItem(nullptr);
+ setActiveState(app);
+ return true;
+ }
+ return false;
+ };
+
+ return true;
+ }
+ auto DesktopMainWindow::setActiveState(app::ApplicationDesktop *app) -> bool
+ {
+ bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get("app_desktop_menu"));
if (app->notifications.notSeen.areEmpty() != true) {
- setFocusItem(notifications);
- bottomBar->setText(BottomBar::Side::LEFT, utils::localize.get("app_desktop_show"));
- bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get("app_desktop_clear"));
+ bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get("app_desktop_clear_all"));
+ inputCallback = [this, app](Item &, const InputEvent &inputEvent) -> bool {
+ if (inputEvent.isShortPress() && inputEvent.is(KeyCode::KEY_RF) && getFocusItem() == nullptr) {
+ LOG_DEBUG("KEY_RF pressed to clear all notifications");
+ setFocusItem(notifications);
+ return notifications->clearAll(inputEvent);
+ }
+ return false;
+ };
}
else {
bottomBar->setText(BottomBar::Side::LEFT, utils::localize.get("app_desktop_calls"));
inputCallback = [app](Item &, const InputEvent &inputEvent) -> bool {
- if (inputEvent.state == InputEvent::State::keyReleasedShort &&
- inputEvent.keyCode == gui::KeyCode::KEY_LF) {
+ if (inputEvent.isShortPress() && inputEvent.is(gui::KeyCode::KEY_LF)) {
+ LOG_DEBUG("KEY_LF pressed to navigate to calls");
return app->showCalls();
}
return false;
M module-apps/application-desktop/windows/DesktopMainWindow.hpp => module-apps/application-desktop/windows/DesktopMainWindow.hpp +7 -7
@@ 4,13 4,11 @@
#pragma once
#include "AppWindow.hpp"
-#include "gui/widgets/BottomBar.hpp"
-#include "gui/widgets/Image.hpp"
#include "gui/widgets/Label.hpp"
-#include "gui/widgets/Text.hpp"
-#include "gui/widgets/TopBar.hpp"
#include "gui/widgets/Window.hpp"
+#include "Translator.hpp"
+
namespace app
{
class ApplicationDesktop;
@@ 18,13 16,14 @@ namespace app
namespace gui
{
+ class NotificationsBox;
class DesktopMainWindow : public AppWindow
{
protected:
gui::Label *time = nullptr;
gui::Label *dayText = nullptr;
- gui::VBox *notifications = nullptr;
+ gui::NotificationsBox *notifications = nullptr;
/// Timed enter value cache, could be templated to any value really
class EnterCache
@@ 59,13 58,14 @@ namespace gui
}
} enter_cache;
/**
- * Name of the appliction that was on top when lock timeout occured
+ * Name of the application that was on top when lock timeout occurred
*/
std::string lockTimeoutApplilcation = "";
// method hides or show widgets and sets bars according to provided state
void setVisibleState();
- auto fillNotifications(app::ApplicationDesktop *app) -> bool;
+ auto buildNotifications(app::ApplicationDesktop *app) -> bool;
+ auto setActiveState(app::ApplicationDesktop *app) -> bool;
bool processLongPressEvent(const InputEvent &inputEvent);
bool processShortPressEventOnUnlocked(const InputEvent &inputEvent);
bool processShortPressEventOnLocked(const InputEvent &inputEvent);