From ee2a27258b6be93e3b66fe8fcd5cc8a189bfcb0f Mon Sep 17 00:00:00 2001 From: pelgraine <140762863+pelgraine@users.noreply.github.com> Date: Thu, 12 Feb 2026 20:45:41 +1100 Subject: [PATCH] improved cursor tracking and rename file handling implented with r key in Notes file list view --- examples/companion_radio/main.cpp | 10 +++--- examples/companion_radio/ui-new/Notesscreen.h | 33 ++++++++++++------- variants/lilygo_tdeck_pro/Tca8418keyboard.h | 18 +++++++--- 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 4105e8b..688135a 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -920,11 +920,11 @@ void handleKeyboardInput() { return; } - // Shift+Enter on a file = rename - if ((key == '\r') && keyboard.wasShiftConsumed()) { + // R on a file = rename + if (key == 'r') { if (notes->startRename()) { composeNeedsRefresh = true; - lastComposeRefresh = 0; + lastComposeRefresh = millis(); } return; } @@ -934,7 +934,7 @@ void handleKeyboardInput() { // Check if we just entered editing mode (new note via Enter) if (notes->isEditing()) { composeNeedsRefresh = true; - lastComposeRefresh = 0; + lastComposeRefresh = millis(); // Draw after debounce interval, not immediately } return; } @@ -958,7 +958,7 @@ void handleKeyboardInput() { ui_task.injectKey(key); if (notes->isEditing()) { composeNeedsRefresh = true; - lastComposeRefresh = 0; + lastComposeRefresh = millis(); // Draw after debounce interval, not immediately } return; } diff --git a/examples/companion_radio/ui-new/Notesscreen.h b/examples/companion_radio/ui-new/Notesscreen.h index 3bf15c7..d979bca 100644 --- a/examples/companion_radio/ui-new/Notesscreen.h +++ b/examples/companion_radio/ui-new/Notesscreen.h @@ -491,8 +491,15 @@ private: display.setColor(DisplayDriver::GREEN); display.print("Notes"); + // Show rename hint when a file (not "+ New Note") is selected + if (_selectedFile >= 1 && _selectedFile <= (int)_fileList.size()) { + display.setColor(DisplayDriver::YELLOW); + display.print(" R:Rename"); + } + snprintf(tmp, sizeof(tmp), "[%d]", (int)_fileList.size()); display.setCursor(display.width() - display.getTextWidth(tmp) - 2, 0); + display.setColor(DisplayDriver::GREEN); display.print(tmp); display.drawRect(0, 11, display.width(), 1); @@ -680,11 +687,11 @@ private: display.setColor(DisplayDriver::LIGHT); display.drawRect(0, 11, display.width(), 1); - // Text area + // Text area - tiny font (same as read mode) int textAreaTop = 14; int textAreaBottom = display.height() - 16; - display.setTextSize(1); + display.setTextSize(0); // Find cursor line int cursorLine = lineForPos(_cursorPos); @@ -733,6 +740,7 @@ private: // If buffer is empty, show cursor at top if (_bufLen == 0) { + display.setTextSize(0); display.setColor(DisplayDriver::GREEN); display.setCursor(0, textAreaTop); display.print("|"); @@ -748,7 +756,6 @@ private: display.setCursor(0, footerY); char status[20]; - int cursorLine = lineForPos(_cursorPos); int curPage = (_editMaxLines > 0) ? (cursorLine / _editMaxLines) + 1 : 1; int totalPg = (_editMaxLines > 0) ? max(1, (_numEditorLines + _editMaxLines - 1) / _editMaxLines) : 1; snprintf(status, sizeof(status), "Pg %d/%d", curPage, totalPg); @@ -881,6 +888,15 @@ private: return false; } + // R - rename selected file + if (c == 'r') { + if (_selectedFile >= 1 && _selectedFile <= (int)_fileList.size()) { + startRename(); + return true; + } + return false; + } + return false; } @@ -1084,14 +1100,9 @@ public: _linesPerPage = textAreaHeight / _lineHeight; if (_linesPerPage < 5) _linesPerPage = 5; - // Size 1 font metrics (for edit mode) - display.setTextSize(1); - uint16_t charW = display.getTextWidth("M"); - _editCharsPerLine = charW > 0 ? display.width() / charW : 20; - if (_editCharsPerLine < 10) _editCharsPerLine = 10; - if (_editCharsPerLine > 40) _editCharsPerLine = 40; - - _editLineHeight = 12; + // Size 0 (tiny) font metrics for edit mode too (same font as read mode) + _editCharsPerLine = _charsPerLine; + _editLineHeight = _lineHeight; int editTextAreaH = display.height() - 14 - 16; // Header + footer _editMaxLines = editTextAreaH / _editLineHeight; if (_editMaxLines < 3) _editMaxLines = 3; diff --git a/variants/lilygo_tdeck_pro/Tca8418keyboard.h b/variants/lilygo_tdeck_pro/Tca8418keyboard.h index 9813d43..83c437a 100644 --- a/variants/lilygo_tdeck_pro/Tca8418keyboard.h +++ b/variants/lilygo_tdeck_pro/Tca8418keyboard.h @@ -31,6 +31,7 @@ private: bool _shiftActive; // Sticky shift (one-shot or held) bool _shiftConsumed; // Was shift active for the last returned key bool _shiftHeld; // Shift key physically held down + bool _shiftUsedWhileHeld; // Was shift consumed by any key while held bool _altActive; // Sticky alt (one-shot) bool _symActive; // Sticky sym (one-shot) unsigned long _lastShiftTime; // For Shift+key combos @@ -150,7 +151,7 @@ private: public: TCA8418Keyboard(uint8_t addr = 0x34, TwoWire* wire = &Wire) : _addr(addr), _wire(wire), _initialized(false), - _shiftActive(false), _shiftConsumed(false), _shiftHeld(false), _altActive(false), _symActive(false), _lastShiftTime(0) {} + _shiftActive(false), _shiftConsumed(false), _shiftHeld(false), _shiftUsedWhileHeld(false), _altActive(false), _symActive(false), _lastShiftTime(0) {} bool begin() { // Check if device responds @@ -208,9 +209,13 @@ public: // Track shift release (before the general release-ignore) if (!pressed && (keyCode == 35 || keyCode == 31)) { _shiftHeld = false; - // Don't clear _shiftActive here - it may be a one-shot tap - // where release arrives before the next key press. - // _shiftActive is cleared when consumed by a key (if !_shiftHeld). + // If shift was used while held (e.g. cursor nav), clear it completely + // so the next bare keypress isn't treated as shifted. + // If shift was NOT used (tap-then-release), keep _shiftActive for one-shot. + if (_shiftUsedWhileHeld) { + _shiftActive = false; + } + _shiftUsedWhileHeld = false; return 0; } @@ -223,6 +228,7 @@ public: if (keyCode == 35 || keyCode == 31) { // Shift keys _shiftActive = true; _shiftHeld = true; + _shiftUsedWhileHeld = false; _lastShiftTime = millis(); Serial.println("KB: Shift activated"); return 0; @@ -288,6 +294,10 @@ public: if (c >= 'a' && c <= 'z') { c = c - 'a' + 'A'; } + // Track that shift was used while physically held + if (_shiftHeld) { + _shiftUsedWhileHeld = true; + } // Only clear shift if it's one-shot (tap), not held down if (!_shiftHeld) { _shiftActive = false;