desc { "default";
max: BUBBLE_CONTENT_WIDTH_MAX -1;
rel1.to_y: "bubble.pad.top";
- rel1.relative: 0.0 1.0;
+ rel1.relative: 1.0 1.0;
rel2.to_x: "bubble.pad.right";
rel2.to_y: "bubble.pad.bottom";
rel2.relative: 0.0 0.0;
align: 1.0 0.0;
+ fixed: 1 0;
}
}
spacer { "bubble.pad.right"; scale;
rel1.to_x: "info.thumb.pad";
rel1.relative: 1.0 1.0;
rel2.to_x: "";
- rel2.relative: 1.0 0.0;
+ rel2.relative: 1.0 1.0;
text.style: "entry_bubble_receive_textblock_style";
}
}
max: BUBBLE_PAD_LEFT_WIDTH -1;
rel2.to: "";
align: 0.0 0.0;
+ fixed: 1 0;
}
}
spacer { "pad.right"; scale;
desc { "default";
rel1.relative: 1.0 1.0;
rel1.to_x: "bubble.pad.left";
- rel2.relative: 1.0 0.0;
+ rel2.relative: 0.0 0.0;
rel2.to_x: "";
align: 0.0 0.0;
}
// Conversation:
virtual MsgConversationListRef getConversationList(ThreadId id) = 0;
+ virtual MsgConversationItemRef getConversationItem(MsgId id) = 0;
protected:
typedef std::vector<IMsgStorageListener *> MsgStorageListeners;
class BaseMsgId
{
public:
+ typedef int Type;
BaseMsgId()
: value(-1)
{
}
- BaseMsgId(int id)
+ BaseMsgId(Type id)
: value(id)
{
}
{
}
- operator int() const
+ operator Type() const
{
return value;
}
- BaseMsgId &operator=(int id)
+ BaseMsgId &operator=(Type id)
{
value = id;
return *this;
value = -1;
}
- int value; // implementation
+ Type value; // implementation
};
class ThreadId
return res;
}
+MsgConversationItemRef MsgStoragePrivate::getConversationItem(MsgId id)
+{
+ MsgConversationItemRef res;
+ msg_struct_t convItem = msg_create_struct(MSG_STRUCT_CONV_INFO);
+ if(msg_get_conversation(m_ServiceHandle, id, convItem) == 0)
+ {
+ res.reset(new MsgConversationItemPrivate(true, convItem));
+ }
+ else
+ {
+ msg_release_struct(&convItem);
+ }
+
+ return res;
+}
+
MessageRef MsgStoragePrivate::getMessage(MsgId id)
{
MessageRef msgRef;
// Conversation:
virtual MsgConversationListRef getConversationList(ThreadId id);
+ virtual MsgConversationItemRef getConversationItem(MsgId id);
private:
typedef void (IMsgStorageListener::*ListenerMethod)(const MsgIdList &);
const char *decorateAllItemStyle = nullptr);
private:
friend class ListView;
+ friend class ListItem;
void registerCallback();
void unregisterCallback();
void ListItem::update()
{
+ if(m_ItemStyle->m_pGenlistItemClass != elm_genlist_item_item_class_get(getElmObjItem()))
+ elm_genlist_item_item_class_update(getElmObjItem(), m_ItemStyle->m_pGenlistItemClass);
elm_genlist_item_update(getElmObjItem());
}
#include "ConvSelectAll.h"
#include "App.h"
#include "ConvListItem.h"
+#include <unordered_map>
namespace Msg
{
int getMessageCheckedCount() const;
private:
+ typedef std::unordered_map<MsgId::Type, ConvListItem*> ConvListItemMap;
+
+ private:
void create(Evas_Object *parent);
Evas_Object *createSelectAll(Evas_Object *parent);
Evas_Object *createList(Evas_Object *parent);
void selectListItems(bool state);
bool isAllListItemSelected() const;
ConvListItem *getItem(MsgId msgId) const;
+ void appendItem(ConvListItem *item);
+ void deleteItem(ConvListItem *item);
+ void clear();
// IListViewListener:
virtual void onListItemSelected(ListItem &listItem);
ThreadId m_ThreadId;
ConvSelectAll *m_pSelectAll;
ListView *m_pList;
+ ConvListItemMap m_ConvListItemMap;
IConvListListener *m_pListner;
App &m_App;
};
MsgId getMsgId() const;
void showPopup();
void setListener(IConvListItemListener *l);
- void updateStatus(MsgId id);
-
+ void updateStatus();
protected:
// ConvListViewItem:
using namespace Msg;
+namespace
+{
+ const int minMessagesBulk = 100;
+ const int additionalMessagesBulk = 50;
+}
+
ConvList::ConvList(Evas_Object *parent, App &app)
: ConvListLayout(parent)
, m_Mode(NormalMode)
, m_MsgEngine(app.getMsgEngine())
, m_pSelectAll(nullptr)
, m_pList(nullptr)
+ , m_ConvListItemMap()
, m_pListner(nullptr)
, m_App(app)
{
void ConvList::fill()
{
- m_pList->clear();
+ clear();
if(!m_ThreadId.isValid())
return;
MsgConversationListRef convList = m_MsgEngine.getStorage().getConversationList(m_ThreadId);
int convListLen = convList->getLength();
+ m_ConvListItemMap.reserve(convListLen <= minMessagesBulk/2 ? minMessagesBulk : convListLen + additionalMessagesBulk);
for(int i = 0; i < convListLen; ++i)
{
MsgConversationItem &item = convList->at(i);
ConvListItem *listItem = new ConvListItem(item, m_App);
- listItem->setListener(this);
- m_pList->appendItem(*listItem);
+ appendItem(listItem);
}
}
void ConvList::setThreadId(ThreadId id)
{
- m_ThreadId = id;
- fill();
+ if(m_ThreadId != id)
+ {
+ m_ThreadId = id;
+ fill();
+ }
}
void ConvList::navigateTo(MsgId msgId)
ConvListItem *ConvList::getItem(MsgId msgId) const
{
- auto items = m_pList->getItems<ConvListItem>();
- for(ConvListItem *item : items)
- {
- if(item->getMsgId() == msgId)
- return item;
- }
- return nullptr;
+ auto it = m_ConvListItemMap.find(msgId);
+ return it != m_ConvListItemMap.end() ? it->second : nullptr;
+}
+
+void ConvList::appendItem(ConvListItem *item)
+{
+ m_ConvListItemMap[item->getMsgId()] = item;
+ item->setListener(this);
+ m_pList->appendItem(*item);
+}
+
+void ConvList::deleteItem(ConvListItem *item)
+{
+ m_ConvListItemMap.erase(item->getMsgId());
+ m_pList->deleteItem(*item);
+}
+
+void ConvList::clear()
+{
+ m_pList->clear();
+ m_ConvListItemMap.clear();
}
void ConvList::deleteSelectedItems()
void ConvList::onMsgStorageUpdate(const MsgIdList &msgIdList)
{
- // FIXME: simple impl for demo
- fill();
+ for(auto &itemId: msgIdList)
+ {
+ ConvListItem *updated = getItem(itemId);
+ if(updated)
+ updated->updateStatus();
+ }
}
void ConvList::onMsgStorageInsert(const MsgIdList &msgIdList)
{
- // FIXME: simple impl for demo
- fill();
+ for(auto &itemId: msgIdList)
+ {
+ if(m_ThreadId == m_MsgEngine.getStorage().getMessage(itemId)->getThreadId())
+ {
+ if(!getItem(itemId))
+ {
+ MsgConversationItemRef item = m_MsgEngine.getStorage().getConversationItem(itemId);
+ ConvListItem *listItem = new ConvListItem(*item, m_App);
+ appendItem(listItem);
+ }
+ }
+ }
}
void ConvList::onMsgStorageDelete(const MsgIdList &msgIdList)
{
- // FIXME: simple impl for demo
- fill();
+ for(auto &itemId: msgIdList)
+ {
+ ConvListItem *deleted = getItem(itemId);
+ if(deleted)
+ deleteItem(deleted);
+ }
if(m_pListner && m_pList->isEmpty())
m_pListner->onAllItemsDeleted(*this);
{
}
-void ConvListItem::updateStatus(MsgId id)
+void ConvListItem::updateStatus()
{
- m_MsgId = id;
MessageRef msg = m_App.getMsgEngine().getStorage().getMessage(m_MsgId);
if(msg)
{
+ m_Time = msg->getTime();
m_NetworkStatus = msg->getNetworkStatus();
- updateProgressField();
+ }
+
+
+ if(m_NetworkStatus != Message::NS_Sending)
+ {
+ if(m_NetworkStatus == Message::NS_Send_Fail)
+ updateItemType(ConvItemType::Failed);
+ else if(m_NetworkStatus == Message::NS_Send_Success)
+ updateItemType(ConvItemType::Sent);
+ else if(m_NetworkStatus == Message::NS_Not_Send)
+ updateItemType(ConvItemType::Draft);
+ else if(m_NetworkStatus == Message::NS_Received)
+ updateItemType(ConvItemType::Received);
+ update();
}
}
protected:
Evas_Object *createProgress();
void updateProgressField();
+ void updateItemType(ConvItemType type);
private:
- void onBubbleResized(Evas_Object *obj, void *data);
Evas_Object *createButton(bool isEnabled, ConvItemType type);
virtual std::string getText(ListItem &item, const char *part);
virtual Evas_Object *getContent(ListItem &item, const char *part);
virtual const char *getCheckPart(ListItem &item);
-
- private:
- //Fixme: temporary fix caused by genlist resize issue
- Evas_Coord m_BubbleWidth;
- Evas_Coord m_BubbleHeight;
};
}
{
const int verticalBoxPads = 10;
const int horizontalBoxPads = 0;
- const int maxWidth = 220; //Fixme: set to 340 when apply base_scale: 2.6
- const char *textStyle = "DEFAULT='font=Tizen:style=Regular font_size=30 wrap=mixed text_class=label'";
+ const int maxWidth = 340;
+ const char *textStyle = "DEFAULT='font=Tizen:style=Regular font_size=24 wrap=mixed text_class=label'";
}
BubbleView::BubbleView(Evas_Object *parent)
break;
}
}
+ elm_box_recalculate(*this);
}
Evas_Object *BubbleView::createTextView(const std::string &text)
Evas_Object *BubbleView::createThumbView(const std::string &path)
{
Evas_Object *image = elm_image_add(*this);
- elm_image_aspect_fixed_set(image, false);
elm_image_file_set(image, path.c_str(), nullptr);
int imageWidth = 0;
int imageHeight = 0;
ConvListViewItem::ConvListViewItem(ConvItemType type)
: ListItem()
- , m_BubbleWidth(0)
- , m_BubbleHeight(0)
{
- switch (type)
- {
- case Sent:
- setStyle(sentStyle);
- break;
- case Received:
- setStyle(receivedStyle);
- break;
- case Draft:
- setStyle(draftStyle);
- break;
- case Failed:
- setStyle(failedStyle);
- break;
- default:
- break;
- }
+ updateItemType(type);
}
ConvListViewItem::~ConvListViewItem()
std::string ConvListViewItem::getText(ListItem &item, const char *part)
{
- if(!strcmp(part, "elm.text"))
- return getText();
- else if(!strcmp(part, timeTextPart))
+ if(!strcmp(part, timeTextPart))
return getTime();
else
return "";
{
if(!strcmp(part, bubbleContentPart))
{
- Evas_Object *bubble = getBubbleContent();
- evas_object_event_callback_add(bubble, EVAS_CALLBACK_RESIZE, EVAS_EVENT_CALLBACK(ConvListViewItem, onBubbleResized), this);
- if(m_BubbleHeight > 0 && m_BubbleWidth > 0)
- {
- evas_object_size_hint_min_set(bubble, m_BubbleWidth, m_BubbleHeight);
- evas_object_size_hint_max_set(bubble, m_BubbleWidth, m_BubbleHeight);
- }
- return bubble;
+ return getBubbleContent();
}
else if(!strcmp(part, thumbContentPart))
{
updateFields(infoStatus, ELM_GENLIST_ITEM_FIELD_CONTENT);
}
-void ConvListViewItem::onBubbleResized(Evas_Object *obj, void *data)
+void ConvListViewItem::updateItemType(ConvItemType type)
{
- MSG_LOG("");
- Evas_Coord w,h;
- evas_object_geometry_get(obj, nullptr, nullptr, &w, &h);
- if(m_BubbleHeight < h || m_BubbleWidth < w)
+ switch (type)
{
- m_BubbleWidth = w;
- m_BubbleHeight = h;
- elm_genlist_item_update(this->getElmObjItem());
+ case Sent:
+ setStyle(sentStyle);
+ break;
+ case Received:
+ setStyle(receivedStyle);
+ break;
+ case Draft:
+ setStyle(draftStyle);
+ break;
+ case Failed:
+ setStyle(failedStyle);
+ break;
+ default:
+ break;
}
}