mirror of
https://github.com/mudita/MuditaOS.git
synced 2026-07-04 13:17:08 -04:00
[EGD-2394] SMS Thread gui implementation
* added handle for DB update in application * thread - ready to decorate SMS on different sms types * WORKAROUND - Show thread of messages work - Text cant be set to empty, so add space instead of empty text * AppSMS made stack big enough for sms app lifetime
This commit is contained in:
@@ -11,7 +11,6 @@
|
||||
#include "Margins.hpp"
|
||||
|
||||
#include "service-db/messages/DBMessage.hpp"
|
||||
#include "service-db/api/DBServiceAPI.hpp"
|
||||
|
||||
#include <log/log.hpp>
|
||||
|
||||
@@ -30,6 +29,8 @@
|
||||
#include <widgets/ListItemProvider.hpp>
|
||||
#include <widgets/ListView.hpp>
|
||||
|
||||
#include "service-db/api/DBServiceAPI.hpp"
|
||||
|
||||
namespace style
|
||||
{
|
||||
namespace window
|
||||
@@ -44,6 +45,7 @@ namespace style
|
||||
namespace gui
|
||||
{
|
||||
|
||||
|
||||
ThreadViewWindow::ThreadViewWindow(app::Application *app) : AppWindow(app, name::window::thread_view)
|
||||
{
|
||||
AppWindow::buildInterface();
|
||||
@@ -55,22 +57,57 @@ namespace gui
|
||||
bottomBar->setText(BottomBar::Side::LEFT, utils::localize.get("common_options"));
|
||||
bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get("common_send"));
|
||||
bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get("common_back"));
|
||||
|
||||
auto elements_width = this->getWidth() - style::window::default_left_margin * 2;
|
||||
body = new gui::VBox(this, style::window::default_left_margin, title->offset_h(), elements_width, bottomBar->getY() - title->offset_h());
|
||||
body->setPenWidth(style::window::default_border_no_focus_w);
|
||||
body->setPenFocusWidth(style::window::default_border_no_focus_w);
|
||||
body->borderCallback = [this](const InputEvent &inputEvent) -> bool {
|
||||
if (inputEvent.state != InputEvent::State::keyReleasedShort)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (inputEvent.keyCode == KeyCode::KEY_UP)
|
||||
{
|
||||
return this->showMessages(Action::Next);
|
||||
}
|
||||
else if (inputEvent.keyCode == KeyCode::KEY_DOWN)
|
||||
{
|
||||
return this->showMessages(Action::Previous);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// new text, TODO - send it and reload sms
|
||||
auto text = new gui::Text(nullptr, 0, 0, elements_width, style::window::sms_height, "", gui::Text::ExpandMode::EXPAND_UP);
|
||||
rebuildText();
|
||||
/// setup
|
||||
body->setReverseOrder(true);
|
||||
body->setVisible(true);
|
||||
setFocusItem(body);
|
||||
}
|
||||
|
||||
// TODO fix text and dont rebuild it...
|
||||
void ThreadViewWindow::rebuildText()
|
||||
{
|
||||
if (text)
|
||||
{
|
||||
body->removeWidget(text);
|
||||
}
|
||||
text = new gui::Text(nullptr, 0, 0, body->getWidth(), style::window::sms_height, "", gui::Text::ExpandMode::EXPAND_UP);
|
||||
text->setInputMode(new InputMode(
|
||||
{InputMode::ABC, InputMode::abc}, [=](const UTF8 &text) { textModeShowCB(text); }, [=]() { textSelectSpecialCB(); }));
|
||||
text->setPenFocusWidth(style::window::default_border_focucs_w);
|
||||
text->setPenWidth(style::window::default_border_focucs_w);
|
||||
text->setEdges(gui::RectangleEdgeFlags::GUI_RECT_EDGE_BOTTOM);
|
||||
// TODO IFS
|
||||
text->activatedCallback = [=](gui::Item &item) {
|
||||
LOG_INFO("Send SMS callback");
|
||||
|
||||
text->activatedCallback = [&](gui::Item &item) {
|
||||
if (text->getText().length() == 0)
|
||||
{
|
||||
LOG_DEBUG("No text to send in SMS");
|
||||
return true;
|
||||
}
|
||||
SMSRecord record;
|
||||
record.number = title->getText();
|
||||
record.body = text->getText();
|
||||
@@ -81,82 +118,171 @@ namespace gui
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
body->tryAddWidget(text);
|
||||
/// setup
|
||||
body->setReverseOrder(true);
|
||||
body->setVisible(true);
|
||||
setFocusItem(body);
|
||||
}
|
||||
|
||||
void ThreadViewWindow::cleanMessages()
|
||||
void ThreadViewWindow::cleanView()
|
||||
{
|
||||
// remove items from list and and set text to no navigation (text is all the time same widget)
|
||||
auto text = body->children.front();
|
||||
body->setFocusItem(text);
|
||||
text->setNavigationItem(NavigationDirection::UP, nullptr);
|
||||
text->setNavigationItem(NavigationDirection::DOWN, nullptr);
|
||||
if (body->children.size() > 1)
|
||||
body->removeWidget(text);
|
||||
body->setFocusItem(nullptr);
|
||||
std::for_each(body->children.begin(), body->children.end(), [&](auto &el) { delete el; });
|
||||
body->children.erase(body->children.begin(), body->children.end());
|
||||
}
|
||||
|
||||
bool ThreadViewWindow::showMessages(ThreadViewWindow::Action what)
|
||||
{
|
||||
if (SMS.thread <= 0)
|
||||
{
|
||||
std::for_each(std::next(body->children.begin(), 1), body->children.end(), [&](auto &el) { delete el; });
|
||||
body->children.erase(std::next(body->children.begin()), body->children.end());
|
||||
LOG_ERROR("threadID not set!");
|
||||
return false;
|
||||
}
|
||||
addSMS(what);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ThreadViewWindow::addMessages(uint32_t thread_id)
|
||||
// TODO TODO TODO
|
||||
// ez - najpierw wylicz ile sie zmieści - potem wstaw
|
||||
void ThreadViewWindow::addSMS(ThreadViewWindow::Action what)
|
||||
{
|
||||
auto elements_width = this->getWidth() - style::window::default_left_margin * 2;
|
||||
LOG_INFO("=============================");
|
||||
std::unique_ptr<std::vector<SMSRecord>> sms = DBServiceAPI::SMSGetLimitOffsetByThreadID(application, 0, 4, thread_id);
|
||||
LOG_INFO("=============================");
|
||||
/// dummy sms thread - TODO TODO load from db - on switchData
|
||||
/// this is not 'static' do it on window focus (on swtich window)
|
||||
auto labelmeta = gui::meta::Label({0, 0, elements_width, style::window::sms_height});
|
||||
labelmeta.edges = RectangleEdgeFlags::GUI_RECT_ALL_EDGES;
|
||||
labelmeta.radius = style::window::sms_radius;
|
||||
labelmeta.align = gui::Alignment::ALIGN_VERTICAL_TOP;
|
||||
labelmeta.focus = style::window::default_border_focucs_w;
|
||||
labelmeta.no_focus = style::window::sms_border_no_focus;
|
||||
labelmeta.margins = Margins(0, 2, 0, 2);
|
||||
// hack - tmp to fix fitting
|
||||
body->setReverseOrder(false);
|
||||
for (auto &el : *sms)
|
||||
LOG_DEBUG("--- %d ---", what);
|
||||
// if there was text - then remove it temp
|
||||
gui::Alignment align;
|
||||
// 1. load elements to tmp vector
|
||||
SMS.dbsize = DBServiceAPI::SMSGetCount(this->application);
|
||||
LOG_DEBUG("start: %d end: %d db: %d", SMS.start, SMS.end, SMS.dbsize);
|
||||
if (what == Action::Start)
|
||||
{
|
||||
auto label = new gui::Label(nullptr, labelmeta);
|
||||
label->setText(el.body);
|
||||
label->activatedCallback = [=](Item &) {
|
||||
LOG_INFO("Message activated!");
|
||||
auto app = dynamic_cast<app::ApplicationMessages *>(application);
|
||||
if (app == nullptr)
|
||||
{
|
||||
LOG_ERROR("Something went horribly wrong");
|
||||
return false;
|
||||
}
|
||||
if (app->windowOptions != nullptr)
|
||||
{
|
||||
app->windowOptions->clearOptions();
|
||||
/// TODO get record properly...
|
||||
app->windowOptions->addOptions(smsWindowOptions(app, el));
|
||||
app->switchWindow(app->windowOptions->getName(), nullptr);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
LOG_INFO("Add sms: %s %s", el.body.c_str(), el.number.c_str());
|
||||
if (body->tryAddWidget(label)) {}
|
||||
SMS.start = 0;
|
||||
SMS.end = maxsmsinwindow;
|
||||
rebuildText();
|
||||
}
|
||||
|
||||
// TODO 2. check how many of these will fit in box
|
||||
// update begin / end in `SMS`
|
||||
if (what == Action::Next)
|
||||
{
|
||||
if (SMS.end != SMS.dbsize)
|
||||
{
|
||||
SMS.start = SMS.end;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete label;
|
||||
break;
|
||||
LOG_INFO("All sms shown");
|
||||
return;
|
||||
}
|
||||
}
|
||||
body->setReverseOrder(true);
|
||||
else if (what == Action::Previous)
|
||||
{
|
||||
if (SMS.start == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (SMS.start - maxsmsinwindow < 0)
|
||||
{
|
||||
SMS.start = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
SMS.start -= maxsmsinwindow;
|
||||
}
|
||||
// TODO show text field here!
|
||||
LOG_DEBUG("---> In progress %d", SMS.start);
|
||||
}
|
||||
SMS.sms = DBServiceAPI::SMSGetLimitOffsetByThreadID(this->application, SMS.start, maxsmsinwindow, SMS.thread);
|
||||
LOG_DEBUG("=> SMS %d < %d < %d", SMS.start, SMS.sms->size(), maxsmsinwindow);
|
||||
// 3. add them to box
|
||||
this->cleanView();
|
||||
// if we are going from 0 then we want to show text prompt
|
||||
if (SMS.start == 0)
|
||||
{
|
||||
body->addWidget(text);
|
||||
}
|
||||
|
||||
SMS.end = SMS.start;
|
||||
for (auto &el : *SMS.sms)
|
||||
{
|
||||
LOG_DEBUG("...");
|
||||
if (!smsBuild(el, false))
|
||||
{
|
||||
break;
|
||||
}
|
||||
++SMS.end;
|
||||
}
|
||||
body->setNavigation();
|
||||
setFocusItem(body);
|
||||
if (Action::Previous == what)
|
||||
{
|
||||
body->setVisible(true, true);
|
||||
}
|
||||
LOG_DEBUG("-------------");
|
||||
}
|
||||
|
||||
bool ThreadViewWindow::smsBuild(const SMSRecord &el, bool bottom)
|
||||
{
|
||||
/// dummy sms thread - TODO TODO load from db - on switchData
|
||||
/// this is not 'static' do it on window focus (on swtich window)
|
||||
// auto label = new gui::Label(nullptr, labelmeta);
|
||||
auto label = new Text(nullptr, 0, 1, 300, 5);
|
||||
label->setTextType(Text::TextType::MULTI_LINE);
|
||||
label->setEditMode(Text::EditMode::SCROLL);
|
||||
label->setEdges(RectangleEdgeFlags::GUI_RECT_ALL_EDGES);
|
||||
label->setRadius(5);
|
||||
label->setFont(style::window::font::medium);
|
||||
label->setPenFocusWidth(style::window::default_border_focucs_w);
|
||||
label->setPenWidth(style::window::sms_border_no_focus);
|
||||
label->expandMode = Text::ExpandMode::EXPAND_DOWN;
|
||||
label->buildDrawList();
|
||||
label->setText(el.body.length() ? el.body : " "); // text doesn't really like being empty
|
||||
// TODO move to other decorating function depending on what happens (bind left, right, add dashdot etc)
|
||||
LOG_DEBUG("ADD SMS TYPE: %d", el.type);
|
||||
switch (el.type)
|
||||
{
|
||||
case SMSType::OUTBOX:
|
||||
default:
|
||||
label->setMargins(gui::Margins(10, 10, 10, 10));
|
||||
}
|
||||
label->activatedCallback = [=](Item &) {
|
||||
LOG_INFO("Message activated!");
|
||||
auto app = dynamic_cast<app::ApplicationMessages *>(application);
|
||||
if (app == nullptr)
|
||||
{
|
||||
LOG_ERROR("Something went horribly wrong");
|
||||
return false;
|
||||
}
|
||||
if (app->windowOptions != nullptr)
|
||||
{
|
||||
app->windowOptions->clearOptions();
|
||||
app->windowOptions->addOptions(smsWindowOptions(app, el));
|
||||
app->switchWindow(app->windowOptions->getName(), nullptr);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
auto rect = new gui::Rect(nullptr, 0, 0, 10, 10);
|
||||
rect->activeItem = false;
|
||||
rect->setPenWidth(0);
|
||||
if (!body->addWidget(rect))
|
||||
{
|
||||
delete rect;
|
||||
delete label;
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_INFO("Add sms: %s %s", el.body.c_str(), el.number.c_str());
|
||||
if (body->addWidget(label))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete label;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadViewWindow::rebuild()
|
||||
{
|
||||
destroyInterface();
|
||||
buildInterface();
|
||||
addSMS(ThreadViewWindow::Action::Start);
|
||||
// destroyInterface();
|
||||
// buildInterface();
|
||||
}
|
||||
|
||||
void ThreadViewWindow::buildInterface()
|
||||
@@ -181,8 +307,9 @@ namespace gui
|
||||
if (pdata)
|
||||
{
|
||||
LOG_INFO("We have it! %d", pdata->thread->dbID);
|
||||
cleanMessages();
|
||||
addMessages(pdata->thread->dbID);
|
||||
cleanView();
|
||||
SMS.thread = pdata->thread->dbID;
|
||||
showMessages(Action::Start);
|
||||
auto ret = DBServiceAPI::ContactGetByID(application, pdata->thread->contactID);
|
||||
// should be name number for now - easier to handle
|
||||
setTitle(ret->front().number);
|
||||
|
||||
Reference in New Issue
Block a user