From 661157e368f5b5ec7b421f0a6addf476807c5423 Mon Sep 17 00:00:00 2001 From: pelgraine <140762863+pelgraine@users.noreply.github.com> Date: Thu, 7 May 2026 20:27:58 +1000 Subject: [PATCH] Fix trace screen for t5s3 and add home icon for trace screen to t5s3 --- examples/companion_radio/main.cpp | 24 +++++++-- examples/companion_radio/ui-new/Tracescreen.h | 51 +++++++++++++++++++ examples/companion_radio/ui-new/UITask.cpp | 35 ++++++++++--- examples/companion_radio/ui-new/homeicons.h | 6 +++ .../companion_radio/ui-new/virtualkeyboard.h | 1 + 5 files changed, 108 insertions(+), 9 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 20e962fe..09311e25 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -696,6 +696,7 @@ #include "DiscoveryScreen.h" #include "LastHeardScreen.h" #include "PathEditorScreen.h" + #include "Tracescreen.h" static TouchDrvGT911 gt911Touch; static bool gt911Ready = false; @@ -1208,18 +1209,18 @@ static void lastHeardToggleContact() { // Home screen FIRST page: tile taps (virtual coordinate hit test) if (ui_task.isOnHomeScreen() && ui_task.isHomeShowingTiles()) { - const int tileW = 40, tileH = 28, gapX = 1, gapY = 1; + const int tileW = 40, tileH = 22, gapX = 1, gapY = 1; const int gridW = tileW * 3 + gapX * 2; const int gridX = (128 - gridW) / 2; // =3 int gridY = ui_task.getTileGridVY(); // Check if tap is within the tile grid area if (vx >= gridX && vx < gridX + gridW && - vy >= gridY && vy < gridY + 2 * (tileH + gapY)) { + vy >= gridY && vy < gridY + 3 * (tileH + gapY)) { int col = (vx - gridX) / (tileW + gapX); if (col > 2) col = 2; int row = (vy - gridY) / (tileH + gapY); - if (row > 1) row = 1; + if (row > 2) row = 2; if (row == 0 && col == 0) { ui_task.gotoChannelPickerScreen(); return 0; } if (row == 0 && col == 1) { ui_task.gotoContactsScreen(); return 0; } @@ -1231,6 +1232,8 @@ static void lastHeardToggleContact() { #else if (row == 1 && col == 2) { ui_task.gotoDiscoveryScreen(); return 0; } #endif + // Third row: only centre tile (col 1) is real; col 0 and col 2 fall through to page-flip + if (row == 2 && col == 1) { ui_task.gotoTraceScreen(); return 0; } } // Tap outside tiles — left half backward, right half forward return (vx < 64) ? (char)KEY_PREV : (char)KEY_NEXT; @@ -1694,6 +1697,21 @@ static void lastHeardToggleContact() { return KEY_ENTER; } + // Trace screen: long press = Enter on most rows; on T5S3 the Type Path row + // opens the virtual keyboard instead so users can enter a comma-separated + // hash list without a physical keyboard. + if (ui_task.isOnTraceScreen()) { +#if defined(LilyGo_T5S3_EPaper_Pro) + TraceScreen* ts = (TraceScreen*)ui_task.getTraceScreen(); + if (ts && ts->isOnTypePathRow()) { + const char* current = ts->getCurrentPathAsText(); + ui_task.showVirtualKeyboard(VKB_TRACE_PATH, "Type Path", current, 79); + return 0; + } +#endif + return KEY_ENTER; + } + // Repeater admin: long press → open keyboard for password or CLI if (ui_task.isOnRepeaterAdmin()) { RepeaterAdminScreen* admin = (RepeaterAdminScreen*)ui_task.getRepeaterAdminScreen(); diff --git a/examples/companion_radio/ui-new/Tracescreen.h b/examples/companion_radio/ui-new/Tracescreen.h index c2269e57..9d0141ea 100644 --- a/examples/companion_radio/ui-new/Tracescreen.h +++ b/examples/companion_radio/ui-new/Tracescreen.h @@ -306,6 +306,33 @@ public: bool wantsExit() const { return _wantExit; } bool isEditing() const { return _editing; } + // --- Public helpers for T5S3 long-press → virtual keyboard integration --- + + // True if the highlighted menu row is the Type Path entry (STATE_BUILD only). + bool isOnTypePathRow() const { + return _state == STATE_BUILD && menuItemAt(_menuSel) == MENU_TYPE_PATH; + } + + // Returns the current path formatted as a comma-separated string, suitable + // for pre-populating an external text editor (e.g. the T5S3 virtual keyboard). + // The returned pointer references an internal buffer and is valid until the + // next call to this method or to setTypedPath()/parseTypedPath(). + const char* getCurrentPathAsText() { + pathToEditBuf(); + return _editBuf; + } + + // Apply a path typed externally (via virtual keyboard submission). + // Replaces the working path buffer with whatever parses out of `text` + // and ensures the inline editor flag is cleared so the menu redraws cleanly. + void setTypedPath(const char* text) { + if (!text) return; + strncpy(_editBuf, text, sizeof(_editBuf) - 1); + _editBuf[sizeof(_editBuf) - 1] = '\0'; + parseTypedPath(); + _editing = false; + } + void enter(int pathHashMode) { _state = STATE_BUILD; _hopCount = 0; @@ -433,7 +460,11 @@ private: snprintf(tmp, sizeof(tmp), "%c Path: %s", prefix, pathStr); display.print(tmp); } else { +#if defined(LilyGo_T5S3_EPaper_Pro) + snprintf(tmp, sizeof(tmp), "%c Type Path: [Long press]", prefix); +#else snprintf(tmp, sizeof(tmp), "%c Type Path: [Press Enter]", prefix); +#endif display.print(tmp); } break; @@ -494,9 +525,17 @@ private: display.setColor(DisplayDriver::LIGHT); display.setCursor(0, footerY); if (_editing) { +#if defined(LilyGo_T5S3_EPaper_Pro) + display.print("Boot:Cancel Tap:Apply"); +#else display.print("Q:Cancel Enter:Apply"); +#endif } else { +#if defined(LilyGo_T5S3_EPaper_Pro) + display.print("Boot:Exit Tap:Sel"); +#else display.print("Q:Exit W/S:Nav Ent:Sel"); +#endif } return 5000; @@ -555,7 +594,11 @@ private: display.drawRect(0, footerY - 2, display.width(), 1); display.setColor(DisplayDriver::LIGHT); display.setCursor(0, footerY); +#if defined(LilyGo_T5S3_EPaper_Pro) + display.print("Boot:Back Tap:Add"); +#else display.print("Q:Back W/S:Scroll Ent:Add"); +#endif return 5000; } @@ -607,7 +650,11 @@ private: display.drawRect(0, footerY - 2, display.width(), 1); display.setColor(DisplayDriver::LIGHT); display.setCursor(0, footerY); +#if defined(LilyGo_T5S3_EPaper_Pro) + display.print("Boot:Cancel"); +#else display.print("Q:Cancel"); +#endif return 500; // Fast refresh for elapsed timer } @@ -699,7 +746,11 @@ private: display.drawRect(0, footerY - 2, display.width(), 1); display.setColor(DisplayDriver::LIGHT); display.setCursor(0, footerY); +#if defined(LilyGo_T5S3_EPaper_Pro) + display.print("Boot:Back Tap:New Trace"); +#else display.print("Q:Back Ent:New Trace"); +#endif return 5000; } diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index ac335f53..62a2361b 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -499,7 +499,7 @@ public: }; const int tileW = 40; - const int tileH = 28; + const int tileH = 22; const int gapX = 1; const int gapY = 1; const int gridW = tileW * 3 + gapX * 2; @@ -518,20 +518,35 @@ public: // Icon centered in tile int iconX = tx + (tileW - HOME_ICON_W) / 2; - int iconY = ty + 4; + int iconY = ty + 2; display.drawXbm(iconX, iconY, tiles[row][col].icon, HOME_ICON_W, HOME_ICON_H); // Label centered below icon display.setTextSize(_node_prefs->smallTextSize()); - display.drawTextCentered(tx + tileW / 2, ty + 18, tiles[row][col].label); + display.drawTextCentered(tx + tileW / 2, ty + 15, tiles[row][col].label); } } - // Nav hint below grid - y = gridY + 2 * tileH + gapY + 2; + // Third row: single centred Trace tile (column 1 position only) + { + int row3y = gridY + 2 * (tileH + gapY); + int col1x = gridX + (tileW + gapX); + + display.setColor(DisplayDriver::LIGHT); + display.drawRect(col1x, row3y, tileW, tileH); + + int iconX = col1x + (tileW - HOME_ICON_W) / 2; + int iconY = row3y + 2; + display.drawXbm(iconX, iconY, icon_trace, HOME_ICON_W, HOME_ICON_H); + + display.setTextSize(_node_prefs->smallTextSize()); + display.drawTextCentered(col1x + tileW / 2, row3y + 15, "Trace"); + } + + // Nav hint at bottom of screen display.setColor(DisplayDriver::GREEN); display.setTextSize(_node_prefs->smallTextSize()); - display.drawTextCentered(display.width() / 2, y, "Tap tile to open"); + display.drawTextCentered(display.width() / 2, display.height() - 8, "Tap tile to open"); } display.setTextSize(1); @@ -2523,6 +2538,14 @@ void UITask::onVKBSubmit() { if (_screenBeforeVKB) setCurrScreen(_screenBeforeVKB); break; } + case VKB_TRACE_PATH: { + TraceScreen* ts = (TraceScreen*)getTraceScreen(); + if (ts) { + ts->setTypedPath(text); + } + if (_screenBeforeVKB) setCurrScreen(_screenBeforeVKB); + break; + } } _screenBeforeVKB = nullptr; _next_refresh = 0; diff --git a/examples/companion_radio/ui-new/homeicons.h b/examples/companion_radio/ui-new/homeicons.h index 22df7068..61f6fa2e 100644 --- a/examples/companion_radio/ui-new/homeicons.h +++ b/examples/companion_radio/ui-new/homeicons.h @@ -54,6 +54,12 @@ static const uint8_t icon_alarm[] PROGMEM = { 0x40,0x40, 0x20,0x80, 0x1F,0x00, 0x00,0x00, 0x20,0x40, 0x40,0x20, }; +// ➡ Right arrow (Trace Route) +static const uint8_t icon_trace[] PROGMEM = { + 0x00,0x00, 0x00,0x00, 0x00,0x80, 0x00,0xC0, 0x00,0xE0, 0xFF,0xF0, + 0xFF,0xF0, 0x00,0xE0, 0x00,0xC0, 0x00,0x80, 0x00,0x00, 0x00,0x00, +}; + // 🔔 Bell — 7x8 status bar indicator (alarm enabled) // MSB-first, 1 byte per row #define BELL_ICON_W 7 diff --git a/examples/companion_radio/ui-new/virtualkeyboard.h b/examples/companion_radio/ui-new/virtualkeyboard.h index 824c73f3..39d7ed55 100644 --- a/examples/companion_radio/ui-new/virtualkeyboard.h +++ b/examples/companion_radio/ui-new/virtualkeyboard.h @@ -39,6 +39,7 @@ enum VKBPurpose { VKB_WEB_LINK, // Web reader link number entry #endif VKB_TEXT_PAGE, // Text reader: go to page number + VKB_TRACE_PATH, // Trace screen: type comma-separated path values }; class VirtualKeyboard {