#define NEW_MSG_MORE_ICON MORE_OPTION_ICON"/b_more_option_ic_compose.png"
#define DELETEG_MORE_ICON MORE_OPTION_ICON"/b_more_option_ic_delete.png"
+#define FAIL_ICON "sent_fail_icon.png"
+
// Images(res):
#define THUMB_CONTACT_IMG_PATH IMAGE_PATH"/messages_list_thumb_image_single.png"
#define THUMB_GROUP_IMG_PATH IMAGE_PATH"/messages_list_thumb_image_multi.png"
#include "macros.inl"
-#define RESOURCE_IMAGE( FILE_NAME ) \
+#define RES_IMAGE( FILE_NAME ) \
group { \
name: FILE_NAME; \
images.image: FILE_NAME RAW; \
collections {
BASE_SCALE;
- RESOURCE_IMAGE("More_option_icon/b_more_option_ic_compose.png");
- RESOURCE_IMAGE("More_option_icon/b_more_option_ic_delete.png");
+ RES_IMAGE("More_option_icon/b_more_option_ic_compose.png");
+ RES_IMAGE("More_option_icon/b_more_option_ic_delete.png");
+ RES_IMAGE("sent_fail_icon.png");
}
#define __ContactAddress_h__
#include "MsgUtils.h"
+#include "ContactRecord.h"
namespace Msg {
class ContactAddress;
typedef std::shared_ptr<ContactAddress> ContactAddressRef;
- class ContactAddress {
+ class ContactAddress
+ : public ContactRecord {
+
public:
enum AddressType {
EmailType,
};
public:
+ ContactAddress();
+ ContactAddress(bool release, contacts_record_h record = nullptr);
virtual ~ContactAddress() {};
virtual AddressType getAddressType() const = 0;
virtual OwnerType getOwnerType() const = 0;
virtual std::string getThumbnailPath() const = 0;
};
+ inline ContactAddress::ContactAddress()
+ : ContactRecord()
+ {
+ }
+
+ inline ContactAddress::ContactAddress(bool release, contacts_record_h record)
+ : ContactRecord(release, record)
+ {
+ }
}
#endif /* __ContactAddress_h__ */
typedef std::shared_ptr<ContactMyProfileEmail> ContactMyProfileEmailRef;
class ContactMyProfileEmail
- : public ContactAddress
- , public ContactRecord {
+ : public ContactAddress {
public:
ContactMyProfileEmail(bool release, const ContactMyProfile &myProfile, contacts_record_h record = nullptr);
static const char *getUri();
std::string getDispName() const override;
std::string getAddress() const override;
std::string getThumbnailPath() const override;
+ ContactRecordRef clone() const override;
private:
int m_MyProfileId;
};
inline ContactMyProfileEmail::ContactMyProfileEmail(bool release, const ContactMyProfile &myProfile, contacts_record_h record)
- : ContactRecord(release, record)
+ : ContactAddress(release, record)
, m_MyProfileId(myProfile.getId())
, m_ThumbnailPath(myProfile.getThumbnailPath())
, m_DispName(myProfile.getDispName())
{
return EmailType;
}
+
+ inline ContactRecordRef ContactMyProfileEmail::clone() const
+ {
+ return cloneInternal<ContactMyProfileEmail>();
+ }
}
typedef std::shared_ptr<ContactMyProfileNumber> ContactMyProfileNumberRef;
class ContactMyProfileNumber
- : public ContactAddress
- , public ContactRecord {
+ : public ContactAddress {
+
public:
ContactMyProfileNumber(bool release, const ContactMyProfile &myProfile, contacts_record_h record = nullptr);
static const char *getUri();
std::string getDispName() const override;
std::string getAddress() const override;
std::string getThumbnailPath() const override;
+ ContactRecordRef clone() const override;
private:
int m_MyProfileId;
};
inline ContactMyProfileNumber::ContactMyProfileNumber(bool release, const ContactMyProfile &myProfile, contacts_record_h record)
- : ContactRecord(release, record)
+ : ContactAddress(release, record)
, m_MyProfileId(myProfile.getId())
, m_ThumbnailPath(myProfile.getThumbnailPath())
, m_DispName(myProfile.getDispName())
{
return NumberType;
}
+
+ inline ContactRecordRef ContactMyProfileNumber::clone() const
+ {
+ return cloneInternal<ContactMyProfileNumber>();
+ }
}
typedef std::shared_ptr<ContactPersonEmail> ContactPersonEmailRef;
class ContactPersonEmail
- : public ContactAddress
- , public ContactRecord {
+ : public ContactAddress {
+
public:
ContactPersonEmail(bool release, contacts_record_h record = nullptr);
static const char *getUri();
std::string getDispName() const override;
std::string getAddress() const override;
std::string getThumbnailPath() const override;
+ ContactRecordRef clone() const override;
};
inline ContactPersonEmail::ContactPersonEmail(bool release, contacts_record_h record)
- : ContactRecord(release, record)
+ : ContactAddress(release, record)
{
}
{
return EmailType;
}
+
+ inline ContactRecordRef ContactPersonEmail::clone() const
+ {
+ return cloneInternal<ContactPersonEmail>();
+ }
}
typedef std::shared_ptr<ContactPersonNumber> ContactPersonNumberRef;
class ContactPersonNumber
- : public ContactAddress
- , public ContactRecord {
+ : public ContactAddress {
+
public:
ContactPersonNumber(bool release, contacts_record_h record = nullptr);
static const char *getUri();
std::string getDispName() const override;
std::string getAddress() const override;
std::string getThumbnailPath() const override;
+ ContactRecordRef clone() const override;
};
inline ContactPersonNumber::ContactPersonNumber(bool release, contacts_record_h record)
- : ContactRecord(release, record)
+ : ContactAddress(release, record)
{
}
{
return NumberType;
}
+
+ inline ContactRecordRef ContactPersonNumber::clone() const
+ {
+ return cloneInternal<ContactPersonNumber>();
+ }
}
int getPersonId() const;
std::string getAddress() const;
std::string getDispName() const;
+ ContactRecordRef clone() const override;
};
inline ContactPersonPhoneLog::ContactPersonPhoneLog(bool release, contacts_record_h record)
{
return _contacts_person_phone_log._uri;
}
+
+ inline ContactRecordRef ContactPersonPhoneLog::clone() const
+ {
+ return cloneInternal<ContactPersonPhoneLog>();
+ }
}
class ContactRecord {
public:
+ ContactRecord();
ContactRecord(bool release, contacts_record_h record = nullptr);
virtual ~ContactRecord();
ContactRecord(ContactRecord&) = delete;
void set(contacts_record_h record);
contacts_record_h getRecord() const;
+ bool isValid() const;
+ virtual ContactRecordRef clone() const;
protected:
+
+ template <typename T>
+ std::shared_ptr<T> cloneInternal() const;
+
std::string getStr(unsigned propertyId) const;
int getInt(unsigned propertyId) const;
int getChildCount(unsigned propertyId) const;
{
return getInt(m_Record, propertyId);
}
+
+ inline bool ContactRecord::isValid() const
+ {
+ return m_Record != nullptr;
+ }
+
+ template <typename T>
+ std::shared_ptr<T> ContactRecord::cloneInternal() const
+ {
+ contacts_record_h clonedRec = {};
+ contacts_record_clone(m_Record, &clonedRec);
+ return std::make_shared<T>(true, clonedRec);
+ }
}
#endif /* __ContactRecord_h__ */
m_Record = nullptr;
}
}
+
+ContactRecordRef ContactRecord::clone() const
+{
+ return cloneInternal<ContactRecord>();
+}
virtual ~InputFrame();
Entry &getEntry();
+ const Entry &getEntry() const;
void setPredictBar(Evas_Object *obj);
void showPredictBar(bool value);
InputLayout &getLayout();
void onAttached(ViewItem &item) override;
private:
- void onHwBackButtonPreessed(Evas_Object *obj, void *event_info);
+ void onFocusChanged(Evas_Object *obj, void *event_info);
void onInputPanelEvent(Ecore_IMF_Context *ctx, int value);
void prepareLayout();
*/
#include "InputFrame.h"
+#include "PopupManager.h"
using namespace Msg;
return *m_pEntry;
}
+const Entry &InputFrame::getEntry() const
+{
+ return *m_pEntry;
+}
+
void InputFrame::setPredictBar(Evas_Object *obj)
{
m_pLayout->setPredictBar(obj);
{
if (!m_pEntry) {
m_pEntry = new Entry(*m_pLayout);
- m_pEntry->addHwButtonEvent(EEXT_CALLBACK_BACK, makeCbFirst(&InputFrame::onHwBackButtonPreessed), this);
- m_pEntry->addInputPanelEventCb(ECORE_IMF_INPUT_PANEL_STATE_EVENT, makeCbFirst(&InputFrame::onInputPanelEvent), this);
+ m_pEntry->enabledInputPanel(false);
+ m_pEntry->setFocusAllow(true);
m_pEntry->setSingleLine(true);
m_pEntry->setFocus(true);
m_pEntry->setScrollable(true);
m_pEntry->setScrollerPolicy(ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_ON);
+
+ m_pEntry->addFocusedCb(makeCbFirst(&InputFrame::onFocusChanged), this);
+ m_pEntry->addUnfocusedCb(makeCbFirst(&InputFrame::onFocusChanged), this);
+ m_pEntry->addInputPanelEventCb(ECORE_IMF_INPUT_PANEL_STATE_EVENT, makeCbFirst(&InputFrame::onInputPanelEvent), this);
+
m_pLayout->setEntry(*m_pEntry);
}
}
-void InputFrame::onHwBackButtonPreessed(Evas_Object *obj, void *event_info)
+void InputFrame::onFocusChanged(Evas_Object *obj, void *event_info)
{
- MSG_LOG("");
- // Empty callback for back button
+ m_pEntry->showInputPanel(m_pEntry->getFocus());
}
void InputFrame::onInputPanelEvent(Ecore_IMF_Context *ctx, int value)
{
switch (value) {
- case ECORE_IMF_INPUT_PANEL_STATE_HIDE:
- if (!isPause())
- pop();
- break;
+ case ECORE_IMF_INPUT_PANEL_STATE_HIDE: {
+ BasePopup *popup = App::getInst().getPopupManager().getTop();
+ if (!isPause() && !(popup && popup->isVisible()))
+ pop();
+ break;
+ }
}
}
+
#include <vector>
namespace Msg {
- struct TokenizedRecipients {
- std::list<std::pair<std::string, MsgAddress::AddressType>> validResults;
- std::string invalidResult;
- };
+ namespace MsgUtils {
+
+ struct TokenizedRecipients {
+ std::list<std::pair<std::string, MsgAddress::AddressType>> validResults;
+ std::string invalidResult;
+ };
- class MsgUtils {
- public:
- static TokenizedRecipients tokenizeRecipients(const std::string &inputText);
- static bool isValidNumber(const std::string &address);
- static bool isValidEmail(const std::string &address);
- static bool isValidAddress(const std::string &address);
- static MsgAddress::AddressType getAddressType(const std::string &address);
- static std::string makeNormalizedNumber(const std::string &number);
- static std::string makeCleanedNumber(const std::string &number);
- static bool isMms(Message::Type type);
- static bool isSms(Message::Type type);
- static std::string makeKbStr(long long bytes);
+ TokenizedRecipients tokenizeRecipients(const std::string &inputText);
+ bool isValidNumber(const std::string &address);
+ bool isValidEmail(const std::string &address);
+ bool isValidAddress(const std::string &address);
+ MsgAddress::AddressType getAddressType(const std::string &address);
+ std::string makeNormalizedNumber(const std::string &number);
+ std::string makeCleanedNumber(const std::string &number);
+ bool isMms(Message::Type type);
+ bool isSms(Message::Type type);
+ std::string makeKbStr(long long bytes);
};
}
#include <unistd.h>
#include <regex>
-using namespace Msg;
+namespace Msg {
+namespace MsgUtils {
-namespace
-{
- unsigned emailAddrLenMax = 256;
- const char *delimiters = ",;";
- const char *numberRegex = "\\+?([[:digit:]][ *\\(\\)-]*){2,14}[[:digit:]]$";
- const char *emailRegex = "(([[:alnum:]_!#$%&'*+/=?`{|}~^-]+)|(^\"([[:alnum:]_!#$%&'*+/=?`{|}~^-\\(\\)<>\\[\\]:;@,. (\\\\)(\\\")])+\"))+(?:\\.(([[:alnum:]_!#$%&'*+/=?`{|}~^-]+)|(\"([[:alnum:]_!#$%&'*+/=?`{|}~^-\\(\\)<>\\[\\]:;@,. (\\\\)(\\\")])+\")))*@[[:alnum:]-]+(?:\\.[[:alnum:]-]+)*";
-}
+unsigned emailAddrLenMax = 256;
+const char *delimiters = ",;";
+const char *numberRegex = "\\+?([[:digit:]][ *\\(\\)-]*){2,14}[[:digit:]]$";
+const char *emailRegex = "(([[:alnum:]_!#$%&'*+/=?`{|}~^-]+)|(^\"([[:alnum:]_!#$%&'*+/=?`{|}~^-\\(\\)<>\\[\\]:;@,. (\\\\)(\\\")])+\"))+(?:\\.(([[:alnum:]_!#$%&'*+/=?`{|}~^-]+)|(\"([[:alnum:]_!#$%&'*+/=?`{|}~^-\\(\\)<>\\[\\]:;@,. (\\\\)(\\\")])+\")))*@[[:alnum:]-]+(?:\\.[[:alnum:]-]+)*";
-TokenizedRecipients MsgUtils::tokenizeRecipients(const std::string &inputText)
+TokenizedRecipients tokenizeRecipients(const std::string &inputText)
{
TokenizedRecipients result;
std::string::size_type begin = inputText.find_first_not_of(delimiters);
return result;
}
-bool MsgUtils::isValidNumber(const std::string &address)
+bool isValidNumber(const std::string &address)
{
if (address.empty())
return false;
return std::regex_match(address, numTemplate);
}
-bool MsgUtils::isValidEmail(const std::string &address)
+bool isValidEmail(const std::string &address)
{
if (address.empty() || address.length() > emailAddrLenMax)
return false;
return std::regex_match(address, emailTemplate);
}
-bool MsgUtils::isValidAddress(const std::string &address)
+bool isValidAddress(const std::string &address)
{
return isValidNumber(address) || isValidEmail(address);
}
-MsgAddress::AddressType MsgUtils::getAddressType(const std::string &address)
+MsgAddress::AddressType getAddressType(const std::string &address)
{
if (isValidNumber(address))
{
return MsgAddress::UnknownAddressType;
}
-std::string MsgUtils::makeNormalizedNumber(const std::string &number)
+std::string makeNormalizedNumber(const std::string &number)
{
std::string normalizedNumber;
for (auto symbol : number)
return normalizedNumber;
}
-std::string MsgUtils::makeCleanedNumber(const std::string &number)
+std::string makeCleanedNumber(const std::string &number)
{
std::string cleanedNumber;
for (auto symbol : number)
return cleanedNumber;
}
-bool MsgUtils::isMms(Message::Type type)
+bool isMms(Message::Type type)
{
switch (type)
{
return type == Message::MT_SMS;
}
-std::string MsgUtils::makeKbStr(long long bytes)
+std::string makeKbStr(long long bytes)
{
const long long kb = 1024; // Bytes in kb
long long sizeKb = 0;
return std::to_string(sizeKb) + " " + (std::string)msg("IDS_MSGF_BODY_MSGSIZE_KB");
}
+} // MsgUtils
+} // Msg
const char *getEntry() const;
void setEditable(bool value);
void enabledInputPanel(bool value);
+ void showInputPanel(bool value);
void setScrollerPolicy(Elm_Scroller_Policy policyH, Elm_Scroller_Policy policyV);
void setAutocapitalType(Elm_Autocapital_Type type);
void setScrollable(bool value);
void setSingleLine(bool value);
void setCursorPos(int pos);
+ void setCursorPosToEnd();
int getCursorPos() const;
void setEditInfo(Entry &entry);
bool isEmpty() const;
void clear();
+ void setLimit(int charCount, int byteCount = 0);
+ void addMarkupFilterCb(Elm_Entry_Filter_Cb, void *data);
+ void addPreeditCb(Evas_Smart_Cb cb, void *data);
+ void addActivatedCb(Evas_Smart_Cb cb, void *data);
+ void addMaxlengthReachedCb(Evas_Smart_Cb cb, void *data);
+ void addFocusedCb(Evas_Smart_Cb cb, void *data);
+ void addUnfocusedCb(Evas_Smart_Cb cb, void *data);
+ void addChangedCb(Evas_Smart_Cb cb, void *data);
+ void addKeyDownCb(Evas_Object_Event_Cb cb, void *data);
void addInputPanelEventCb(Ecore_IMF_Input_Panel_Event type, InputPanelEventCb cb, const void *data);
void delInputPanelEventCb(Ecore_IMF_Input_Panel_Event type, InputPanelEventCb cb);
};
void pop(void *id = nullptr);
void pop(BasePopup *popup);
void push(BasePopup &popup, void *id = nullptr);
+ BasePopup *getTop() const;
/**
* @brief Process pause event
class ISearchBarListener {
public:
virtual ~ISearchBarListener() {};
- void onButtonClicked(SearchBar &obj) {};
- void onTextClicked(SearchBar &obj) {};
+ virtual void onButtonClicked(SearchBar &obj) {};
+ virtual void onTextClicked(SearchBar &obj) {};
};
}
elm_entry_input_panel_enabled_set(getEo(), value);
}
+void Entry::showInputPanel(bool value)
+{
+ if (value)
+ elm_entry_input_panel_show(getEo());
+ else
+ elm_entry_input_panel_hide(getEo());
+}
+
void Entry::setInputPanelReturnType(Elm_Input_Panel_Return_Key_Type retType)
{
elm_entry_input_panel_return_key_type_set(getEo(), retType);
elm_entry_cursor_pos_set(getEo(), pos);
}
+void Entry::setCursorPosToEnd()
+{
+ elm_entry_cursor_end_set(getEo());
+}
+
int Entry::getCursorPos() const
{
return elm_entry_cursor_pos_get(getEo());
View::setText(getEo(), "");
}
+void Entry::setLimit(int charCount, int byteCount)
+{
+ Elm_Entry_Filter_Limit_Size limitFilter = {charCount, byteCount};
+ elm_entry_markup_filter_append(getEo(), elm_entry_filter_limit_size, &limitFilter);
+}
+
+void Entry::addKeyDownCb(Evas_Object_Event_Cb cb, void *data)
+{
+ addEventCb(EVAS_CALLBACK_KEY_DOWN, cb, data);
+}
+
+void Entry::addChangedCb(Evas_Smart_Cb cb, void *data)
+{
+ addSmartCb("changed", cb, data);
+}
+
+void Entry::addFocusedCb(Evas_Smart_Cb cb, void *data)
+{
+ addSmartCb("focused", cb, data);
+}
+
+void Entry::addUnfocusedCb(Evas_Smart_Cb cb, void *data)
+{
+ addSmartCb("unfocused", cb, data);
+}
+
+void Entry::addMaxlengthReachedCb(Evas_Smart_Cb cb, void *data)
+{
+ addSmartCb("maxlength,reached", cb, data);
+}
+
+void Entry::addActivatedCb(Evas_Smart_Cb cb, void *data)
+{
+ addSmartCb("activated", cb, data);
+}
+
+void Entry::addMarkupFilterCb(Elm_Entry_Filter_Cb cb, void *data)
+{
+ elm_entry_markup_filter_append(getEo(), cb, data);
+}
+
void Entry::addInputPanelEventCb(Ecore_IMF_Input_Panel_Event type, InputPanelEventCb cb, const void *data)
{
- Ecore_IMF_Context *imf = (Ecore_IMF_Context*)elm_entry_imf_context_get(getEo());
+ auto *imf = (Ecore_IMF_Context*)elm_entry_imf_context_get(getEo());
if (imf)
ecore_imf_context_input_panel_event_callback_add(imf, type, cb, data);
}
void Entry::delInputPanelEventCb(Ecore_IMF_Input_Panel_Event type, InputPanelEventCb cb)
{
- Ecore_IMF_Context *imf = (Ecore_IMF_Context*)elm_entry_imf_context_get(getEo());
+ auto *imf = (Ecore_IMF_Context*)elm_entry_imf_context_get(getEo());
if (imf)
ecore_imf_context_input_panel_event_callback_del(imf, type, cb);
}
}
}
+BasePopup *PopupManager::getTop() const
+{
+ return m_pPopup;
+}
+
void PopupManager::onHwBackButtonClicked(Evas_Object *obj, void *eventInfo)
{
pop();
#include "InputFrame.h"
#include "SearchBar.h"
+#include "ContactAddress.h"
namespace Msg {
class RecipInputFrame
- : public InputFrame {
+ : public InputFrame
+ , private ISearchBarListener {
public:
- RecipInputFrame(NaviFrameController &parent);
+ RecipInputFrame(NaviFrameController &parent, std::string recip);
virtual ~RecipInputFrame();
+ std::string getAddress() const;
+
private:
// NaviFrameItem:
void onAttached(ViewItem &item) override;
- bool onRequestPop() override;
+
+ // Entry:
+ void onEntryChanged(Evas_Object *obj, void *event_info);
+ void onEntryActivated(Evas_Object *obj, void *event_info);
+ void onEntryFilter(Evas_Object *obj, char **text);
+
+ // ISearchBarListener:
+ void onButtonClicked(SearchBar &obj) override;
+ void onTextClicked(SearchBar &obj) override;
+
+ // Timer:
+ Eina_Bool onSearchTimerTick();
+
+ private:
+ template<typename ContactRec>
+ std::shared_ptr<ContactRec> search(const std::string &searchWord);
+
+ void showSearchBar(bool show);
+ void prepareEntry(std::string initText);
+ void close();
+ void reqestSearch();
+ void cancelSearch();
+ void searchButtonHandler();
private:
SearchBar *m_pSearchBar;
+ Ecore_Timer *m_pTimer;
+ std::string m_ContactAddress;
+ std::string m_DsipName;
};
}
void RecipFrame::showInputFrame()
{
if (!m_pInputFrame) {
- m_pInputFrame = new RecipInputFrame(getParent());
+ m_pInputFrame = new RecipInputFrame(getParent(), m_pRecipField->getEntry().getText());
m_pInputFrame->setOnPopCb(makeCbLast(&RecipFrame::onInputFramePop), this);
getParent().push(*m_pInputFrame);
}
void RecipFrame::onInputFramePop(NaviFrameItem &item)
{
MSG_LOG("");
+ m_pRecipField->getEntry().setText((m_pInputFrame->getAddress()));
m_pInputFrame = nullptr;
}
*/
#include "RecipInputFrame.h"
+#include "ContactManager.h"
#include "Logger.h"
+#include "ContactPersonPhoneLog.h"
+#include "ContactPersonNumber.h"
+#include "App.h"
+#include "TextDecorator.h"
+#include "MsgUtils.h"
+#include "ToastPopup.h"
+
+#include <Eina.h>
using namespace Msg;
-RecipInputFrame::RecipInputFrame(NaviFrameController &parent)
+namespace {
+ const int minDigits = 3;
+ const int minCharacters = 2;
+
+ bool isDigit(const std::string &str) {
+ auto itEnd = str.end();
+ for (auto it = str.begin() ;it != itEnd; ++it) {
+ if (!isdigit(*it))
+ return false;
+ }
+ return true;
+ }
+
+ bool isSeparatorChar(char c)
+ {
+ return c == ';' || c == ',';
+ }
+
+ bool isSeparatorChar(const std::string &str)
+ {
+ return str.size() == 1 && isSeparatorChar(str[0]);
+ }
+
+ bool isPreedit(const char *str)
+ {
+ return strstr(str, "<preedit>") == str &&
+ strstr(str, "</preedit>") != nullptr;
+ }
+}
+
+RecipInputFrame::RecipInputFrame(NaviFrameController &parent, std::string recip)
: InputFrame(parent)
, m_pSearchBar(nullptr)
+ , m_pTimer(nullptr)
{
- m_pSearchBar = new SearchBar(getLayout());
- setPredictBar(*m_pSearchBar);
- showPredictBar(true);
+ prepareEntry(std::move(recip));
}
RecipInputFrame::~RecipInputFrame()
{
+ cancelSearch();
+}
+
+std::string RecipInputFrame::getAddress() const
+{
+ return getEntry().getText();
+}
+
+void RecipInputFrame::showSearchBar(bool show)
+{
+ if (show && !m_pSearchBar) {
+ m_pSearchBar = new SearchBar(getLayout());
+ setPredictBar(*m_pSearchBar);
+ }
+ showPredictBar(show);
+}
+
+void RecipInputFrame::prepareEntry(std::string initText)
+{
+ getEntry().setText(std::move(initText));
+ getEntry().setCursorPosToEnd();
+ getEntry().setInputPanelReturnType(ELM_INPUT_PANEL_RETURN_KEY_TYPE_SEARCH);
+ getEntry().addChangedCb(makeCbFirst(&RecipInputFrame::onEntryChanged), this);
+ getEntry().addActivatedCb(makeCbFirst(&RecipInputFrame::onEntryActivated), this);
+ getEntry().addMarkupFilterCb(makeCbFirst(&RecipInputFrame::onEntryFilter), this);
+}
+
+void RecipInputFrame::close()
+{
+ cancelSearch();
+ pop();
+}
+
+template<typename ContactRec>
+std::shared_ptr<ContactRec> RecipInputFrame::search(const std::string &searchWord)
+{
+ if (!searchWord.empty()) {
+ auto list = App::getInst().getContactManager().search<ContactRec>(searchWord);
+ if (list) {
+ do {
+ auto &rec = list->get();
+ if (rec.isValid() && MsgUtils::isValidAddress(rec.getAddress())) {
+ return std::static_pointer_cast<ContactRec>(rec.clone());
+ } else {
+ MSG_LOG("Skip invalid contact: ", rec.getAddress());
+ }
+ } while (list->next());
+ }
+ }
+ return {};
+}
+
+Eina_Bool RecipInputFrame::onSearchTimerTick()
+{
+ std::string searchWord = getEntry().getText();
+ std::string highlightWord;
+
+ int len = eina_unicode_utf8_get_len(searchWord.c_str());
+ bool isDig = isDigit(searchWord);
+
+ if ((isDig && len >= minDigits) || (!isDig && len >= minCharacters)) {
+
+ ContactPersonNumberRef numberRef;
+ ContactPersonPhoneLogRef phoneLogRef;
+ std::string address;
+ std::string dispName;
+
+ numberRef = search<ContactPersonNumber>(searchWord);
+
+ if (numberRef) {
+ address = numberRef->getAddress();
+ dispName = numberRef->getDispName();
+ } else if (!numberRef) {
+ phoneLogRef = search<ContactPersonPhoneLog>(searchWord);
+ if (phoneLogRef)
+ address = phoneLogRef->getAddress();
+ }
+
+ if (!dispName.empty()) {
+ highlightWord = TextDecorator::highlightKeyword(std::move(dispName), searchWord);
+
+ }
+ else if (!address.empty()) {
+ highlightWord = TextDecorator::highlightKeyword(std::move(address), searchWord);
+ }
+ }
+
+ if (!highlightWord.empty()) {
+ showSearchBar(true);
+ m_pSearchBar->setText(highlightWord);
+ } else {
+ showSearchBar(false);
+ }
+
+ m_pTimer = nullptr;
+ return false; // Delete timer
+}
+
+void RecipInputFrame::reqestSearch()
+{
+ static const double interval = 0.3;
+
+ if (!isPopping()) {
+ if (!m_pTimer)
+ m_pTimer = ecore_timer_add(interval, makeCbFirst(&RecipInputFrame::onSearchTimerTick), this);
+ else
+ ecore_timer_reset(m_pTimer);
+ }
+}
+
+void RecipInputFrame::cancelSearch()
+{
+ if (m_pTimer) {
+ ecore_timer_del(m_pTimer);
+ m_pTimer = nullptr;
+ }
+}
+
+void RecipInputFrame::searchButtonHandler()
+{
+ cancelSearch();
+
+ std::string input = getEntry().getText();
+ int len = eina_unicode_utf8_get_len(input.c_str());
+
+ if (len > 0) {
+ bool isDig = isDigit(input);
+
+ if (len < minCharacters && !isDig) {
+ ToastPopup::toast(msgt("WDS_MSG_TPOP_ENTER_2_OR_MORE_LETTERS_ABB"));
+ return;
+ }
+
+ if (len < minDigits && isDig) {
+ ToastPopup::toast(msgt("WDS_MSG_TPOP_ENTER_3_OR_MORE_DIGITS_ABB"));
+ return;
+ }
+
+ auto numberRef = search<ContactPersonNumber>(input);
+ auto phoneLogRef = search<ContactPersonPhoneLog>(input);
+
+ if (numberRef || phoneLogRef) {
+ // TODO: impl.
+ } else {
+ if (MsgUtils::isValidNumber(input)) {
+ close();
+ } else {
+ ToastPopup::toast(msgt("WDS_PB_TPOP_NO_RESULTS_FOUND"), FAIL_ICON);
+ }
+ }
+ }
}
void RecipInputFrame::onAttached(ViewItem &item)
InputFrame::onAttached(item);
}
-bool RecipInputFrame::onRequestPop()
+void RecipInputFrame::onEntryFilter(Evas_Object *obj, char **text)
+{
+ if (*text) {
+ MSG_LOG(*text);
+ if (isPreedit(*text))
+ return;
+
+ if (isSeparatorChar(*text)) {
+ free(*text);
+ *text = nullptr;
+ close();
+ }
+ }
+}
+
+void RecipInputFrame::onEntryChanged(Evas_Object *obj, void *event_info)
+{
+ MSG_LOG("");
+ reqestSearch();
+}
+
+void RecipInputFrame::onButtonClicked(SearchBar &obj)
+{
+ MSG_LOG("");
+ searchButtonHandler();
+}
+
+void RecipInputFrame::onTextClicked(SearchBar &obj)
+{
+ MSG_LOG("");
+ close();
+}
+
+void RecipInputFrame::onEntryActivated(Evas_Object *obj, void *event_info)
{
MSG_LOG("");
- return true;
+ searchButtonHandler();
}
+