#include "Message.h"
#include "MessageMms.h"
#include "MessageSMS.h"
+#include "MsgReport.h"
namespace Msg
{
*/
enum SendResult
{
- SendSuccess = 0, /**< Sending successful.*/
- SendFail = -1, /**< Sending failure.*/
- SendNullPointer = -2, /**< Invalid parameter passed into sendMessage().*/
- SendNoSIM = -3, /**< No SIM was found.*/
- SendMemoryFull = -4, /**< No free space available for message-storage.*/
- SendDPMRestricted = -5, /**< Sending message is restricted by DPM.*/
+ SendSuccess = 0, /**< Sending successful.*/
+ SendFail = -1, /**< Sending failure.*/
+ SendNoSIM = -2, /**< No SIM was found.*/
+ SendDPMRestricted = -3, /**< Sending message is restricted by DPM.*/
+ SendReadReportNotReq = -4, /**< Read report not requested.*/
+ SendReadReportAlreadySent = -5, /**< Read report already dent.*/
};
public:
* @brief Manually downloads MMS by demand.
* @param[in] msgId id of message to be downloaded.
*/
- virtual void retrieveMessage(MsgId msgId) = 0;
+ virtual SendResult retrieveMessage(MsgId msgId) = 0;
+
+ /**
+ * @brief Send read report (for MMS only)
+ * @param[in] msgId id of message (MMS)
+ */
+ virtual SendResult sendReadReport(MsgId msgId, MsgReport::ReadStatus status) = 0;
};
}
MsgTransport::SendResult MsgTransport::sendMessage(MessageRef &msg, ThreadId *threadId)
{
- return msg ? sendMessage(*msg, threadId) : MsgTransport::SendNullPointer;
+ return msg ? sendMessage(*msg, threadId) : MsgTransport::SendFail;
}
MsgTransport::SendResult MsgTransport::sendMessage(MessageMmsRef &msg, ThreadId *threadId)
{
- return msg ? sendMessage(*msg, threadId) : MsgTransport::SendNullPointer;
+ return msg ? sendMessage(*msg, threadId) : MsgTransport::SendFail;
}
MsgTransport::SendResult MsgTransport::sendMessage(MessageSMSRef &msg, ThreadId *threadId)
{
- return msg ? sendMessage(*msg, threadId) : MsgTransport::SendNullPointer;
+ return msg ? sendMessage(*msg, threadId) : MsgTransport::SendFail;
}
#include "MsgTransportPrivate.h"
#include "MessagePrivate.h"
+#include "MsgUtilsPrivate.h"
#include "Logger.h"
using namespace Msg;
+
MsgTransportPrivate::MsgTransportPrivate(msg_handle_t serviceHandle)
: MsgTransport()
, m_ServiceHandle(serviceHandle)
msg_get_thread_id_by_address2(m_ServiceHandle, privMsg.getAddressList(), (msg_thread_id_t*)threadId);
msg_release_struct(&req);
- if(err == MSG_SUCCESS)
- {
- MSG_LOG("sending success");
- return SendSuccess;
- }
- else if (err == MSG_ERR_INVALID_PARAMETER)
- {
- MSG_LOG_ERROR("sending failed error code INVALID_PARAM: ", err);
- return SendNullPointer;
- }
- else if (err == MSG_ERR_NO_SIM)
- {
- MSG_LOG_ERROR("sending failed error code NO SIM: ", err);
- return SendNoSIM;
- }
- else if (err == MSG_ERR_PLUGIN_STORAGE)
- {
- MSG_LOG_ERROR("sending failed error code MSG_ERR_PLUGIN_STORAGE: ", err);
- return SendMemoryFull;
- }
- else if (err == MSG_ERR_DPM_RESTRICT)
- {
- MSG_LOG_ERROR("sending failed error code MSG_ERR_DPM_RESTRICT: ", err);
- return SendDPMRestricted;
- }
- else
- {
- MSG_LOG_ERROR("[DEBUG] sending failed error code: ", err);
- return SendFail;
- }
+ MsgTransport::SendResult sendRes= MsgUtilsPrivate::nativeToSendResult(err);
+ MSG_LOG("Send result: ", sendRes);
+ return sendRes;
}
-void MsgTransportPrivate::retrieveMessage(MsgId msgId)
+MsgTransport::SendResult MsgTransportPrivate::retrieveMessage(MsgId msgId)
{
msg_struct_t req = msg_create_struct(MSG_STRUCT_REQUEST_INFO);
msg_struct_t sendOpt = msg_create_struct(MSG_STRUCT_SENDOPT);
msg_release_struct(&retrieveMsg);
msg_release_struct(&sendOpt);
msg_release_struct(&req);
+
+ MsgTransport::SendResult sendRes= MsgUtilsPrivate::nativeToSendResult(err);
+ MSG_LOG("Send result: ", sendRes);
+ return sendRes;
+}
+
+MsgTransport::SendResult MsgTransportPrivate::sendReadReport(MsgId msgId, MsgReport::ReadStatus status)
+{
+ msg_error_t err = msg_mms_send_read_report(m_ServiceHandle, msgId, MsgUtilsPrivate::reportReadReportStatusToNative(status));
+ MsgTransport::SendResult sendRes= MsgUtilsPrivate::nativeToSendResult(err);
+ MSG_LOG("Send result: ", sendRes);
+ return sendRes;
}
virtual ~MsgTransportPrivate();
virtual SendResult sendMessage(Message &msg, ThreadId *threadId);
- virtual void retrieveMessage(MsgId msgId);
+ virtual SendResult retrieveMessage(MsgId msgId);
+ virtual SendResult sendReadReport(MsgId msgId, MsgReport::ReadStatus status);
private:
msg_handle_t m_ServiceHandle;
}
}
+int MsgUtilsPrivate::reportReadReportStatusToNative(MsgReport::ReadStatus status)
+{
+ switch(status)
+ {
+ case MsgReport::ReadStatusIsRead:
+ return MSG_READ_REPORT_IS_READ;
+
+ case MsgReport::ReadStatusIsDeleted:
+ return MSG_READ_REPORT_IS_DELETED;
+
+ case MsgReport::ReadStatusRejectByUser:
+ return MSG_READ_REPORT_REJECT_BY_USER;
+
+ default:
+ case MsgReport::ReadStatusNone:
+ return MSG_READ_REPORT_NONE;
+ }
+}
+
MsgReport::Type MsgUtilsPrivate::nativeToReportType(int type)
{
switch(type)
}
return 0;
}
+
+MsgTransport::SendResult MsgUtilsPrivate::nativeToSendResult(int sendRes)
+{
+ switch(sendRes)
+ {
+ case MSG_SUCCESS:
+ return MsgTransport::SendSuccess;
+ case MSG_ERR_NO_SIM:
+ return MsgTransport::SendNoSIM;
+ case MSG_ERR_DPM_RESTRICT:
+ return MsgTransport::SendDPMRestricted;
+ case MSG_ERR_READREPORT_NOT_REQUESTED:
+ return MsgTransport::SendReadReportNotReq;
+ case MSG_ERR_READREPORT_ALEADY_SENT:
+ return MsgTransport::SendReadReportAlreadySent;
+ default:
+ return MsgTransport::SendFail;
+ }
+}
#include "MsgReport.h"
#include "MsgUtils.h"
#include "MsgSettings.h"
+#include "MsgTransport.h"
#include <msg_storage.h>
#include <msg_types.h>
static MsgAddress::RecipientType nativeToRecipientType(int type);
static MsgReport::DeliveryStatus nativeToReportDeliveryStatus(int status);
static MsgReport::ReadStatus nativeToReportReadStatus(int status);
+ static int reportReadReportStatusToNative(MsgReport::ReadStatus status);
static MsgReport::Type nativeToReportType(int type);
static Message::Type nativeToMessageType(int type);
static MsgMedia::Type nativeToSmilType(int type);
static int smilTypeToNative(MsgMedia::Type type);
static Message::NetworkStatus nativeToNetworkStatus(int status);
static int activeNotifPolicyToNative(MsgSettings::ActiveNotifPolicy policy);
+ static MsgTransport::SendResult nativeToSendResult(int sendRes);
static std::string getStr(msg_struct_t msgStruct, int field, int maxStrLen);
static int setStr(msg_struct_t msgStruct, int field, const std::string &text);
std::vector<T*> ListView::getItems() const
{
std::vector<T*> list;
+ list.reserve(elm_genlist_items_count(getEo()));
Elm_Object_Item *elmItem = elm_genlist_first_item_get(getEo());
while(elmItem)
{
: public BubbleEntity
{
public:
- BubbleDownloadButtonEntity(Message::Direction direction);
+ BubbleDownloadButtonEntity();
virtual ~BubbleDownloadButtonEntity();
void disabled(bool status);
bool m_Disabled;
};
- inline BubbleDownloadButtonEntity::BubbleDownloadButtonEntity(Message::Direction direction)
- : BubbleEntity(DownloadButtonItem, direction)
+ inline BubbleDownloadButtonEntity::BubbleDownloadButtonEntity()
+ : BubbleEntity(DownloadButtonItem, Message::MD_Received)
, m_Disabled(false)
{
}
BubbleEntity *createEntity(const std::string &filePath, BubbleBgViewItem::BgType bgType, Message::Direction direction);
BubbleEntity *createEntity(const MsgConvMedia &msgMedia, BubbleBgViewItem::BgType bgType, Message::Direction direction);
BubbleTextEntity *createTextEntity(std::string text, BubbleBgViewItem::BgType bgType, Message::Direction direction);
- BubbleDownloadButtonEntity *createDownloadButtonEntity(Message::Direction direction);
+ BubbleDownloadButtonEntity *createDownloadButtonEntity();
private:
BubbleEntity *createEntity(const std::string &filePath, const std::string &fileName, std::string mime, BubbleBgViewItem::BgType bgType, Message::Direction direction);
*/
ComposeListItem &getComposeItem();
+ /**
+ * @brief Get conversation(ConvListItem type) items
+ * @return conversation items.
+ */
+ std::vector<ConvListItem*> getConvItems() const;
+
private:
typedef std::unordered_map<MsgId::Type, ConvListItem*> ConvListItemMap;
typedef std::unordered_set<std::string> DateLineItemSet;
void updateStatus();
void updateTime();
+ bool isNeededReadReport() const;
protected:
// ConvListViewItem:
private:
ConvListViewItem::ConvItemType getConvItemType(const MsgConversationItem &item);
void prepareBubble(const MsgConversationItem &item, const std::string &searchWord);
- BubbleTextEntity *createTextEntity(BubbleBgViewItem::BgType bgType, Message::Direction direction, const MsgConvMedia &media, std::string searchWord);
- BubbleTextEntity *createTextEntity(BubbleBgViewItem::BgType bgType, Message::Direction direction, std::string text, bool markup, std::string searchWord);
+ BubbleTextEntity *createTextEntity(BubbleBgViewItem::BgType bgType, const MsgConvMedia &media, std::string searchWord);
+ BubbleTextEntity *createTextEntity(BubbleBgViewItem::BgType bgType, std::string text, bool markup, std::string searchWord);
void addEntity(BubbleEntity *entity);
void updateEntityBgType(BubbleBgViewItem::BgType bgType);
BubbleBgViewItem::BgType getBubbleBgType(const MsgConversationItem &item);
WorkingDirRef m_WorkingDir;
MsgId m_MsgId;
bool m_IsDraft;
+ Message::Direction m_Direction;
Message::NetworkStatus m_NetworkStatus;
Message::Type m_Type;
time_t m_Time;
const ThumbId &m_ThumbId;
BubbleEntityFactory &m_BubbleEntityFactory;
bool m_IsRestrictedByDpm;
+ bool m_IsNeededReadReport;
};
class IConvListItemListener
return text.empty() ? nullptr : new BubbleTextEntity(bgType, direction, std::move(text));
}
-BubbleDownloadButtonEntity *BubbleEntityFactory::createDownloadButtonEntity(Message::Direction direction)
+BubbleDownloadButtonEntity *BubbleEntityFactory::createDownloadButtonEntity()
{
- return new BubbleDownloadButtonEntity(direction);
+ return new BubbleDownloadButtonEntity;
}
BubbleEntity *BubbleEntityFactory::createEntity(const std::string &filePath, const std::string &fileName, std::string mime, BubbleBgViewItem::BgType bgType, Message::Direction direction)
void ConvList::deleteSelectedItems()
{
- auto items = m_pList->getItems<ConvListItem>();
+ auto items = getConvItems();
MsgIdList messages;
for(ConvListItem *item : items)
{
int ConvList::getMessageCount() const
{
- auto items = m_pList->getItems<ConvListItem>();
+ auto items = getConvItems();
return (int)items.size();
}
int ConvList::getMessageCheckedCount() const
{
- auto items = m_pList->getItems<ConvListItem>();
+ auto items = getConvItems();
int count = 0;
for(ConvListItem *item : items)
{
bool ConvList::isAllListItemSelected() const
{
// Simple but not fast impl:
- auto items = m_pList->getItems<ConvListItem>();
+ auto items = getConvItems();
for(ConvListItem *item : items)
{
if(!item->getCheckedState())
return *m_pComposeItem;
}
+std::vector<ConvListItem*> ConvList::getConvItems() const
+{
+ return m_pList->getItems<ConvListItem>();
+}
+
void ConvList::onListItemLongPressed(ListItem &listItem)
{
ConvListItem *item = dynamic_cast<ConvListItem*>(&listItem);
void ConvList::onTimeFormatChanged()
{
MSG_LOG("");
- auto items = m_pList->getItems<ConvListItem>();
+ auto items = getConvItems();
for(ConvListItem *item : items)
{
item->updateTime();
MSG_LOG("");
// Update ConvListItem:
- auto convListItems = m_pList->getItems<ConvListItem>();
+ auto convListItems = getConvItems();
for(ConvListItem *item : convListItems)
{
item->updateTime();
, m_App(app)
, m_MsgId(item.getMsgId())
, m_IsDraft(item.isDraft())
+ , m_Direction(item.getDirection())
, m_NetworkStatus(item.getNetworkStatus())
, m_Type(item.getType())
, m_Time(item.getTime())
, m_ThumbId(thumbId)
, m_BubbleEntityFactory(bubbleEntityFactory)
, m_IsRestrictedByDpm(item.isRestrictedByDpm())
+ , m_IsNeededReadReport(false)
{
+ m_IsNeededReadReport = m_Direction == MsgUtils::isMms(m_Type) && Message::MD_Received && !item.isRead();
prepareBubble(item, searchWord);
}
m_TimeStr.clear();
}
+bool ConvListItem::isNeededReadReport() const
+{
+ return m_IsNeededReadReport && !m_IsRestrictedByDpm;
+}
+
ConvListViewItem::ConvItemType ConvListItem::getConvItemType(const MsgConversationItem &item)
{
ConvItemType type = ConvItemType::Sent;
return type;
}
-BubbleTextEntity *ConvListItem::createTextEntity(BubbleBgViewItem::BgType bgType, Message::Direction direction, const MsgConvMedia &media, std::string searchWord)
+BubbleTextEntity *ConvListItem::createTextEntity(BubbleBgViewItem::BgType bgType, const MsgConvMedia &media, std::string searchWord)
{
std::string filePath = media.getPath();
std::string text = FileUtils::readTextFile(filePath);
- BubbleTextEntity *entity = createTextEntity(bgType, direction, std::move(text), true, std::move(searchWord));
+ BubbleTextEntity *entity = createTextEntity(bgType, std::move(text), true, std::move(searchWord));
if(entity)
entity->setFilePath(std::move(filePath));
return entity;
}
-BubbleTextEntity *ConvListItem::createTextEntity(BubbleBgViewItem::BgType bgType, Message::Direction direction, std::string text, bool markup, std::string searchWord)
+BubbleTextEntity *ConvListItem::createTextEntity(BubbleBgViewItem::BgType bgType, std::string text, bool markup, std::string searchWord)
{
bool found = false;
std::string markupText = markup ? utf8ToMarkup(text) : std::move(text);
if(found)
showSearch();
- return m_BubbleEntityFactory.createTextEntity(std::move(resText), bgType, direction);
+ return m_BubbleEntityFactory.createTextEntity(std::move(resText), bgType, m_Direction);
}
BubbleDownloadButtonEntity *ConvListItem::findDownloadButton() const
void ConvListItem::prepareBubble(const MsgConversationItem &item, const std::string &searchWord)
{
BubbleBgViewItem::BgType bgType = getBubbleBgType(item);
- Message::Direction direction = item.getDirection();
if(m_IsRestrictedByDpm)
{
- addEntity(createTextEntity(BubbleBgViewItem::RestrictedStyle, direction, msg("IDS_MSG_BODY_COULDNT_RECEIVE_THIS_MESSAGE_THE_SECURITY_POLICY_PREVENTS_RECEIVING_MESSAGES"), false, ""));
+ addEntity(createTextEntity(BubbleBgViewItem::RestrictedStyle, msg("IDS_MSG_BODY_COULDNT_RECEIVE_THIS_MESSAGE_THE_SECURITY_POLICY_PREVENTS_RECEIVING_MESSAGES"), false, ""));
}
else if(!MsgUtils::isMms(m_Type))
{
- addEntity(createTextEntity(bgType, direction, item.getText(), true, searchWord));
+ addEntity(createTextEntity(bgType, item.getText(), true, searchWord));
}
else if(m_Type == Message::MT_MMS_Noti)
{
std::string text = MessageDetailContent::getMmsNotiConvListItemContent(m_App, m_MsgId);
- addEntity(createTextEntity(bgType, direction, std::move(text), false, searchWord));
- addEntity(m_BubbleEntityFactory.createDownloadButtonEntity(direction));
+ addEntity(createTextEntity(bgType, std::move(text), false, searchWord));
+ addEntity(m_BubbleEntityFactory.createDownloadButtonEntity());
updateDownloadButton();
}
else
std::string mime = media.getMime();
std::transform(mime.begin(), mime.end(), mime.begin(), ::tolower);
if(mime == "text/plain")
- addEntity(createTextEntity(bgType, direction, media, searchWord));
+ addEntity(createTextEntity(bgType, media, searchWord));
else if(mime != "application/smil")
- addEntity(m_BubbleEntityFactory.createEntity(media, bgType, direction));
+ addEntity(m_BubbleEntityFactory.createEntity(media, bgType, m_Direction));
}
}
}
#include "ContactManager.h"
#include "SystemSettingsManager.h"
#include "WorkingDir.h"
+#include "MsgReport.h"
#include <functional>
virtual void onContactListChanged();
// Popup callbacks:
+ void onSendReadReportPopupDel(Evas_Object *popup, void *eventInfo);
+ void onSendReadReportPopupButtonClicked(Popup &popup, int buttonId);
void onPopupDel(Evas_Object *popup, void *eventInfo);
void onRecipPopupDel(Evas_Object *popup, void *eventInfo);
void onMsgSendErrorButtonClicked(Popup &popup, int buttonId);
void setRecipEntryFocus();
void resetMsgThread();
void updateActiveNotifPolicy();
+ std::vector<MsgId> getMsgIdListForReadReport() const;
+ void showSendReadReportPopup();
void showMainPopup();
void showNoRecipPopup();
PopupList &createPopupList(const std::string &title);
void showSendDpmNotif(const MsgAddressList &addressList);
void showUnsavedRecipientPopup(const std::string &address);
void showSavedRecipientPopup(const std::string &title, int contactId, ContactAddress::OwnerType ownerType);
+ void sendReadReport(MsgReport::ReadStatus status);
+ bool sendReadReportIfNeeded();
void sendMessage(MsgId msgId);
void sendMessage();
bool checkBeforeSend(const Message &msg);
m_pRecipPanel->setListener(nullptr);
if(m_pContactsList)
m_pContactsList->setListener(nullptr);
+ if(m_pConvList)
+ m_pConvList->setListener(nullptr);
m_AttachPanel.setListener(nullptr);
if(m_NnotifyConvertMsgTypeIdler)
{
ecore_idler_del(m_NnotifyConvertMsgTypeIdler);
m_NnotifyConvertMsgTypeIdler = nullptr;
}
+ markAsRead();
}
void Conversation::execCmd(const AppControlComposeRef &cmd)
void Conversation::markAsRead()
{
- if(m_ThreadId.isValid())
+ // Warning thread and messages marks as read only for ConversationMode.
+ if(m_ThreadId.isValid() && m_Mode == ConversationMode)
getMsgEngine().getStorage().setReadStatus(m_ThreadId);
}
return true;
}
+std::vector<MsgId> Conversation::getMsgIdListForReadReport() const
+{
+ std::vector<MsgId> msgIds;
+ if(m_pConvList)
+ {
+ auto items = m_pConvList->getConvItems();
+ for(ConvListItem *item : items)
+ {
+ if(item->isNeededReadReport())
+ msgIds.push_back(item->getMsgId());
+ }
+ }
+
+ return msgIds;
+}
+
+bool Conversation::sendReadReportIfNeeded()
+{
+ if(getMsgEngine().getSettings().getMmsReadReport() &&
+ !getApp().getSysSettingsManager().isMessagingRestrictedByDpm())
+ {
+ auto msgIds = getMsgIdListForReadReport();
+ if(!msgIds.empty())
+ {
+ showSendReadReportPopup();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void Conversation::sendReadReport(MsgReport::ReadStatus status)
+{
+ auto ids = getMsgIdListForReadReport();
+ for(MsgId id : ids)
+ {
+ getMsgEngine().getTransport().sendReadReport(id, status);
+ }
+}
+
void Conversation::sendMessage(MsgId msgId)
{
MessageRef msg = getMsgEngine().getStorage().getMessage(msgId);
popup.show();
}
+void Conversation::showSendReadReportPopup()
+{
+ auto &popupMngr = getApp().getPopupManager();
+ Popup &popup = popupMngr.getPopup();
+ popup.setTitle(msgt("IDS_MSGF_OPT_SEND_READ_REPORT"));
+ popup.addEventCb(EVAS_CALLBACK_DEL, EVAS_EVENT_CALLBACK(Conversation, onSendReadReportPopupDel), this);
+ popup.addButton(msgt("IDS_MSG_BUTTON_SEND_ABB3"), Popup::OkButtonId, POPUP_BUTTON_CB(Conversation, onSendReadReportPopupButtonClicked), this);
+ popup.addButton(msgt("IDS_MSG_BUTTON_CANCEL_ABB2"), Popup::CancelButtonId, POPUP_BUTTON_CB(Conversation, onSendReadReportPopupButtonClicked), this);
+ popup.setContent(msgt("IDS_MSG_POP_THE_SENDER_HAS_REQUESTED_A_READ_REPORT_TAP_SEND_TO_SEND_ONE"));
+ popup.show();
+}
+
void Conversation::showMainPopup()
{
PopupList &popup = getApp().getPopupManager().getPopupList();
updateNavibar();
return;
}
+
if(m_pRecipPanel)
{
if(m_pRecipPanel->isMbeVisible() || m_pRecipPanel->getItemsCount() == 0)
m_pRecipPanel->addRecipientsFromEntry(false);
m_pRecipPanel->clearEntry();
}
+
if(!isRecipExists() && !isBodyEmpty() && m_Mode == NewMessageMode)
{
showNoRecipPopup();
return;
}
- else
- {
- saveDraftMsg();
- pop();
- }
+
+ if(sendReadReportIfNeeded())
+ return;
+
+ saveDraftMsg();
+ pop();
}
void Conversation::onHwMoreButtonClicked()
m_pBody->setFocus(true);
}
+void Conversation::onSendReadReportPopupDel(Evas_Object *popup, void *eventInfo)
+{
+ MSG_LOG("");
+ pop();
+}
+
+void Conversation::onSendReadReportPopupButtonClicked(Popup &popup, int buttonId)
+{
+ MSG_LOG("");
+ if(buttonId == Popup::OkButtonId)
+ sendReadReport(MsgReport::ReadStatusIsRead);
+ popup.destroy();
+}
+
void Conversation::onRecipPopupDel(Evas_Object *popup, void *eventInfo)
{
MSG_LOG("");