lock screen and lock screen clock t5s3

This commit is contained in:
pelgraine
2026-03-12 05:12:45 +11:00
parent 565c2a4c9b
commit 8b78eac17f
4 changed files with 128 additions and 1 deletions

View File

@@ -1395,8 +1395,10 @@ void loop() {
// Swipe = finger drag > threshold → scroll/page turn
// Long press = finger held > 500ms without moving → edit/enter
// After processing an event, cooldown waits for finger lift before next event.
// Touch is disabled while lock screen is active.
// ---------------------------------------------------------------------------
#if defined(LilyGo_T5S3_EPaper_Pro)
if (!ui_task.isLocked())
{
int16_t tx, ty;
bool gotPoint = readTouchLandscape(&tx, &ty);

View File

@@ -1003,6 +1003,75 @@ public:
}
};
// ==========================================================================
// Lock Screen — T5S3 only
// Big clock, battery %, unread message count. Touch disabled while shown.
// Long press boot button to lock/unlock. Touch disabled while locked.
// ==========================================================================
#if defined(LilyGo_T5S3_EPaper_Pro)
class LockScreen : public UIScreen {
UITask* _task;
mesh::RTCClock* _rtc;
NodePrefs* _node_prefs;
public:
LockScreen(UITask* task, mesh::RTCClock* rtc, NodePrefs* node_prefs)
: _task(task), _rtc(rtc), _node_prefs(node_prefs) {}
int render(DisplayDriver& display) override {
uint32_t now = _rtc->getCurrentTime();
char timeBuf[6] = "--:--";
if (now > 1700000000) {
int32_t local = (int32_t)now + ((int32_t)_node_prefs->utc_offset_hours * 3600);
int hrs = (local / 3600) % 24;
if (hrs < 0) hrs += 24;
int mins = (local / 60) % 60;
if (mins < 0) mins += 60;
sprintf(timeBuf, "%02d:%02d", hrs, mins);
}
// ---- Huge clock: HH:MM on one line ----
display.setTextSize(5); // Clock face size (FreeSansBold24pt × 5)
display.setColor(DisplayDriver::LIGHT);
display.drawTextCentered(display.width() / 2, 55, timeBuf);
// ---- Battery + unread on one line ----
display.setTextSize(1);
{
uint16_t mv = _task->getBattMilliVolts();
int pct = 0;
if (mv > 0) {
pct = ((mv - 3000) * 100) / (4200 - 3000);
if (pct < 0) pct = 0;
if (pct > 100) pct = 100;
}
int unread = _task->getUnreadMsgCount();
char infoBuf[32];
if (unread > 0) {
sprintf(infoBuf, "%d%% | %d unread", pct, unread);
} else {
sprintf(infoBuf, "%d%%", pct);
}
display.setColor(DisplayDriver::GREEN);
display.drawTextCentered(display.width() / 2, 108, infoBuf);
}
// ---- Unlock hint ----
display.setTextSize(0);
display.setColor(DisplayDriver::LIGHT);
display.drawTextCentered(display.width() / 2, 120, "Hold button to unlock");
return 30000;
}
bool handleInput(char c) override {
return false;
}
};
#endif // LilyGo_T5S3_EPaper_Pro
void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* node_prefs) {
_display = display;
_sensors = sensors;
@@ -1066,6 +1135,9 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no
settings_screen = new SettingsScreen(this, &rtc_clock, node_prefs);
repeater_admin = nullptr; // Lazy-initialized on first use to preserve heap for audio
discovery_screen = new DiscoveryScreen(this, &rtc_clock);
#if defined(LilyGo_T5S3_EPaper_Pro)
lock_screen = new LockScreen(this, &rtc_clock, node_prefs);
#endif
audiobook_screen = nullptr; // Created and assigned from main.cpp if audio hardware present
#ifdef HAS_4G_MODEM
sms_screen = new SMSScreen(this);
@@ -1297,7 +1369,10 @@ void UITask::loop() {
if (ev == BUTTON_EVENT_CLICK) {
#if defined(LilyGo_T5S3_EPaper_Pro)
// T5S3: single click = cycle pages on home, go back to home from elsewhere
if (curr == home) {
// Ignored while locked — long press required to unlock
if (_locked) {
c = 0;
} else if (curr == home) {
c = checkDisplayOn(KEY_NEXT);
} else {
// Navigate back: reader reading→file list, file list→home, others→home
@@ -1499,6 +1574,15 @@ char UITask::handleLongPress(char c) {
the_mesh.enterCLIRescue();
c = 0; // consume event
}
#if defined(LilyGo_T5S3_EPaper_Pro)
else if (_locked) {
unlockScreen();
c = 0;
} else {
lockScreen();
c = 0;
}
#endif
return c;
}
@@ -1536,6 +1620,33 @@ char UITask::handleTripleClick(char c) {
return c;
}
#if defined(LilyGo_T5S3_EPaper_Pro)
void UITask::lockScreen() {
if (_locked) return;
_locked = true;
_screenBeforeLock = curr;
setCurrScreen(lock_screen);
board.setBacklight(false); // Save power
_next_refresh = 0; // Draw lock screen immediately
_auto_off = millis() + 60000; // 60s before display off while locked
Serial.println("[UI] Screen locked");
}
void UITask::unlockScreen() {
if (!_locked) return;
_locked = false;
if (_screenBeforeLock) {
setCurrScreen(_screenBeforeLock);
} else {
gotoHomeScreen();
}
_screenBeforeLock = nullptr;
_auto_off = millis() + AUTO_OFF_MILLIS;
_next_refresh = 0;
Serial.println("[UI] Screen unlocked");
}
#endif
bool UITask::getGPSState() {
#if ENV_INCLUDE_GPS == 1
return _node_prefs != NULL && _node_prefs->gps_enabled;

View File

@@ -86,6 +86,11 @@ class UITask : public AbstractUITask {
UIScreen* map_screen; // Map tile screen (GPS + SD card tiles)
UIScreen* curr;
bool _homeShowingTiles = false; // Set by HomeScreen render when tile grid is visible
#if defined(LilyGo_T5S3_EPaper_Pro)
UIScreen* lock_screen; // Lock screen (big clock + battery + unread)
UIScreen* _screenBeforeLock = nullptr;
bool _locked = false;
#endif
void userLedHandler();
@@ -157,6 +162,11 @@ public:
bool isOnRepeaterAdmin() const { return curr == repeater_admin; }
bool isOnDiscoveryScreen() const { return curr == discovery_screen; }
bool isOnMapScreen() const { return curr == map_screen; }
#if defined(LilyGo_T5S3_EPaper_Pro)
bool isLocked() const { return _locked; }
void lockScreen();
void unlockScreen();
#endif
#ifdef MECK_WEB_READER
bool isOnWebReader() const { return curr == web_reader; }
#endif

View File

@@ -144,6 +144,10 @@ void FastEPDDisplay::setTextSize(int sz) {
_canvas->setFont(&FreeSansBold24pt7b);
_canvas->setTextSize(1);
break;
case 5: // Clock face — lock screen (FreeSansBold24pt scaled 5×)
_canvas->setFont(&FreeSansBold24pt7b);
_canvas->setTextSize(5);
break;
default:
#ifdef MECK_SERIF_FONT
_canvas->setFont(&FreeSerif12pt7b);