Fixed in-call screen and call ended notifications; fixed dial number screen print responsiveness; fixed firmware version 4G text issue caused by - instead of .

This commit is contained in:
pelgraine
2026-02-26 02:19:10 +11:00
parent 197b6de4a6
commit d159318b00
4 changed files with 77 additions and 98 deletions
+58 -12
View File
@@ -33,6 +33,11 @@
static bool composeNeedsRefresh = false;
#define COMPOSE_REFRESH_INTERVAL 100 // ms before starting e-ink refresh after keypress (refresh itself takes ~644ms)
// Phone dialer debounce — independent from compose/smsSuppressLoop to avoid
// interfering with call view rendering and alert display
static bool dialerNeedsRefresh = false;
static unsigned long lastDialerRefresh = 0;
// DM compose mode (direct message to a specific contact)
static bool composeDM = false;
static int composeDMContactIdx = -1;
@@ -887,6 +892,19 @@ void loop() {
} else if (callEvt.type == CallEventType::ENDED) {
Serial.printf("[Call] Ended (%lus) with %s\n",
(unsigned long)callEvt.duration, callEvt.phone);
// Show alert with duration (supplements the immediate alert from Q hangup;
// this catches remote hangups and network drops)
{
char alertBuf[48];
if (callEvt.duration > 0) {
snprintf(alertBuf, sizeof(alertBuf), "Call Ended %lu:%02lu",
(unsigned long)(callEvt.duration / 60),
(unsigned long)(callEvt.duration % 60));
} else {
snprintf(alertBuf, sizeof(alertBuf), "Call Ended");
}
ui_task.showAlert(alertBuf, 2000);
}
ui_task.forceRefresh();
} else if (callEvt.type == CallEventType::MISSED) {
char alertBuf[48];
@@ -931,7 +949,7 @@ void loop() {
webReaderNeedsRefresh = false;
}
#endif
if (!composeMode && !notesSuppressLoop && !smsSuppressLoop
if (!composeMode && !notesSuppressLoop && !smsSuppressLoop && !dialerNeedsRefresh
#ifdef MECK_WEB_READER
&& !webReaderTextEntry
#endif
@@ -961,6 +979,21 @@ void loop() {
lastComposeRefresh = millis();
composeNeedsRefresh = false;
}
// Phone dialer debounced render (separate from compose debounce)
#ifdef HAS_4G_MODEM
if (dialerNeedsRefresh && (millis() - lastDialerRefresh) >= COMPOSE_REFRESH_INTERVAL) {
if (smsMode) {
SMSScreen* dialScr = (SMSScreen*)ui_task.getSMSScreen();
if (dialScr && dialScr->getSubView() == SMSScreen::PHONE_DIALER) {
display.startFrame();
dialScr->render(display);
display.endFrame();
}
}
dialerNeedsRefresh = false;
lastDialerRefresh = millis();
}
#endif
#ifdef MECK_WEB_READER
if (webReaderNeedsRefresh && (millis() - lastWebReaderRefresh) >= COMPOSE_REFRESH_INTERVAL) {
WebReaderScreen* wr2 = (WebReaderScreen*)ui_task.getWebReaderScreen();
@@ -1026,7 +1059,8 @@ void loop() {
touchFingerDown = true;
lastTouchAccepted = now;
if (smsScr->handleTouch(tx, ty)) {
ui_task.forceRefresh();
dialerNeedsRefresh = true;
lastDialerRefresh = millis();
}
}
} else {
@@ -1488,17 +1522,18 @@ void handleKeyboardInput() {
if (smsMode) {
SMSScreen* smsScr = (SMSScreen*)ui_task.getSMSScreen();
if (smsScr) {
// During active call views, route all keys directly to the screen
// and force a refresh after each keypress (no debounce needed)
// Keep display alive — SMS routes many keys via handleInput() directly,
// bypassing injectKey() which normally extends the auto-off timer.
ui_task.keepAlive();
if (smsScr->isInCallView()) {
smsScr->handleInput(key);
if (smsScr->isInCallView()) {
// Still in a call view — refresh to update display
ui_task.forceRefresh();
} else {
// Call ended, returned to a non-call view
ui_task.forceRefresh();
if (!smsScr->isInCallView()) {
// Hangup just happened — show "Call Ended" alert immediately
ui_task.showAlert("Call Ended", 2000);
}
// Force immediate render (call screen updates or return-to-dialer)
ui_task.forceRefresh();
ui_task.loop();
return;
}
@@ -1509,10 +1544,21 @@ void handleKeyboardInput() {
return;
}
// Phone dialer: route keys directly (letter keys map to numbers)
// Phone dialer: debounced refresh for digit entry, immediate render for
// view transitions (Enter=call, Q=back). This avoids the 686ms e-ink
// block per keypress while ensuring call/back screens render instantly.
if (smsScr->getSubView() == SMSScreen::PHONE_DIALER) {
smsScr->handleInput(key);
ui_task.forceRefresh();
if (smsScr->getSubView() == SMSScreen::PHONE_DIALER) {
// Still on dialer (digit/backspace) — debounced refresh
dialerNeedsRefresh = true;
lastDialerRefresh = millis();
} else {
// View changed (startCall or Q back) — render immediately
dialerNeedsRefresh = false;
ui_task.forceRefresh();
ui_task.loop();
}
return;
}
+11 -84
View File
@@ -47,7 +47,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_ENDED };
DIALING_OUT, INCOMING_CALL, IN_CALL };
private:
UITask* _task;
@@ -96,8 +96,6 @@ private:
unsigned long _callConnectTime; // millis() when call connected (UI timer)
uint8_t _callVolume; // Current speaker volume (0-5)
uint8_t _callDotAnim; // Animation frame for dialing dots
unsigned long _callEndedTime; // millis() when call ended (for brief splash)
unsigned long _callEndedDuration; // Call duration in seconds (for ended screen)
// Refresh debounce
bool _needsRefresh;
@@ -129,7 +127,6 @@ public:
, _contactsCursor(0), _contactsScrollTop(0)
, _editNamePos(0), _editIsNew(false), _editReturnView(INBOX)
, _callReturnView(APP_MENU), _callConnectTime(0), _callVolume(3), _callDotAnim(0)
, _callEndedTime(0), _callEndedDuration(0)
, _needsRefresh(false), _lastRefresh(0)
, _sdReady(false)
{
@@ -154,7 +151,7 @@ public:
bool isComposing() const { return _view == COMPOSE; }
bool isEnteringPhone() const { return _enteringPhone || _view == PHONE_DIALER; }
bool isInCallView() const {
return _view == DIALING_OUT || _view == INCOMING_CALL || _view == IN_CALL || _view == CALL_ENDED;
return _view == DIALING_OUT || _view == INCOMING_CALL || _view == IN_CALL;
}
// Transition to dialing screen — used by all dial callsites
@@ -169,13 +166,6 @@ public:
modemManager.dialCall(phone);
}
// Show brief "Call Ended" splash before returning to previous view
void showCallEnded(unsigned long duration) {
_callEndedDuration = duration;
_callEndedTime = millis();
_view = CALL_ENDED;
}
// Handle call events from modem (incoming, connected, ended, etc.)
void onCallEvent(const CallEvent& evt) {
switch (evt.type) {
@@ -202,13 +192,12 @@ public:
case CallEventType::ENDED:
Serial.printf("[SMSScreen] Call ended (%lus)\n", (unsigned long)evt.duration);
if (_view == IN_CALL || _view == DIALING_OUT) {
// Remote hangup or network drop — show ended splash
showCallEnded(evt.duration);
} else if (_view != CALL_ENDED) {
// Already left call view (e.g. user hung up), just clean up
_callPhone[0] = '\0';
_callConnectTime = 0;
// Remote hangup or network drop — return to previous view
// "Call Ended" alert is shown by main.cpp via showAlert()
_view = _callReturnView;
}
_callPhone[0] = '\0';
_callConnectTime = 0;
_needsRefresh = true;
break;
@@ -318,7 +307,6 @@ public:
case DIALING_OUT: return renderDialingOut(display);
case INCOMING_CALL: return renderIncomingCall(display);
case IN_CALL: return renderInCall(display);
case CALL_ENDED: return renderCallEnded(display);
}
return 1000;
}
@@ -1110,54 +1098,6 @@ public:
return 1000; // 1s refresh for timer
}
// ---- Call ended (brief splash) ----
int renderCallEnded(DisplayDriver& display) {
// Auto-dismiss after 2 seconds
if (_callEndedTime > 0 && (millis() - _callEndedTime) > 2000) {
_view = _callReturnView;
_callPhone[0] = '\0';
_callConnectTime = 0;
return 0; // Immediate re-render in new view
}
int W = display.width();
int H = display.height();
// Header
display.setTextSize(1);
display.setColor(DisplayDriver::GREEN);
display.setCursor(0, 0);
display.print("Call Ended");
renderSignalIndicator(display, W - 2, 0);
display.setColor(DisplayDriver::LIGHT);
display.drawRect(0, 11, W, 1);
// Contact name
char dispName[SMS_CONTACT_NAME_LEN];
smsContacts.displayName(_callPhone, dispName, sizeof(dispName));
display.setTextSize(1);
display.setColor(DisplayDriver::LIGHT);
display.setCursor(4, 20);
display.print(dispName);
// Duration
if (_callEndedDuration > 0) {
char durBuf[16];
snprintf(durBuf, sizeof(durBuf), "%02lu:%02lu",
_callEndedDuration / 60, _callEndedDuration % 60);
display.setTextSize(1);
display.setColor(DisplayDriver::LIGHT);
uint16_t durW = display.getTextWidth(durBuf);
display.setCursor((W - durW) / 2, H / 2 + 4);
display.print(durBuf);
}
return 500; // Check frequently for auto-dismiss
}
// =========================================================================
// INPUT HANDLING
// =========================================================================
@@ -1174,7 +1114,6 @@ public:
case DIALING_OUT: return handleDialingOutInput(c);
case INCOMING_CALL: return handleIncomingCallInput(c);
case IN_CALL: return handleInCallInput(c);
case CALL_ENDED: return handleCallEndedInput(c);
}
return false;
}
@@ -1658,15 +1597,12 @@ public:
bool handleInCallInput(char c) {
switch (c) {
case '\r': // Enter - hang up
case 'q': case 'Q': {
unsigned long dur = 0;
if (_callConnectTime > 0) {
dur = (millis() - _callConnectTime) / 1000;
}
case 'q': case 'Q':
modemManager.hangupCall();
showCallEnded(dur);
_view = _callReturnView;
_callPhone[0] = '\0';
_callConnectTime = 0;
return true;
}
case 'w': case 'W': // Volume up
if (_callVolume < 5) {
@@ -1690,15 +1626,6 @@ public:
return true; // Absorb all keys during call
}
}
// ---- Call ended input (any key dismisses) ----
bool handleCallEndedInput(char c) {
(void)c;
_view = _callReturnView;
_callPhone[0] = '\0';
_callConnectTime = 0;
return true;
}
};
#endif // SMS_SCREEN_H
+6
View File
@@ -114,6 +114,12 @@ public:
#endif
void showAlert(const char* text, int duration_millis) override;
void forceRefresh() override { _next_refresh = 100; }
// Wake display and extend auto-off timer. Call this when handling keys
// outside of injectKey() to prevent display auto-off during direct input.
void keepAlive() {
if (_display != NULL && !_display->isOn()) _display->turnOn();
_auto_off = millis() + 15000; // matches AUTO_OFF_MILLIS default
}
int getMsgCount() const { return _msgcount; }
int getUnreadMsgCount() const; // Per-channel unread tracking (standalone)
bool hasDisplay() const { return _display != NULL; }
+2 -2
View File
@@ -154,7 +154,7 @@ build_flags =
-D OFFLINE_QUEUE_SIZE=256
-D HAS_4G_MODEM=1
-D MECK_WEB_READER=1
-D FIRMWARE_VERSION='"Meck v0.9.4-4G"'
-D FIRMWARE_VERSION='"Meck v0.9.4.4G"'
build_src_filter = ${LilyGo_TDeck_Pro.build_src_filter}
+<helpers/esp32/*.cpp>
+<helpers/ui/MomentaryButton.cpp>
@@ -179,7 +179,7 @@ build_flags =
-D OFFLINE_QUEUE_SIZE=256
-D HAS_4G_MODEM=1
-D MECK_WEB_READER=1
-D FIRMWARE_VERSION='"Meck v0.9.4-4G-SA"'
-D FIRMWARE_VERSION='"Meck v0.9.4.4G.SA"'
build_src_filter = ${LilyGo_TDeck_Pro.build_src_filter}
+<helpers/esp32/*.cpp>
+<helpers/ui/MomentaryButton.cpp>