|
|
|
@@ -48,7 +48,7 @@ class UITask; // forward declaration
|
|
|
|
|
class SMSScreen : public UIScreen {
|
|
|
|
|
public:
|
|
|
|
|
enum SubView { APP_MENU, INBOX, CONVERSATION, COMPOSE, CONTACTS, EDIT_CONTACT, PHONE_DIALER,
|
|
|
|
|
DIALING_OUT, INCOMING_CALL, IN_CALL, CALL_LOG };
|
|
|
|
|
DIALING_OUT, INCOMING_CALL, IN_CALL, CALL_LOG, CONTACT_PAGE };
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
UITask* _task;
|
|
|
|
@@ -92,6 +92,18 @@ private:
|
|
|
|
|
// Contacts list state
|
|
|
|
|
int _contactsCursor;
|
|
|
|
|
int _contactsScrollTop;
|
|
|
|
|
SubView _contactsReturnView; // where Q returns to from the contacts list
|
|
|
|
|
|
|
|
|
|
// Contact page (view / add / edit a single contact)
|
|
|
|
|
char _cpName[SMS_CONTACT_NAME_LEN];
|
|
|
|
|
char _cpPhone[SMS_PHONE_LEN];
|
|
|
|
|
char _cpOrigPhone[SMS_PHONE_LEN]; // key before an edit, for rename
|
|
|
|
|
int _cpCursor; // 0 = Name, 1 = Number, 2 = Save
|
|
|
|
|
bool _cpIsNew;
|
|
|
|
|
bool _cpEditing; // true = typing into the selected field
|
|
|
|
|
char _cpEditBuf[SMS_CONTACT_NAME_LEN];
|
|
|
|
|
int _cpEditPos;
|
|
|
|
|
bool _cpNeedNumber; // set when Save is pressed with no number
|
|
|
|
|
|
|
|
|
|
// Edit contact state
|
|
|
|
|
char _editPhone[SMS_PHONE_LEN];
|
|
|
|
@@ -142,7 +154,9 @@ public:
|
|
|
|
|
, _msgCount(0), _msgScrollPos(0)
|
|
|
|
|
, _composePos(0), _composeNewConversation(false)
|
|
|
|
|
, _phoneInputPos(0), _enteringPhone(false)
|
|
|
|
|
, _contactsCursor(0), _contactsScrollTop(0)
|
|
|
|
|
, _contactsCursor(0), _contactsScrollTop(0), _contactsReturnView(INBOX)
|
|
|
|
|
, _cpCursor(0), _cpIsNew(false), _cpEditing(false), _cpEditPos(0)
|
|
|
|
|
, _cpNeedNumber(false)
|
|
|
|
|
, _editNamePos(0), _editIsNew(false), _editReturnView(INBOX)
|
|
|
|
|
, _callReturnView(APP_MENU), _callConnectTime(0), _callVolume(3), _callDotAnim(0)
|
|
|
|
|
, _callLogCount(0), _callLogCursor(0), _callLogScrollTop(0), _unseenMissed(0)
|
|
|
|
@@ -154,6 +168,10 @@ public:
|
|
|
|
|
memset(_composePhone, 0, sizeof(_composePhone));
|
|
|
|
|
memset(_phoneInputBuf, 0, sizeof(_phoneInputBuf));
|
|
|
|
|
memset(_activePhone, 0, sizeof(_activePhone));
|
|
|
|
|
memset(_cpName, 0, sizeof(_cpName));
|
|
|
|
|
memset(_cpPhone, 0, sizeof(_cpPhone));
|
|
|
|
|
memset(_cpOrigPhone, 0, sizeof(_cpOrigPhone));
|
|
|
|
|
memset(_cpEditBuf, 0, sizeof(_cpEditBuf));
|
|
|
|
|
memset(_editPhone, 0, sizeof(_editPhone));
|
|
|
|
|
memset(_editNameBuf, 0, sizeof(_editNameBuf));
|
|
|
|
|
memset(_callPhone, 0, sizeof(_callPhone));
|
|
|
|
@@ -359,6 +377,7 @@ public:
|
|
|
|
|
switch (_view) {
|
|
|
|
|
case APP_MENU: return renderAppMenu(display);
|
|
|
|
|
case CALL_LOG: return renderCallLog(display);
|
|
|
|
|
case CONTACT_PAGE: return renderContactPage(display);
|
|
|
|
|
case INBOX: return renderInbox(display);
|
|
|
|
|
case CONVERSATION: return renderConversation(display);
|
|
|
|
|
case COMPOSE: return renderCompose(display);
|
|
|
|
@@ -400,11 +419,37 @@ public:
|
|
|
|
|
|
|
|
|
|
y += lineHeight;
|
|
|
|
|
|
|
|
|
|
// Item 1: SMS Inbox
|
|
|
|
|
// Item 1: Call Log
|
|
|
|
|
display.setCursor(4, y);
|
|
|
|
|
display.setColor(_menuCursor == 1 ? DisplayDriver::GREEN : DisplayDriver::LIGHT);
|
|
|
|
|
if (_menuCursor == 1) display.print("> ");
|
|
|
|
|
else display.print(" ");
|
|
|
|
|
display.print("Call Log");
|
|
|
|
|
|
|
|
|
|
// Show unseen missed-call count (hidden when there are none)
|
|
|
|
|
if (_unseenMissed > 0) {
|
|
|
|
|
char countHint[12];
|
|
|
|
|
snprintf(countHint, sizeof(countHint), " [%d]", _unseenMissed);
|
|
|
|
|
display.setColor(DisplayDriver::LIGHT);
|
|
|
|
|
display.print(countHint);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
y += lineHeight;
|
|
|
|
|
|
|
|
|
|
// Item 2: Contacts
|
|
|
|
|
display.setCursor(4, y);
|
|
|
|
|
display.setColor(_menuCursor == 2 ? DisplayDriver::GREEN : DisplayDriver::LIGHT);
|
|
|
|
|
if (_menuCursor == 2) display.print("> ");
|
|
|
|
|
else display.print(" ");
|
|
|
|
|
display.print("Contacts");
|
|
|
|
|
|
|
|
|
|
y += lineHeight;
|
|
|
|
|
|
|
|
|
|
// Item 3: SMS Inbox
|
|
|
|
|
display.setCursor(4, y);
|
|
|
|
|
display.setColor(_menuCursor == 3 ? DisplayDriver::GREEN : DisplayDriver::LIGHT);
|
|
|
|
|
if (_menuCursor == 3) display.print("> ");
|
|
|
|
|
else display.print(" ");
|
|
|
|
|
display.print("SMS Inbox");
|
|
|
|
|
|
|
|
|
|
// Show unread count hint (hidden when there are none)
|
|
|
|
@@ -417,23 +462,6 @@ public:
|
|
|
|
|
display.print(countHint);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
y += lineHeight;
|
|
|
|
|
|
|
|
|
|
// Item 2: Call Log
|
|
|
|
|
display.setCursor(4, y);
|
|
|
|
|
display.setColor(_menuCursor == 2 ? DisplayDriver::GREEN : DisplayDriver::LIGHT);
|
|
|
|
|
if (_menuCursor == 2) display.print("> ");
|
|
|
|
|
else display.print(" ");
|
|
|
|
|
display.print("Call Log");
|
|
|
|
|
|
|
|
|
|
// Show unseen missed-call count (hidden when there are none)
|
|
|
|
|
if (_unseenMissed > 0) {
|
|
|
|
|
char countHint[12];
|
|
|
|
|
snprintf(countHint, sizeof(countHint), " [%d]", _unseenMissed);
|
|
|
|
|
display.setColor(DisplayDriver::LIGHT);
|
|
|
|
|
display.print(countHint);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Modem status indicator
|
|
|
|
|
ModemState ms = modemManager.getState();
|
|
|
|
|
display.setTextSize(_prefs->smallTextSize());
|
|
|
|
@@ -1028,6 +1056,203 @@ public:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---- Contacts list ----
|
|
|
|
|
// ---- Contact page: view / add / edit one contact ----
|
|
|
|
|
void openContactPage(const char* name, const char* phone, bool isNew) {
|
|
|
|
|
strncpy(_cpName, name, SMS_CONTACT_NAME_LEN - 1);
|
|
|
|
|
_cpName[SMS_CONTACT_NAME_LEN - 1] = '\0';
|
|
|
|
|
strncpy(_cpPhone, phone, SMS_PHONE_LEN - 1);
|
|
|
|
|
_cpPhone[SMS_PHONE_LEN - 1] = '\0';
|
|
|
|
|
strncpy(_cpOrigPhone, phone, SMS_PHONE_LEN - 1);
|
|
|
|
|
_cpOrigPhone[SMS_PHONE_LEN - 1] = '\0';
|
|
|
|
|
_cpIsNew = isNew;
|
|
|
|
|
_cpCursor = 0;
|
|
|
|
|
_cpEditing = false;
|
|
|
|
|
_cpEditPos = 0;
|
|
|
|
|
_cpEditBuf[0] = '\0';
|
|
|
|
|
_cpNeedNumber = false;
|
|
|
|
|
_view = CONTACT_PAGE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int renderContactPage(DisplayDriver& display) {
|
|
|
|
|
display.setTextSize(1);
|
|
|
|
|
display.setColor(DisplayDriver::GREEN);
|
|
|
|
|
display.setCursor(0, 0);
|
|
|
|
|
display.print(_cpIsNew ? "New Contact" : "Contact");
|
|
|
|
|
|
|
|
|
|
display.setColor(DisplayDriver::LIGHT);
|
|
|
|
|
display.drawRect(0, 11, display.width(), 1);
|
|
|
|
|
|
|
|
|
|
display.setTextSize(1);
|
|
|
|
|
int lineHeight = 16;
|
|
|
|
|
int y = 24;
|
|
|
|
|
char rowBuf[SMS_CONTACT_NAME_LEN + 16];
|
|
|
|
|
|
|
|
|
|
// Row 0: Name
|
|
|
|
|
display.setCursor(4, y);
|
|
|
|
|
display.setColor(_cpCursor == 0 ? DisplayDriver::GREEN : DisplayDriver::LIGHT);
|
|
|
|
|
display.print(_cpCursor == 0 ? "> " : " ");
|
|
|
|
|
if (_cpEditing && _cpCursor == 0) {
|
|
|
|
|
snprintf(rowBuf, sizeof(rowBuf), "Name: %s_", _cpEditBuf);
|
|
|
|
|
} else {
|
|
|
|
|
snprintf(rowBuf, sizeof(rowBuf), "Name: %s", _cpName);
|
|
|
|
|
}
|
|
|
|
|
display.print(rowBuf);
|
|
|
|
|
y += lineHeight;
|
|
|
|
|
|
|
|
|
|
// Row 1: Number
|
|
|
|
|
display.setCursor(4, y);
|
|
|
|
|
display.setColor(_cpCursor == 1 ? DisplayDriver::GREEN : DisplayDriver::LIGHT);
|
|
|
|
|
display.print(_cpCursor == 1 ? "> " : " ");
|
|
|
|
|
if (_cpEditing && _cpCursor == 1) {
|
|
|
|
|
snprintf(rowBuf, sizeof(rowBuf), "Number: %s_", _cpEditBuf);
|
|
|
|
|
} else {
|
|
|
|
|
snprintf(rowBuf, sizeof(rowBuf), "Number: %s", _cpPhone);
|
|
|
|
|
}
|
|
|
|
|
display.print(rowBuf);
|
|
|
|
|
y += lineHeight;
|
|
|
|
|
|
|
|
|
|
// Row 2: Save
|
|
|
|
|
display.setCursor(4, y);
|
|
|
|
|
display.setColor(_cpCursor == 2 ? DisplayDriver::GREEN : DisplayDriver::LIGHT);
|
|
|
|
|
display.print(_cpCursor == 2 ? "> " : " ");
|
|
|
|
|
display.print("Save");
|
|
|
|
|
y += lineHeight;
|
|
|
|
|
|
|
|
|
|
if (_cpNeedNumber) {
|
|
|
|
|
display.setTextSize(_prefs->smallTextSize());
|
|
|
|
|
display.setColor(DisplayDriver::YELLOW);
|
|
|
|
|
display.setCursor(4, y + 4);
|
|
|
|
|
display.print("A number is required");
|
|
|
|
|
display.setTextSize(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Footer
|
|
|
|
|
display.setTextSize(1);
|
|
|
|
|
int footerY = display.height() - 12;
|
|
|
|
|
display.drawRect(0, footerY - 2, display.width(), 1);
|
|
|
|
|
display.setColor(DisplayDriver::YELLOW);
|
|
|
|
|
display.setCursor(0, footerY);
|
|
|
|
|
if (_cpEditing) {
|
|
|
|
|
display.print("Sh+Del:Cancel");
|
|
|
|
|
const char* rt = "Ent:Done";
|
|
|
|
|
display.setCursor(display.width() - display.getTextWidth(rt) - 6, footerY);
|
|
|
|
|
display.print(rt);
|
|
|
|
|
} else {
|
|
|
|
|
display.print("Q:Back");
|
|
|
|
|
if (!_cpIsNew) {
|
|
|
|
|
const char* mid = "F:Dial D:Del";
|
|
|
|
|
display.setCursor((display.width() - display.getTextWidth(mid)) / 2, footerY);
|
|
|
|
|
display.print(mid);
|
|
|
|
|
}
|
|
|
|
|
const char* rt = "Ent:Sel";
|
|
|
|
|
display.setCursor(display.width() - display.getTextWidth(rt) - 6, footerY);
|
|
|
|
|
display.print(rt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 5000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool handleContactPageInput(char c) {
|
|
|
|
|
// --- Field editing ---
|
|
|
|
|
if (_cpEditing) {
|
|
|
|
|
if (c == '\r') {
|
|
|
|
|
_cpEditBuf[_cpEditPos] = '\0';
|
|
|
|
|
if (_cpCursor == 0) {
|
|
|
|
|
strncpy(_cpName, _cpEditBuf, SMS_CONTACT_NAME_LEN - 1);
|
|
|
|
|
_cpName[SMS_CONTACT_NAME_LEN - 1] = '\0';
|
|
|
|
|
} else {
|
|
|
|
|
strncpy(_cpPhone, _cpEditBuf, SMS_PHONE_LEN - 1);
|
|
|
|
|
_cpPhone[SMS_PHONE_LEN - 1] = '\0';
|
|
|
|
|
}
|
|
|
|
|
_cpEditing = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (c == 0x18) { // Shift+Backspace -- abandon this field edit
|
|
|
|
|
_cpEditing = false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (c == '\b') {
|
|
|
|
|
if (_cpEditPos > 0) {
|
|
|
|
|
_cpEditPos--;
|
|
|
|
|
_cpEditBuf[_cpEditPos] = '\0';
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
int limit = (_cpCursor == 0) ? SMS_CONTACT_NAME_LEN - 1 : SMS_PHONE_LEN - 1;
|
|
|
|
|
if (c >= 32 && c < 127 && _cpEditPos < limit) {
|
|
|
|
|
_cpEditBuf[_cpEditPos++] = c;
|
|
|
|
|
_cpEditBuf[_cpEditPos] = '\0';
|
|
|
|
|
}
|
|
|
|
|
return true; // consume all keys while editing
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- Navigation ---
|
|
|
|
|
switch (c) {
|
|
|
|
|
case 'w': case 'W':
|
|
|
|
|
if (_cpCursor > 0) _cpCursor--;
|
|
|
|
|
_cpNeedNumber = false;
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case 's': case 'S':
|
|
|
|
|
if (_cpCursor < 2) _cpCursor++;
|
|
|
|
|
_cpNeedNumber = false;
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case '\r':
|
|
|
|
|
if (_cpCursor == 2) {
|
|
|
|
|
saveContactPage();
|
|
|
|
|
} else {
|
|
|
|
|
const char* src = (_cpCursor == 0) ? _cpName : _cpPhone;
|
|
|
|
|
strncpy(_cpEditBuf, src, sizeof(_cpEditBuf) - 1);
|
|
|
|
|
_cpEditBuf[sizeof(_cpEditBuf) - 1] = '\0';
|
|
|
|
|
_cpEditPos = strlen(_cpEditBuf);
|
|
|
|
|
_cpEditing = true;
|
|
|
|
|
_cpNeedNumber = false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case 'f': case 'F': // Dial this contact
|
|
|
|
|
if (!_cpIsNew && _cpPhone[0]) startCall(_cpPhone);
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case 'd': case 'D': // Delete this contact
|
|
|
|
|
if (!_cpIsNew && _cpOrigPhone[0]) {
|
|
|
|
|
smsContacts.remove(_cpOrigPhone);
|
|
|
|
|
Serial.printf("[SMSContacts] Deleted: %s\n", _cpOrigPhone);
|
|
|
|
|
returnToContacts();
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case 'q':
|
|
|
|
|
case KEY_CANCEL: // Back without saving
|
|
|
|
|
returnToContacts();
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void saveContactPage() {
|
|
|
|
|
if (_cpPhone[0] == '\0') {
|
|
|
|
|
_cpNeedNumber = true; // number is the storage key, so it cannot be blank
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// Renaming the number is a remove-then-add, since contacts are keyed on it
|
|
|
|
|
if (!_cpIsNew && _cpOrigPhone[0] && strcmp(_cpOrigPhone, _cpPhone) != 0) {
|
|
|
|
|
smsContacts.remove(_cpOrigPhone);
|
|
|
|
|
}
|
|
|
|
|
smsContacts.set(_cpPhone, _cpName);
|
|
|
|
|
Serial.printf("[SMSContacts] Saved: %s = %s\n", _cpPhone, _cpName);
|
|
|
|
|
returnToContacts();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void returnToContacts() {
|
|
|
|
|
int cnt = smsContacts.count();
|
|
|
|
|
if (_contactsCursor >= cnt) _contactsCursor = (cnt > 0) ? cnt - 1 : 0;
|
|
|
|
|
_view = CONTACTS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int renderContacts(DisplayDriver& display) {
|
|
|
|
|
display.setTextSize(1);
|
|
|
|
|
display.setColor(DisplayDriver::GREEN);
|
|
|
|
@@ -1045,9 +1270,7 @@ public:
|
|
|
|
|
display.setCursor(0, 25);
|
|
|
|
|
display.print("No contacts saved");
|
|
|
|
|
display.setCursor(0, 37);
|
|
|
|
|
display.print("Open a conversation");
|
|
|
|
|
display.setCursor(0, 49);
|
|
|
|
|
display.print("and press A to add");
|
|
|
|
|
display.print("Press A to add one");
|
|
|
|
|
display.setTextSize(1);
|
|
|
|
|
} else {
|
|
|
|
|
display.setTextSize(_prefs->smallTextSize());
|
|
|
|
@@ -1095,8 +1318,11 @@ public:
|
|
|
|
|
display.setColor(DisplayDriver::YELLOW);
|
|
|
|
|
display.setCursor(0, footerY);
|
|
|
|
|
display.print("Q:Back");
|
|
|
|
|
const char* rt = "Ent:SMS F:Call";
|
|
|
|
|
display.setCursor(display.width() - display.getTextWidth(rt) - 2, footerY);
|
|
|
|
|
const char* mid = "A:Add";
|
|
|
|
|
display.setCursor((display.width() - display.getTextWidth(mid)) / 2, footerY);
|
|
|
|
|
display.print(mid);
|
|
|
|
|
const char* rt = "Ent:Open";
|
|
|
|
|
display.setCursor(display.width() - display.getTextWidth(rt) - 6, footerY);
|
|
|
|
|
display.print(rt);
|
|
|
|
|
|
|
|
|
|
return 5000;
|
|
|
|
@@ -1330,6 +1556,7 @@ public:
|
|
|
|
|
switch (_view) {
|
|
|
|
|
case APP_MENU: return handleAppMenuInput(c);
|
|
|
|
|
case CALL_LOG: return handleCallLogInput(c);
|
|
|
|
|
case CONTACT_PAGE: return handleContactPageInput(c);
|
|
|
|
|
case INBOX: return handleInboxInput(c);
|
|
|
|
|
case CONVERSATION: return handleConversationInput(c);
|
|
|
|
|
case COMPOSE: return handleComposeInput(c);
|
|
|
|
@@ -1351,7 +1578,7 @@ public:
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case 's': case 'S':
|
|
|
|
|
if (_menuCursor < 2) _menuCursor++;
|
|
|
|
|
if (_menuCursor < 3) _menuCursor++;
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case '\r': // Enter - select menu item
|
|
|
|
@@ -1361,12 +1588,6 @@ public:
|
|
|
|
|
_phoneInputPos = 0;
|
|
|
|
|
_view = PHONE_DIALER;
|
|
|
|
|
} else if (_menuCursor == 1) {
|
|
|
|
|
// SMS Inbox
|
|
|
|
|
if (_sdReady) refreshInbox();
|
|
|
|
|
_inboxCursor = 0;
|
|
|
|
|
_inboxScrollTop = 0;
|
|
|
|
|
_view = INBOX;
|
|
|
|
|
} else {
|
|
|
|
|
// Call Log
|
|
|
|
|
if (_sdReady) {
|
|
|
|
|
smsStore.markMissedSeen();
|
|
|
|
@@ -1375,6 +1596,18 @@ public:
|
|
|
|
|
_callLogCursor = 0;
|
|
|
|
|
_callLogScrollTop = 0;
|
|
|
|
|
_view = CALL_LOG;
|
|
|
|
|
} else if (_menuCursor == 2) {
|
|
|
|
|
// Contacts
|
|
|
|
|
_contactsCursor = 0;
|
|
|
|
|
_contactsScrollTop = 0;
|
|
|
|
|
_contactsReturnView = APP_MENU;
|
|
|
|
|
_view = CONTACTS;
|
|
|
|
|
} else {
|
|
|
|
|
// SMS Inbox
|
|
|
|
|
if (_sdReady) refreshInbox();
|
|
|
|
|
_inboxCursor = 0;
|
|
|
|
|
_inboxScrollTop = 0;
|
|
|
|
|
_view = INBOX;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
@@ -1557,6 +1790,7 @@ public:
|
|
|
|
|
case 'd': case 'D': // Open contacts list
|
|
|
|
|
_contactsCursor = 0;
|
|
|
|
|
_contactsScrollTop = 0;
|
|
|
|
|
_contactsReturnView = INBOX;
|
|
|
|
|
_view = CONTACTS;
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
@@ -1727,7 +1961,18 @@ public:
|
|
|
|
|
if (_contactsCursor < cnt - 1) _contactsCursor++;
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case '\r': // Enter - compose to selected contact
|
|
|
|
|
case '\r': // Enter - open the contact page
|
|
|
|
|
if (cnt > 0 && _contactsCursor < cnt) {
|
|
|
|
|
const SMSContact& ct = smsContacts.get(_contactsCursor);
|
|
|
|
|
openContactPage(ct.name, ct.phone, false);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case 'a': case 'A': // Add a new contact
|
|
|
|
|
openContactPage("", "", true);
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case 'm': case 'M': // Compose an SMS to the selected contact
|
|
|
|
|
if (cnt > 0 && _contactsCursor < cnt) {
|
|
|
|
|
const SMSContact& ct = smsContacts.get(_contactsCursor);
|
|
|
|
|
_composeNewConversation = true;
|
|
|
|
@@ -1747,9 +1992,14 @@ public:
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case 'q':
|
|
|
|
|
case KEY_CANCEL: // Back to inbox
|
|
|
|
|
refreshInbox();
|
|
|
|
|
_view = INBOX;
|
|
|
|
|
case KEY_CANCEL: // Back to wherever the list was opened from
|
|
|
|
|
if (_contactsReturnView == INBOX) {
|
|
|
|
|
refreshInbox();
|
|
|
|
|
_view = INBOX;
|
|
|
|
|
} else {
|
|
|
|
|
_view = APP_MENU;
|
|
|
|
|
_menuCursor = 2;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|