Unified navigation inputs for cannedmessages

This commit is contained in:
HarukiToreda 2025-05-26 01:35:34 -04:00
parent e974a58d18
commit 7c4714afbb
7 changed files with 552 additions and 450 deletions

View File

@ -62,6 +62,7 @@
"stdexcept": "cpp", "stdexcept": "cpp",
"streambuf": "cpp", "streambuf": "cpp",
"cinttypes": "cpp", "cinttypes": "cpp",
"typeinfo": "cpp" "typeinfo": "cpp",
"*.xbm": "cpp"
} }
} }

View File

@ -10,6 +10,7 @@
#include "buzz.h" #include "buzz.h"
#include "main.h" #include "main.h"
#include "modules/ExternalNotificationModule.h" #include "modules/ExternalNotificationModule.h"
#include "modules/CannedMessageModule.h"
#include "power.h" #include "power.h"
#include "sleep.h" #include "sleep.h"
#ifdef ARCH_PORTDUINO #ifdef ARCH_PORTDUINO
@ -26,6 +27,7 @@
using namespace concurrency; using namespace concurrency;
ButtonThread *buttonThread; // Declared extern in header ButtonThread *buttonThread; // Declared extern in header
extern CannedMessageModule* cannedMessageModule;
volatile ButtonThread::ButtonEventType ButtonThread::btnEvent = ButtonThread::BUTTON_EVENT_NONE; volatile ButtonThread::ButtonEventType ButtonThread::btnEvent = ButtonThread::BUTTON_EVENT_NONE;
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) || defined(USERPREFS_BUTTON_PIN) #if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO) || defined(USERPREFS_BUTTON_PIN)
@ -118,6 +120,17 @@ ButtonThread::ButtonThread() : OSThread("Button")
void ButtonThread::switchPage() void ButtonThread::switchPage()
{ {
// Prevent screen switch if CannedMessageModule is focused and intercepting input
#if HAS_SCREEN
extern CannedMessageModule* cannedMessageModule;
if (cannedMessageModule && cannedMessageModule->isInterceptingAndFocused()) {
LOG_DEBUG("User button ignored during canned message input");
return; // Skip screen change
}
#endif
// Default behavior if not blocked
#ifdef BUTTON_PIN #ifdef BUTTON_PIN
#if !defined(USERPREFS_BUTTON_PIN) #if !defined(USERPREFS_BUTTON_PIN)
if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) != if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) !=
@ -135,8 +148,8 @@ void ButtonThread::switchPage()
powerFSM.trigger(EVENT_PRESS); powerFSM.trigger(EVENT_PRESS);
} }
#endif #endif
#endif #endif
#if defined(ARCH_PORTDUINO) #if defined(ARCH_PORTDUINO)
if ((settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) && if ((settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) &&
(settingsMap[user] != moduleConfig.canned_message.inputbroker_pin_press) || (settingsMap[user] != moduleConfig.canned_message.inputbroker_pin_press) ||

View File

@ -40,6 +40,7 @@ class ButtonThread : public concurrency::OSThread
bool isBuzzing() { return buzzer_flag; } bool isBuzzing() { return buzzer_flag; }
void setScreenFlag(bool flag) { screen_flag = flag; } void setScreenFlag(bool flag) { screen_flag = flag; }
bool getScreenFlag() { return screen_flag; } bool getScreenFlag() { return screen_flag; }
bool isInterceptingAndFocused();
// Disconnect and reconnect interrupts for light sleep // Disconnect and reconnect interrupts for light sleep
#ifdef ARCH_ESP32 #ifdef ARCH_ESP32

View File

@ -1754,7 +1754,6 @@ float Screen::estimatedHeading(double lat, double lon)
/// We will skip one node - the one for us, so we just blindly loop over all /// We will skip one node - the one for us, so we just blindly loop over all
/// nodes /// nodes
static size_t nodeIndex;
static int8_t prevFrame = -1; static int8_t prevFrame = -1;
// Draw the arrow pointing to a node's location // Draw the arrow pointing to a node's location
@ -2640,8 +2639,6 @@ static void drawDeviceFocused(OLEDDisplay *display, OLEDDisplayUiState *state, i
config.display.heading_bold = false; config.display.heading_bold = false;
#if HAS_GPS #if HAS_GPS
auto number_of_satellites = gpsStatus->getNumSatellites();
if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) { if (config.position.gps_mode != meshtastic_Config_PositionConfig_GpsMode_ENABLED) {
String displayLine = ""; String displayLine = "";
if (config.position.fixed_position) { if (config.position.fixed_position) {
@ -2878,7 +2875,6 @@ static void drawCompassAndLocationScreen(OLEDDisplay *display, OLEDDisplayUiStat
bool origBold = config.display.heading_bold; bool origBold = config.display.heading_bold;
config.display.heading_bold = false; config.display.heading_bold = false;
auto number_of_satellites = gpsStatus->getNumSatellites();
String Satelite_String = "Sat:"; String Satelite_String = "Sat:";
display->drawString(0, compactFirstLine, Satelite_String); display->drawString(0, compactFirstLine, Satelite_String);
String displayLine = ""; String displayLine = "";
@ -3322,7 +3318,6 @@ void NavigationBar(OLEDDisplay *display, OLEDDisplayUiState *state)
if (totalIcons == 0) return; if (totalIcons == 0) return;
const size_t iconsPerPage = (SCREEN_WIDTH + spacing) / (iconSize + spacing); const size_t iconsPerPage = (SCREEN_WIDTH + spacing) / (iconSize + spacing);
const size_t totalPages = (totalIcons + iconsPerPage - 1) / iconsPerPage;
const size_t currentPage = currentFrame / iconsPerPage; const size_t currentPage = currentFrame / iconsPerPage;
const size_t pageStart = currentPage * iconsPerPage; const size_t pageStart = currentPage * iconsPerPage;
const size_t pageEnd = min(pageStart + iconsPerPage, totalIcons); const size_t pageEnd = min(pageStart + iconsPerPage, totalIcons);
@ -3654,8 +3649,6 @@ int32_t Screen::runOnce()
// Switch to a low framerate (to save CPU) when we are not in transition // Switch to a low framerate (to save CPU) when we are not in transition
// but we should only call setTargetFPS when framestate changes, because // but we should only call setTargetFPS when framestate changes, because
// otherwise that breaks animations. // otherwise that breaks animations.
// === Auto-hide indicator icons unless in transition ===
OLEDDisplayUiState *state = ui->getUiState();
if (targetFramerate != IDLE_FRAMERATE && ui->getUiState()->frameState == FIXED) { if (targetFramerate != IDLE_FRAMERATE && ui->getUiState()->frameState == FIXED) {
// oldFrameState = ui->getUiState()->frameState; // oldFrameState = ui->getUiState()->frameState;

View File

@ -19,8 +19,7 @@
#define INPUT_BROKER_MSG_FN_SYMBOL_ON 0xf1 #define INPUT_BROKER_MSG_FN_SYMBOL_ON 0xf1
#define INPUT_BROKER_MSG_FN_SYMBOL_OFF 0xf2 #define INPUT_BROKER_MSG_FN_SYMBOL_OFF 0xf2
#define INPUT_BROKER_MSG_BLUETOOTH_TOGGLE 0xAA #define INPUT_BROKER_MSG_BLUETOOTH_TOGGLE 0xAA
#define INPUT_BROKER_MSG_SELECT 0x0D // Enter key / rotary encoder click #define INPUT_BROKER_MSG_TAB 0x09
typedef struct _InputEvent { typedef struct _InputEvent {
const char *source; const char *source;

File diff suppressed because it is too large Load Diff

View File

@ -11,13 +11,13 @@ enum cannedMessageModuleRunState {
CANNED_MESSAGE_RUN_STATE_DISABLED, CANNED_MESSAGE_RUN_STATE_DISABLED,
CANNED_MESSAGE_RUN_STATE_INACTIVE, CANNED_MESSAGE_RUN_STATE_INACTIVE,
CANNED_MESSAGE_RUN_STATE_ACTIVE, CANNED_MESSAGE_RUN_STATE_ACTIVE,
CANNED_MESSAGE_RUN_STATE_FREETEXT,
CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE, CANNED_MESSAGE_RUN_STATE_SENDING_ACTIVE,
CANNED_MESSAGE_RUN_STATE_ACK_NACK_RECEIVED, CANNED_MESSAGE_RUN_STATE_ACK_NACK_RECEIVED,
CANNED_MESSAGE_RUN_STATE_MESSAGE,
CANNED_MESSAGE_RUN_STATE_ACTION_SELECT, CANNED_MESSAGE_RUN_STATE_ACTION_SELECT,
CANNED_MESSAGE_RUN_STATE_ACTION_UP, CANNED_MESSAGE_RUN_STATE_ACTION_UP,
CANNED_MESSAGE_RUN_STATE_ACTION_DOWN, CANNED_MESSAGE_RUN_STATE_ACTION_DOWN,
CANNED_MESSAGE_RUN_STATE_FREETEXT,
CANNED_MESSAGE_RUN_STATE_MESSAGE_SELECTION,
CANNED_MESSAGE_RUN_STATE_DESTINATION_SELECTION CANNED_MESSAGE_RUN_STATE_DESTINATION_SELECTION
}; };
@ -77,6 +77,7 @@ public:
void showTemporaryMessage(const String &message); void showTemporaryMessage(const String &message);
void resetSearch(); void resetSearch();
void updateFilteredNodes(); void updateFilteredNodes();
bool isInterceptingAndFocused();
String drawWithCursor(String text, int cursor); String drawWithCursor(String text, int cursor);
// === Admin Handlers === // === Admin Handlers ===
@ -182,6 +183,15 @@ private:
std::vector<uint8_t> activeChannelIndices; std::vector<uint8_t> activeChannelIndices;
std::vector<NodeEntry> filteredNodes; std::vector<NodeEntry> filteredNodes;
bool isInputSourceAllowed(const InputEvent *event);
bool isUpEvent(const InputEvent *event);
bool isDownEvent(const InputEvent *event);
bool isSelectEvent(const InputEvent *event);
bool handleTabSwitch(const InputEvent *event);
int handleDestinationSelectionInput(const InputEvent *event, bool isUp, bool isDown, bool isSelect);
bool handleMessageSelectorInput(const InputEvent *event, bool isUp, bool isDown, bool isSelect);
bool handleFreeTextInput(const InputEvent *event);
bool handleSystemCommandInput(const InputEvent *event);
#if defined(USE_VIRTUAL_KEYBOARD) #if defined(USE_VIRTUAL_KEYBOARD)
Letter keyboard[2][4][10] = {{{{"Q", 20, 0, 0, 0, 0}, Letter keyboard[2][4][10] = {{{{"Q", 20, 0, 0, 0, 0},