#define NO_SPAM_MSG_ICON "No_item/msg_no_spam_messages.png"
-#define TEST_IMAGE_PATH "images/cat.png"
-
#define NEW_MSG_MORE_ICON MORE_OPTION_DIR"/b_more_option_ic_compose.png"
#define DELETEG_MORE_ICON MORE_OPTION_DIR"/b_more_option_ic_delete.png"
#define ADD_TO_SPAM_MORE_ICON MORE_OPTION_DIR"/b_more_option_ic_add_to_spam.png"
virtual void onEmoticonReply(const std::string &emoticon) {};
virtual void onTerminate() {};
- void clear();
+ void terminateHandler();
private:
void onReply(app_control_h request, app_control_h reply, app_control_result_e result) override;
+ void clear();
private:
IInputSelectorListener *m_pListener;
char **pArrayVal = nullptr;
if (APP_CONTROL_ERROR_NONE == app_control_get_extra_data_array(handle, key.c_str(), &pArrayVal, &arrayLength)) {
for (int i = 0; i < arrayLength; ++i) {
- res.push_back(pArrayVal[i]);
- free(pArrayVal[i]);
+ if (pArrayVal[i]) {
+ res.push_back(pArrayVal[i]);
+ free(pArrayVal[i]);
+ }
}
free(pArrayVal);
}
: m_pListener(nullptr)
{
setOperation(APP_CONTROL_OPERATION_GET_INPUT);
+ addExtraData("return_key_type", "DONE");
}
InputSelector::~InputSelector()
removeExtraData(APP_CONTROL_DATA_INPUT_DEFAULT_TEXT);
}
+void InputSelector::terminateHandler()
+{
+ onTerminate();
+ if (m_pListener)
+ m_pListener->onTerminate(*this);
+ clear();
+}
+
bool InputSelector::launch(InputType type)
{
terminate();
onVoiceReply(text, fileList);
} if (replyType == "template") {
onTemplateReply(text);
- } else {
- onTerminate();
- if (m_pListener)
- m_pListener->onTerminate(*this);
- clear();
}
}
+ terminateHandler();
}
{
contacts_filter_h filter = nullptr;
contacts_filter_create(_contacts_person_phone_log._uri, &filter);
- contacts_filter_add_str(filter, _contacts_person_email.email, CONTACTS_MATCH_FULLSTRING, address.c_str());
+ contacts_filter_add_str(filter, _contacts_person_phone_log.address, CONTACTS_MATCH_FULLSTRING, address.c_str());
return filter ? getContactPersonPhoneLog(filter) : nullptr;
}
void App::exit()
{
+ MSG_LOG("");
+
if (m_IsTerminating)
return;
void NaviFrameController::pop(FrameController &frame)
{
+ if (frame.isPopping())
+ return;
+
+ MSG_LOG("Is Last frame: ", isLastFrame());
+ MSG_LOG("PopupManager isEmpty: ", App::getInst().getPopupManager().isEmpty());
+
if (isLastFrame() && App::getInst().getPopupManager().isEmpty())
App::getInst().exit();
else {
void NaviFrameController::popGroup(FrameController::GroupType type)
{
auto items = getItems();
- for (NaviFrameItem * item: items) {
+ for (NaviFrameItem *item: items) {
auto *frame = dynamic_cast<FrameController*>(item);
- if (frame && frame->getGroupType() == type)
+ if (frame && frame->getGroupType() == type) {
pop(*frame);
+ }
}
}
{
textMetric.reset();
- static const int maxGsm7Len = 160;
- static const int maxUnicodeLen = 70;
- const int maxMmsLen = m_Engine.getSettings().getMaxMmsSize(); // In bytes
- int maxSmsLen = maxGsm7Len; // In chars
+ static const unsigned maxGsm7Len = 160;
+ static const unsigned maxUnicodeLen = 70;
+ const unsigned maxMmsLen = m_Engine.getSettings().getMaxMmsSize(); // In bytes
+ unsigned maxSmsLen = maxGsm7Len; // In chars
msg_encode_type_t encode = MSG_ENCODE_GSM7BIT;
unsigned textLen = 0;
msg_release_struct(&req);
MsgTransport::SendResult sendRes = MsgUtilsPrivate::nativeToSendResult(err);
+ MSG_LOG("Send raw result: ", err);
MSG_LOG("Send result: ", sendRes);
return sendRes;
}
#include "LangUtils.h"
#include "Callback.h"
#include <Elementary.h>
+#include <app.h>
#include <efl_extension.h>
namespace Msg
#include "WorkingDir.h"
#include "AppControlCompose.h"
#include "ConnectivityChecker.h"
+#include "SendingOptionsFrame.h"
#include "View.h"
#include <set>
class Popup;
class Composer
- : private IMsgTransportListener {
+ : private IMsgTransportListener
+ , private ISendingOptionsFrameListener {
public:
Composer();
const Recipient &getRecip() const;
void setText(std::string text);
bool addFile(const std::string &file);
- ThreadId send();
+ void send();
ThreadId getThreadId() const;
void reset();
void clear();
// IMsgTransportListener:
void onMsgTransportSentStatus(const MsgSentStatus &status) override;
- bool checkBeforeSend(Message::Type type);
+ // ISendingOptionsFrameListener:
+ void onSendAsText(SendingOptionsFrame &sender) override;
+ void onSendAsAudio(SendingOptionsFrame &sender) override;
+ void onDestroy(SendingOptionsFrame &sender) override;
+
+ bool checkConnectivity(Message::Type type);
+ bool checkSendingOptions();
std::vector<MessageRef> createMessage();
void requestSendMessage();
void sendMessage();
- bool readAddress(MessageRef msg);
+ bool readAddress(Message &msg);
void handleSendResult(MsgTransport::SendResult result);
+ void destroySendingPopup(bool anim = true);
+ void navigateToSendingOptions();
void setText(MessageRef msg, const std::string &text);
void setText(MessageSMS &msg, const std::string &text);
void setText(MessageMms &msg, const std::string &text);
+ void addFile(MessageMms &msg, const std::string &filePath);
+ void removeAudioFiles();
+
+ void notifyOnSendStart();
+ void notifyOnSendFinished();
+ void notifyOnCloseSendPopup();
// Popup:
void showMaxCharactersPopup();
class IComposerListener {
public:
virtual ~IComposerListener() {}
- virtual void onSendFinished(Composer &composer, Message::NetworkStatus status) {};
+ virtual void onSendStart(Composer &composer) {};
+ virtual void onSendFinished(Composer &composer) {};
virtual void onCloseSendPopup(Composer &composer) {};
};
}
protected:
void onTemplateReply(const std::string &text) override;
void onKeyboardReply(const std::string &text) override;
- void onVoiceReply(const std::string &text, const std::list<std::string> &filePath) override;
+ void onVoiceReply(const std::string &text, const std::list<std::string> &fileList) override;
void onEmoticonReply(const std::string &emoticon) override;
private:
void showMsgBody(const std::string &text);
void navigateToConv(ThreadId threadId);
void send();
+ void addDummyAudio();
// IComposerListener:
- void onSendFinished(Composer &composer, Message::NetworkStatus status) override;
+ void onSendStart(Composer &composer) override;
+ void onSendFinished(Composer &composer) override;
void onCloseSendPopup(Composer &composer) override;
// IMsgBodyFrameListener:
class SendingOptionListViewItem;
class AlwaysSendAsTextListViewItem;
+ class ISendingOptionsFrameListener;
class SendingOptionsFrame
: public FrameController
SendingOptionsFrame(NaviFrameController &parent);
virtual ~SendingOptionsFrame();
+ void setListener(ISendingOptionsFrameListener *l);
+
private:
// NaviFrameItem:
void onAttached(ViewItem &item) override;
private:
void preapareList();
void fillList();
+ void alwaysSendTextHandler(bool value);
private:
ListView *m_pList;
SendingOptionListViewItem *m_pSendingOptionItem;
AlwaysSendAsTextListViewItem *m_pSendAsTextItem;
+ ISendingOptionsFrameListener *m_pListener;
+ };
+
+ class ISendingOptionsFrameListener {
+ public:
+ virtual ~ISendingOptionsFrameListener() {}
+ virtual void onSendAsText(SendingOptionsFrame &sender) {};
+ virtual void onSendAsAudio(SendingOptionsFrame &sender) {};
+ virtual void onDestroy(SendingOptionsFrame &sender) {};
};
}
#include "IconTextPopup.h"
#include "ToastPopup.h"
#include "NaviFrameController.h"
+#include "MediaType.h"
+#include "SendingOptionsFrame.h"
+#include "MediaUtils.h"
using namespace Msg;
Composer::~Composer()
{
MSG_LOG("");
- if (m_pSendingPopup)
- m_pSendingPopup->destroy();
+ destroySendingPopup(false);
App::getInst().getMsgEngine().getTransport().removeListener(*this);
}
return isValid;
}
-ThreadId Composer::send()
+void Composer::addFile(MessageMms &msg, const std::string &filePath)
+{
+ constexpr int defaultPageDuration = 5000; // msec
+ if (!filePath.empty()) {
+ MsgPage &msgPage = msg.addPage();
+ MediaTypeData mediaData = getMsgMediaTypeByFileExt(filePath);
+ int pageDuration = 0;
+
+ if (mediaData.type == MsgMedia::VideoType || mediaData.type == MsgMedia::AudioType)
+ pageDuration = MediaUtils::getDuration(filePath);
+
+ if (pageDuration <= 0)
+ pageDuration = defaultPageDuration;
+
+ msgPage.setPageDuration(pageDuration);
+ MsgMedia &media = msgPage.addMedia();
+ media.setFilePath(filePath);
+ }
+}
+
+void Composer::removeAudioFiles()
+{
+ decltype(m_Files) newFileList;
+ for (std::string &file : m_Files) {
+ if (getMsgMediaTypeByFileExt(file).type != MsgMedia::AudioType)
+ newFileList.push_back(std::move(file));
+ }
+ m_Files = std::move(newFileList);
+}
+
+void Composer::send()
{
reset();
requestSendMessage();
- return getThreadId();
}
ThreadId Composer::getThreadId() const
m_Files.clear();
}
-bool Composer::readAddress(MessageRef msg)
+bool Composer::readAddress(Message &msg)
{
- if(m_Recip.isValid() && msg) {
- MsgAddress &msgAddr = msg->addAddress();
+ if(m_Recip.isValid()) {
+ MsgAddress &msgAddr = msg.addAddress();
msgAddr.setAddress(m_Recip.getAddress());
msgAddr.setRecipientType(MsgAddress::To);
msgAddr.setAddressType(MsgAddress::Phone);
}
}
-bool Composer::checkBeforeSend(Message::Type type)
+bool Composer::checkConnectivity(Message::Type type)
{
auto &checker = App::getInst().getNavigation().getConnectivityChecker();
return MsgUtils::isMms(type) ? checker.isReadyToSendMms()
: checker.isReadyToSendSms();
}
-std::vector<MessageRef> Composer::createMessage()
+void Composer::navigateToSendingOptions()
{
- auto &msgEngine = App::getInst().getMsgEngine();
+ auto &navi = App::getInst().getNavigation();
+ auto *frame = new SendingOptionsFrame(navi);
+ frame->setListener(this);
+ navi.push(*frame);
+}
+bool Composer::checkSendingOptions()
+{
+ if (!App::getInst().getMsgEngine().getSettings().getSendAsAudio() ||
+ m_Files.empty())
+ return true;
+
+ bool onlyAudio = true;
+ for (const std::string &file : m_Files) {
+ onlyAudio &= getMsgMediaTypeByFileExt(file).type == MsgMedia::AudioType;
+ if (!onlyAudio)
+ break;
+ }
+
+ if (onlyAudio) {
+ navigateToSendingOptions();
+ return false;
+ }
+ return true;
+}
+
+std::vector<MessageRef> Composer::createMessage()
+{
std::vector<MessageRef> msgList;
+ auto &msgEngine = App::getInst().getMsgEngine();
const int maxMsgSize = msgEngine.getSettings().getMaxMmsSize();
if (maxMsgSize <= 0) {
return {};
}
- auto textList = MsgUtils::splitUtf8String(m_Text, maxMsgSize);
-
- for (auto &&text : textList) {
- MsgTextMetric metric;
- msgEngine.getComposer().calculateTextMetric(m_Text, metric);
- Message::Type type = metric.isMms ? Message::MT_MMS : Message::MT_SMS;
- auto msg = msgEngine.getComposer().createMessage(type);
- if (readAddress(msg)) {
- setText(msg, text);
- msgList.push_back(msg);
+ if (m_Files.empty()) {
+ // Text messages:
+ auto textList = MsgUtils::splitUtf8String(m_Text, maxMsgSize);
+ for (auto &&text : textList) {
+ MsgTextMetric metric;
+ msgEngine.getComposer().calculateTextMetric(m_Text, metric);
+ Message::Type type = metric.isMms ? Message::MT_MMS : Message::MT_SMS;
+ auto msg = msgEngine.getComposer().createMessage(type);
+ if (msg && readAddress(*msg)) {
+ setText(msg, text);
+ msgList.push_back(msg);
+ }
+ }
+ } else {
+ // Create MMS:
+ auto mms = msgEngine.getComposer().createMms();
+ if (mms) {
+ if (readAddress(*mms)) {
+ for (const std::string &file : m_Files)
+ addFile(*mms, file);
+ msgList.push_back(mms);
+ }
}
}
-
return msgList;
}
void Composer::requestSendMessage()
{
m_SendInfo.reset();
+ destroySendingPopup(false);
- m_SendInfo.msgs = createMessage();
- if (m_SendInfo.msgs.empty())
- return;
-
- if (!checkBeforeSend(m_SendInfo.msgs [0]->getType()))
+ if (!checkSendingOptions())
return;
+ removeAudioFiles();
sendMessage();
}
void Composer::sendMessage()
{
+ MSG_LOG("");
+ // Create message:
+ m_SendInfo.msgs = createMessage();
+ if (m_SendInfo.msgs.empty())
+ return;
+
+ MSG_LOG("");
+ // Check connectivity:
+ if (!checkConnectivity(m_SendInfo.msgs[0]->getType()))
+ return;
+
+ // Send process:
MsgTransport::SendResult sendRes = MsgTransport::SendFail;
MessageRef lastSentMsg;
sendRes = App::getInst().getMsgEngine().getTransport().sendMessage(msg, &m_SendInfo.threadId, &reqId);
MSG_LOG("Send result = ", sendRes);
+ MSG_LOG("Thread id = ", m_SendInfo.threadId);
MSG_LOG("Request id = ", reqId);
if (sendRes != MsgTransport::SendSuccess)
if (sendRes == MsgTransport::SendSuccess && m_SendInfo.threadId.isValid()) {
showSendingProgressPopup();
+ notifyOnSendStart();
} else {
+ notifyOnSendStart();
handleSendResult(sendRes);
}
}
-void Composer::handleSendResult( MsgTransport::SendResult result)
+void Composer::notifyOnSendStart()
+{
+ if (m_pListener)
+ m_pListener->onSendStart(*this);
+}
+
+void Composer::notifyOnSendFinished()
+{
+ if (m_pListener)
+ m_pListener->onSendFinished(*this);
+}
+
+void Composer::notifyOnCloseSendPopup()
+{
+ if (m_pListener)
+ m_pListener->onCloseSendPopup(*this);
+}
+
+void Composer::handleSendResult(MsgTransport::SendResult result)
+{
+ notifyOnSendFinished();
+}
+
+void Composer::destroySendingPopup(bool anim)
{
- // TODO: impl.
+ if (m_pSendingPopup) {
+ m_pSendingPopup->destroy(anim);
+ m_pSendingPopup = nullptr;
+ }
}
void Composer::showMaxCharactersPopup()
m_pSendingPopup->setText(msgt("WDS_MSG_TPOP_SENDING_FAILED_ABB"));
m_pSendingPopup->setTimeOut();
} else if (m_SendInfo.status != Message::NS_Send_Pending) {
- m_pSendingPopup->destroy();
+ destroySendingPopup();
showSentWhenServiceBecomesAvailablePopup();
}
- if (m_pListener)
- m_pListener->onSendFinished(*this, m_SendInfo.status);
+ notifyOnSendFinished();
}
}
{
MSG_LOG("");
m_pSendingPopup = nullptr;
- if (m_pListener)
- m_pListener->onCloseSendPopup(*this);
+ notifyOnCloseSendPopup();
}
void Composer::onSendingPopupBackButtonPressed(Evas_Object *obj, void *event_info)
{
MSG_LOG("");
- if (m_pSendingPopup)
- m_pSendingPopup->destroy();
-
+ destroySendingPopup();
if (m_SendInfo.inProgress)
m_SendInfo.reset();
}
MSG_LOG("");
popup.destroy();
}
+
+void Composer::onSendAsText(SendingOptionsFrame &sender)
+{
+ MSG_LOG("");
+ removeAudioFiles();
+ sendMessage();
+}
+
+void Composer::onSendAsAudio(SendingOptionsFrame &sender)
+{
+ MSG_LOG("");
+ m_Text.clear();
+ sendMessage();
+}
+
+void Composer::onDestroy(SendingOptionsFrame &sender)
+{
+ MSG_LOG("");
+}
#include "ConvFrame.h"
#include "App.h"
#include "Logger.h"
+#include "PathUtils.h"
using namespace Msg;
void MsgInputSelector::send()
{
- ThreadId id = m_Composer.send();
- if (id.isValid()) {
- if (m_CloseAfterSent)
- getNavigation().popGroup(FrameController::ComposerGroup);
- else
- navigateToConv(id);
+ m_Composer.send();
+}
+
+void MsgInputSelector::addDummyAudio()
+{
+ std::string file = PathUtils::getResourcePath("dummy_res/1.mp3");
+ m_Composer.addFile(file);
+}
+
+void MsgInputSelector::onSendStart(Composer &composer)
+{
+ MSG_LOG("");
+ ThreadId id = composer.getThreadId();
+
+ if (m_CloseAfterSent || !id.isValid()) {
+ getNavigation().popGroup(FrameController::ComposerGroup);
+ } else {
+ navigateToConv(id);
}
}
-void MsgInputSelector::onSendFinished(Composer &composer, Message::NetworkStatus status)
+void MsgInputSelector::onSendFinished(Composer &composer)
{
MSG_LOG("");
}
{
MSG_LOG("");
m_Composer.setText(emoticon);
+ // addDummyAudio(); // Only for test will be removed
send();
}
-void MsgInputSelector::onVoiceReply(const std::string &text, const std::list<std::string> &filePath)
+void MsgInputSelector::onVoiceReply(const std::string &text, const std::list<std::string> &fileList)
{
MSG_LOG("");
m_Composer.setText(text);
+ for (const std::string &file : fileList) {
+ m_Composer.addFile(file);
+ }
send();
}
#include "LangUtils.h"
#include "App.h"
#include "NaviFrameController.h"
+#include "App.h"
+#include "MsgEngine.h"
#include <functional>
, m_pList(nullptr)
, m_pSendingOptionItem(nullptr)
, m_pSendAsTextItem(nullptr)
+ , m_pListener(nullptr)
{
preapareList();
}
SendingOptionsFrame::~SendingOptionsFrame()
{
+ if (m_pListener)
+ m_pListener->onDestroy(*this);
+}
+
+void SendingOptionsFrame::setListener(ISendingOptionsFrameListener *l)
+{
+ m_pListener = l;
}
void SendingOptionsFrame::preapareList()
m_pList->appendItem(*m_pSendingOptionItem);
m_pSendAsTextItem = new AlwaysSendAsTextListViewItem;
+ m_pSendAsTextItem->setCheckedState(!App::getInst().getMsgEngine().getSettings().getSendAsAudio());
m_pSendAsTextItem->setOnSelectedCb(std::bind(&SendingOptionsFrame::onSendAsTextItemSelected, this, _1));
m_pSendAsTextItem->setOnChangedCb(std::bind(&SendingOptionsFrame::onCheckItemClicked, this, _1));
m_pList->appendItem(*m_pSendAsTextItem);
m_pList->appendItem(*new PaddingListViewItem);
}
+void SendingOptionsFrame::alwaysSendTextHandler(bool value)
+{
+ App::getInst().getMsgEngine().getSettings().setSendAsAudio(!value);
+
+ if (m_pListener) {
+ bool sendAsAudio = App::getInst().getMsgEngine().getSettings().getSendAsAudio();
+ sendAsAudio ? m_pListener->onSendAsAudio(*this) : m_pListener->onSendAsText(*this);
+ }
+ pop();
+}
+
void SendingOptionsFrame::onAttached(ViewItem &item)
{
MSG_LOG("");
void SendingOptionsFrame::onTextButtonClicked()
{
MSG_LOG("");
+ if (m_pListener)
+ m_pListener->onSendAsText(*this);
+ pop();
}
void SendingOptionsFrame::onAudioButtonClicked()
{
MSG_LOG("");
+ if (m_pListener)
+ m_pListener->onSendAsAudio(*this);
+ pop();
}
void SendingOptionsFrame::onSendAsTextItemSelected(ListItem &item)
auto &textItem = static_cast<AlwaysSendAsTextListViewItem&>(item);
textItem.changeCheckedState();
bool newState = textItem.getCheckedState();
+ alwaysSendTextHandler(newState);
}
void SendingOptionsFrame::onCheckItemClicked(AlwaysSendAsTextListViewItem &item)
{
MSG_LOG("");
bool newState = item.getCheckedState();
+ alwaysSendTextHandler(newState);
}