T-Watch touch ui fixes: repeater admin, path editor. Add boot cpu freq 80 flag to platformio

This commit is contained in:
Pelgraine
2026-07-08 19:22:35 +10:00
parent 973d02df60
commit 821db1cff6
5 changed files with 104 additions and 5 deletions
+29 -3
View File
@@ -1613,6 +1613,28 @@ static void lastHeardToggleContact() {
if (ui_task.isOnSMSScreen()) return 0;
#endif
#if defined(LILYGO_TWATCH_S3_PLUS)
// Repeater admin (watch): tap selects a menu row (tap again = activate);
// param entry opens the keyboard for the value.
if (ui_task.isOnRepeaterAdmin()) {
RepeaterAdminScreen* admin = (RepeaterAdminScreen*)ui_task.getRepeaterAdminScreen();
if (admin) {
RepeaterAdminScreen::AdminState astate = admin->getState();
if (astate == RepeaterAdminScreen::STATE_CATEGORY_MENU ||
astate == RepeaterAdminScreen::STATE_COMMAND_MENU) {
int result = admin->selectRowAtVY(vy);
if (result == 1) { ui_task.forceRefresh(); return 0; }
if (result == 2) return KEY_ENTER; // tapped current row -- activate
return 0;
}
if (astate == RepeaterAdminScreen::STATE_PARAM_ENTRY) {
ui_task.openTWatchKeyboard(3, 0); // tap opens keyboard for the value
return 0;
}
}
}
#endif
// All other screens: tap = select
return KEY_ENTER;
}
@@ -1988,9 +2010,13 @@ static void lastHeardToggleContact() {
#endif
}
#if defined(LILYGO_TWATCH_S3_PLUS)
// Watch: any other admin state long-press opens the CLI keyboard.
ui_task.openTWatchKeyboard(3, 0); // TWKB_ADMIN_CLI
return 0;
// Watch: keyboard only for param entry; menu/other states activate the
// highlighted item (no raw CLI keyboard).
if (astate == RepeaterAdminScreen::STATE_PARAM_ENTRY) {
ui_task.openTWatchKeyboard(3, 0); // param value entry
return 0;
}
return KEY_ENTER;
#endif
}
}
@@ -281,7 +281,7 @@ public:
if (selected) {
display.setColor(DisplayDriver::LIGHT);
#if defined(LilyGo_T5S3_EPaper_Pro)
#if defined(LilyGo_T5S3_EPaper_Pro) || defined(LILYGO_TWATCH_S3_PLUS)
display.fillRect(0, y, display.width(), lineH);
#else
display.fillRect(0, y + 5, display.width(), lineH);
@@ -383,6 +383,12 @@ public:
const char* right = "Hold:Select";
display.setCursor(display.width() - display.getTextWidth(right) - 2, footerY);
display.print(right);
#elif defined(LILYGO_TWATCH_S3_PLUS)
display.setCursor(0, footerY);
display.print("Tap:Slct");
const char* right = "Hold:Entr";
display.setCursor(display.width() - display.getTextWidth(right) - 2, footerY);
display.print(right);
#else
display.setCursor(0, footerY);
display.print("Sh+Del:Bk W/S:Nav");
@@ -479,6 +479,39 @@ public:
AdminState getState() const { return _state; }
uint8_t getPermissions() const { return _permissions; }
// Map a touch Y (128-virtual space) to a menu row and select it.
// Returns 0 = miss/no-op, 1 = selection moved, 2 = tapped current selection.
// Mirrors the row layout in renderCategoryMenu / renderCommandMenu.
int selectRowAtVY(int vy) {
const int headerH = 14, footerH = 14;
int lineH = the_mesh.getNodePrefs()->smallLineH();
if (_state == STATE_CATEGORY_MENU) {
int bodyTop = headerH;
if (_serverTime > 0) bodyTop += lineH + 2; // clock drift line
if (_telemHasVoltage || _telemHasTemp || _telemRequested) bodyTop += lineH + 2; // telemetry line
if (vy < bodyTop || vy >= 128 - footerH) return 0;
int row = (vy - bodyTop) / lineH;
if (row < 0 || row >= CAT_COUNT) return 0;
if (row == _catSel) return 2;
_catSel = row;
return 1;
}
if (_state == STATE_COMMAND_MENU) {
int bodyTop = headerH + lineH + 2; // category title line
if (vy < bodyTop || vy >= 128 - footerH) return 0;
int idx = _scrollOffset + (vy - bodyTop) / lineH;
int count = CATEGORIES[_catSel].count;
if (idx < 0 || idx >= count) return 0;
if (idx == _cmdSel) return 2;
_cmdSel = idx;
return 1;
}
return 0;
}
void onLoginResult(bool success, uint8_t permissions, uint32_t server_time) {
_waitingForLogin = false;
if (success) {
@@ -562,6 +595,11 @@ public:
// --- Header ---
display.setTextSize(1);
#if defined(LILYGO_TWATCH_S3_PLUS)
// Clip long lines at the screen edge instead of wrapping them onto the row
// below (restored before returning so other screens are unaffected).
((LGFXDisplay*)&display)->setTextWrap(false);
#endif
display.setColor(DisplayDriver::GREEN);
display.setCursor(0, 0);
const char* hdrPrefix = (_state == STATE_PASSWORD_ENTRY || _state == STATE_LOGGING_IN)
@@ -627,6 +665,8 @@ public:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.print("Boot:Exit");
renderFooterMidRight(display, footerY, "Back:Exit", "Tap:Open", "Swipe:Sel");
#elif defined(LILYGO_TWATCH_S3_PLUS)
display.print("Long Press: Select");
#else
display.print("Sh+Del:Exit");
renderFooterMidRight(display, footerY, "Sh+Del:Exit", "Ent:Open", "W/S:Sel");
@@ -637,6 +677,8 @@ public:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.print("Boot:Back");
renderFooterMidRight(display, footerY, "Back:Back", "Tap:Run", "Swipe:Sel");
#elif defined(LILYGO_TWATCH_S3_PLUS)
display.print("Long Press: Run");
#else
display.print("Sh+Del:Back");
renderFooterMidRight(display, footerY, "Sh+Del:Back", "Ent:Run", "W/S:Sel");
@@ -647,6 +689,8 @@ public:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.print("Boot:Cancel");
renderFooterRight(display, footerY, "Tap:Send");
#elif defined(LILYGO_TWATCH_S3_PLUS)
display.print("Tap: Enter value");
#else
display.print("Sh+Del:Cancel");
renderFooterRight(display, footerY, "Ent:Send");
@@ -679,6 +723,10 @@ public:
break;
}
#if defined(LILYGO_TWATCH_S3_PLUS)
((LGFXDisplay*)&display)->setTextWrap(true); // restore default before returning
#endif
if (_state == STATE_LOGGING_IN || _state == STATE_COMMAND_PENDING) return 30000; // static text; poll()/callbacks force refresh on state change
if (_state == STATE_PASSWORD_ENTRY && _lastCharAt > 0 && (millis() - _lastCharAt) < 800) {
return _lastCharAt + 800 - millis() + 50;
+15 -1
View File
@@ -34,7 +34,7 @@
#endif
#ifndef AUTO_OFF_MILLIS
#define AUTO_OFF_MILLIS 15000 // 15 seconds
#define AUTO_OFF_MILLIS 45000 // 45 seconds
#endif
// Right-aligned values on the dense home pages compensate for the e-ink X
// origin offset so they are not clipped at the right edge. Default 0 for
@@ -2223,6 +2223,20 @@ void UITask::loop() {
} else {
c = checkDisplayOn(KEY_NEXT);
}
#elif defined(LILYGO_TWATCH_S3_PLUS)
// Watch: on the contacts screen a button click opens the path editor for
// the selected contact; elsewhere it wakes the display / emits KEY_NEXT.
if (isOnContactsScreen()) {
int idx = ((ContactsScreen*)contacts_screen)->getSelectedContactIdx();
if (idx >= 0) {
gotoPathEditor(idx);
c = 0;
} else {
c = checkDisplayOn(KEY_NEXT);
}
} else {
c = checkDisplayOn(KEY_NEXT);
}
#else
c = checkDisplayOn(KEY_NEXT);
#endif