mirror of
https://github.com/pelgraine/Meck.git
synced 2026-08-07 01:02:45 +02:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user