mirror of
https://github.com/pelgraine/Meck.git
synced 2026-03-28 17:42:44 +01:00
"Added additional channel compose functionality - can switch channels now. Minor ui changes for nav bar"
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
static bool composeMode = false;
|
||||
static char composeBuffer[138]; // 137 chars max + null terminator
|
||||
static int composePos = 0;
|
||||
static uint8_t composeChannelIdx = 0; // Which channel to send to
|
||||
|
||||
void initKeyboard();
|
||||
void handleKeyboardInput();
|
||||
@@ -402,7 +403,7 @@ void handleKeyboardInput() {
|
||||
if (key == '\b') {
|
||||
// Backspace - check if shift was recently pressed for cancel combo
|
||||
if (keyboard.wasShiftRecentlyPressed(500)) {
|
||||
// Shift+Backspace = Cancel
|
||||
// Shift+Backspace = Cancel (works anytime)
|
||||
Serial.println("Compose: Shift+Backspace, cancelling...");
|
||||
composeMode = false;
|
||||
composeBuffer[0] = '\0';
|
||||
@@ -420,6 +421,40 @@ void handleKeyboardInput() {
|
||||
return;
|
||||
}
|
||||
|
||||
// A/D keys switch channels (only when buffer is empty or as special function)
|
||||
if ((key == 'a' || key == 'A') && composePos == 0) {
|
||||
// Previous channel
|
||||
if (composeChannelIdx > 0) {
|
||||
composeChannelIdx--;
|
||||
} else {
|
||||
// Wrap to last valid channel
|
||||
for (uint8_t i = MAX_GROUP_CHANNELS - 1; i > 0; i--) {
|
||||
ChannelDetails ch;
|
||||
if (the_mesh.getChannel(i, ch) && ch.name[0] != '\0') {
|
||||
composeChannelIdx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
Serial.printf("Compose: Channel switched to %d\n", composeChannelIdx);
|
||||
drawComposeScreen();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((key == 'd' || key == 'D') && composePos == 0) {
|
||||
// Next channel
|
||||
ChannelDetails ch;
|
||||
uint8_t nextIdx = composeChannelIdx + 1;
|
||||
if (the_mesh.getChannel(nextIdx, ch) && ch.name[0] != '\0') {
|
||||
composeChannelIdx = nextIdx;
|
||||
} else {
|
||||
composeChannelIdx = 0; // Wrap to first channel
|
||||
}
|
||||
Serial.printf("Compose: Channel switched to %d\n", composeChannelIdx);
|
||||
drawComposeScreen();
|
||||
return;
|
||||
}
|
||||
|
||||
// Regular character input
|
||||
if (key >= 32 && key < 127 && composePos < 137) {
|
||||
composeBuffer[composePos++] = key;
|
||||
@@ -438,7 +473,11 @@ void handleKeyboardInput() {
|
||||
composeMode = true;
|
||||
composeBuffer[0] = '\0';
|
||||
composePos = 0;
|
||||
Serial.println("Entering compose mode");
|
||||
// If on channel screen, sync compose channel with viewed channel
|
||||
if (ui_task.isOnChannelScreen()) {
|
||||
composeChannelIdx = ui_task.getChannelScreenViewIdx();
|
||||
}
|
||||
Serial.printf("Entering compose mode, channel %d\n", composeChannelIdx);
|
||||
drawComposeScreen();
|
||||
break;
|
||||
|
||||
@@ -451,20 +490,46 @@ void handleKeyboardInput() {
|
||||
|
||||
case 'w':
|
||||
case 'W':
|
||||
case 'a':
|
||||
case 'A':
|
||||
// Navigate left/previous
|
||||
Serial.println("Nav: Previous");
|
||||
ui_task.injectKey(0xF2); // KEY_PREV
|
||||
// Navigate up/previous (scroll on channel screen)
|
||||
if (ui_task.isOnChannelScreen()) {
|
||||
ui_task.injectKey('w'); // Pass directly for channel switching
|
||||
} else {
|
||||
Serial.println("Nav: Previous");
|
||||
ui_task.injectKey(0xF2); // KEY_PREV
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 's':
|
||||
case 'S':
|
||||
// Navigate down/next (scroll on channel screen)
|
||||
if (ui_task.isOnChannelScreen()) {
|
||||
ui_task.injectKey('s'); // Pass directly for channel switching
|
||||
} else {
|
||||
Serial.println("Nav: Next");
|
||||
ui_task.injectKey(0xF1); // KEY_NEXT
|
||||
}
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
case 'A':
|
||||
// Navigate left or switch channel (on channel screen)
|
||||
if (ui_task.isOnChannelScreen()) {
|
||||
ui_task.injectKey('a'); // Pass directly for channel switching
|
||||
} else {
|
||||
Serial.println("Nav: Previous");
|
||||
ui_task.injectKey(0xF2); // KEY_PREV
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'D':
|
||||
// Navigate right/next
|
||||
Serial.println("Nav: Next");
|
||||
ui_task.injectKey(0xF1); // KEY_NEXT
|
||||
// Navigate right or switch channel (on channel screen)
|
||||
if (ui_task.isOnChannelScreen()) {
|
||||
ui_task.injectKey('d'); // Pass directly for channel switching
|
||||
} else {
|
||||
Serial.println("Nav: Next");
|
||||
ui_task.injectKey(0xF1); // KEY_NEXT
|
||||
}
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
@@ -499,7 +564,16 @@ void drawComposeScreen() {
|
||||
display.setTextSize(1);
|
||||
display.setColor(DisplayDriver::GREEN);
|
||||
display.setCursor(0, 0);
|
||||
display.print("Compose - Public Channel");
|
||||
|
||||
// Get the channel name for display
|
||||
ChannelDetails channel;
|
||||
char headerBuf[40];
|
||||
if (the_mesh.getChannel(composeChannelIdx, channel)) {
|
||||
snprintf(headerBuf, sizeof(headerBuf), "To: %s", channel.name);
|
||||
} else {
|
||||
snprintf(headerBuf, sizeof(headerBuf), "To: Channel %d", composeChannelIdx);
|
||||
}
|
||||
display.print(headerBuf);
|
||||
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
display.drawRect(0, 11, display.width(), 1);
|
||||
@@ -534,9 +608,21 @@ void drawComposeScreen() {
|
||||
display.setCursor(0, statusY);
|
||||
display.setColor(DisplayDriver::YELLOW);
|
||||
|
||||
char status[50];
|
||||
sprintf(status, "%d/137 Enter:Send Sh+Del:Cancel", composePos);
|
||||
display.print(status);
|
||||
char status[40];
|
||||
if (composePos == 0) {
|
||||
// Empty buffer - show channel switching hint
|
||||
display.print("A/D:Ch");
|
||||
sprintf(status, "Sh+Del:X");
|
||||
display.setCursor(display.width() - display.getTextWidth(status) - 2, statusY);
|
||||
display.print(status);
|
||||
} else {
|
||||
// Has text - show send/cancel hint
|
||||
sprintf(status, "%d/137 Ent:Send", composePos);
|
||||
display.print(status);
|
||||
sprintf(status, "Sh+Del:X");
|
||||
display.setCursor(display.width() - display.getTextWidth(status) - 2, statusY);
|
||||
display.print(status);
|
||||
}
|
||||
|
||||
display.endFrame();
|
||||
#endif
|
||||
@@ -545,25 +631,25 @@ void drawComposeScreen() {
|
||||
void sendComposedMessage() {
|
||||
if (composePos == 0) return;
|
||||
|
||||
MESH_DEBUG_PRINTLN("Sending message: %s", composeBuffer);
|
||||
MESH_DEBUG_PRINTLN("Sending message to channel %d: %s", composeChannelIdx, composeBuffer);
|
||||
|
||||
// Get the Public channel (index 0)
|
||||
// Get the selected channel
|
||||
ChannelDetails channel;
|
||||
if (the_mesh.getChannel(0, channel)) {
|
||||
if (the_mesh.getChannel(composeChannelIdx, channel)) {
|
||||
uint32_t timestamp = rtc_clock.getCurrentTime();
|
||||
|
||||
// Send to channel
|
||||
if (the_mesh.sendGroupMessage(timestamp, channel.channel,
|
||||
the_mesh.getNodePrefs()->node_name,
|
||||
composeBuffer, composePos)) {
|
||||
MESH_DEBUG_PRINTLN("Message sent to Public channel");
|
||||
MESH_DEBUG_PRINTLN("Message sent to channel %s", channel.name);
|
||||
ui_task.showAlert("Sent!", 1500);
|
||||
} else {
|
||||
MESH_DEBUG_PRINTLN("Failed to send message");
|
||||
ui_task.showAlert("Send failed!", 1500);
|
||||
}
|
||||
} else {
|
||||
MESH_DEBUG_PRINTLN("Could not get Public channel");
|
||||
MESH_DEBUG_PRINTLN("Could not get channel %d", composeChannelIdx);
|
||||
ui_task.showAlert("No channel!", 1500);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,19 +2,27 @@
|
||||
|
||||
#include <helpers/ui/UIScreen.h>
|
||||
#include <helpers/ui/DisplayDriver.h>
|
||||
#include <helpers/ChannelDetails.h>
|
||||
#include <MeshCore.h>
|
||||
|
||||
// Maximum messages to store in history
|
||||
#define CHANNEL_MSG_HISTORY_SIZE 20
|
||||
#define CHANNEL_MSG_TEXT_LEN 160
|
||||
|
||||
#ifndef MAX_GROUP_CHANNELS
|
||||
#define MAX_GROUP_CHANNELS 20
|
||||
#endif
|
||||
|
||||
class UITask; // Forward declaration
|
||||
class MyMesh; // Forward declaration
|
||||
extern MyMesh the_mesh;
|
||||
|
||||
class ChannelScreen : public UIScreen {
|
||||
public:
|
||||
struct ChannelMessage {
|
||||
uint32_t timestamp;
|
||||
uint8_t path_len;
|
||||
uint8_t channel_idx; // Which channel this message belongs to
|
||||
char text[CHANNEL_MSG_TEXT_LEN];
|
||||
bool valid;
|
||||
};
|
||||
@@ -28,10 +36,12 @@ private:
|
||||
int _newestIdx; // Index of newest message (circular buffer)
|
||||
int _scrollPos; // Current scroll position (0 = newest)
|
||||
int _msgsPerPage; // Messages that fit on screen
|
||||
uint8_t _viewChannelIdx; // Which channel we're currently viewing
|
||||
|
||||
public:
|
||||
ChannelScreen(UITask* task, mesh::RTCClock* rtc)
|
||||
: _task(task), _rtc(rtc), _msgCount(0), _newestIdx(-1), _scrollPos(0), _msgsPerPage(3) {
|
||||
: _task(task), _rtc(rtc), _msgCount(0), _newestIdx(-1), _scrollPos(0),
|
||||
_msgsPerPage(3), _viewChannelIdx(0) {
|
||||
// Initialize all messages as invalid
|
||||
for (int i = 0; i < CHANNEL_MSG_HISTORY_SIZE; i++) {
|
||||
_messages[i].valid = false;
|
||||
@@ -39,13 +49,14 @@ public:
|
||||
}
|
||||
|
||||
// Add a new message to the history
|
||||
void addMessage(uint8_t path_len, const char* sender, const char* text) {
|
||||
void addMessage(uint8_t channel_idx, uint8_t path_len, const char* sender, const char* text) {
|
||||
// Move to next slot in circular buffer
|
||||
_newestIdx = (_newestIdx + 1) % CHANNEL_MSG_HISTORY_SIZE;
|
||||
|
||||
ChannelMessage* msg = &_messages[_newestIdx];
|
||||
msg->timestamp = _rtc->getCurrentTime();
|
||||
msg->path_len = path_len;
|
||||
msg->channel_idx = channel_idx;
|
||||
msg->valid = true;
|
||||
|
||||
// The text already contains "Sender: message" format, just store it
|
||||
@@ -60,52 +71,84 @@ public:
|
||||
_scrollPos = 0;
|
||||
}
|
||||
|
||||
// Get count of messages for the currently viewed channel
|
||||
int getMessageCountForChannel() const {
|
||||
int count = 0;
|
||||
for (int i = 0; i < CHANNEL_MSG_HISTORY_SIZE; i++) {
|
||||
if (_messages[i].valid && _messages[i].channel_idx == _viewChannelIdx) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int getMessageCount() const { return _msgCount; }
|
||||
|
||||
uint8_t getViewChannelIdx() const { return _viewChannelIdx; }
|
||||
void setViewChannelIdx(uint8_t idx) { _viewChannelIdx = idx; _scrollPos = 0; }
|
||||
|
||||
int render(DisplayDriver& display) override {
|
||||
char tmp[32];
|
||||
char tmp[40];
|
||||
|
||||
// Header
|
||||
// Header - show current channel name
|
||||
display.setCursor(0, 0);
|
||||
display.setTextSize(1);
|
||||
display.setColor(DisplayDriver::GREEN);
|
||||
display.print("Public Channel");
|
||||
|
||||
// Message count on right
|
||||
sprintf(tmp, "[%d]", _msgCount);
|
||||
// Get channel name
|
||||
ChannelDetails channel;
|
||||
if (the_mesh.getChannel(_viewChannelIdx, channel)) {
|
||||
display.print(channel.name);
|
||||
} else {
|
||||
sprintf(tmp, "Channel %d", _viewChannelIdx);
|
||||
display.print(tmp);
|
||||
}
|
||||
|
||||
// Message count for this channel on right
|
||||
int channelMsgCount = getMessageCountForChannel();
|
||||
sprintf(tmp, "[%d]", channelMsgCount);
|
||||
display.setCursor(display.width() - display.getTextWidth(tmp) - 2, 0);
|
||||
display.print(tmp);
|
||||
|
||||
// Divider line
|
||||
display.drawRect(0, 11, display.width(), 1);
|
||||
|
||||
if (_msgCount == 0) {
|
||||
if (channelMsgCount == 0) {
|
||||
display.setCursor(0, 25);
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
display.print("No messages yet");
|
||||
display.setCursor(0, 40);
|
||||
display.print("Press C to compose");
|
||||
display.print("A/D: Switch channel");
|
||||
display.setCursor(0, 52);
|
||||
display.print("C: Compose message");
|
||||
} else {
|
||||
int lineHeight = 10;
|
||||
int headerHeight = 14;
|
||||
int footerHeight = 14;
|
||||
int availableHeight = display.height() - headerHeight - footerHeight;
|
||||
|
||||
// Calculate chars per line based on display width
|
||||
int charsPerLine = display.width() / 6;
|
||||
|
||||
int y = headerHeight;
|
||||
|
||||
// Display messages from scroll position
|
||||
int msgsDrawn = 0;
|
||||
for (int i = 0; i + _scrollPos < _msgCount && y < display.height() - footerHeight - lineHeight; i++) {
|
||||
// Calculate index in circular buffer
|
||||
int idx = _newestIdx - _scrollPos - i;
|
||||
// Build list of messages for this channel (newest first)
|
||||
int channelMsgs[CHANNEL_MSG_HISTORY_SIZE];
|
||||
int numChannelMsgs = 0;
|
||||
|
||||
for (int i = 0; i < _msgCount && numChannelMsgs < CHANNEL_MSG_HISTORY_SIZE; i++) {
|
||||
int idx = _newestIdx - i;
|
||||
while (idx < 0) idx += CHANNEL_MSG_HISTORY_SIZE;
|
||||
idx = idx % CHANNEL_MSG_HISTORY_SIZE;
|
||||
|
||||
if (!_messages[idx].valid) continue;
|
||||
|
||||
if (_messages[idx].valid && _messages[idx].channel_idx == _viewChannelIdx) {
|
||||
channelMsgs[numChannelMsgs++] = idx;
|
||||
}
|
||||
}
|
||||
|
||||
// Display messages from scroll position
|
||||
int msgsDrawn = 0;
|
||||
for (int i = _scrollPos; i < numChannelMsgs && y < display.height() - footerHeight - lineHeight; i++) {
|
||||
int idx = channelMsgs[i];
|
||||
ChannelMessage* msg = &_messages[idx];
|
||||
|
||||
// Time indicator with hop count
|
||||
@@ -125,23 +168,21 @@ public:
|
||||
display.print(tmp);
|
||||
y += lineHeight;
|
||||
|
||||
// Message text with word wrap - the text already contains "Sender: message"
|
||||
// Message text with word wrap
|
||||
display.setColor(DisplayDriver::LIGHT);
|
||||
|
||||
int textLen = strlen(msg->text);
|
||||
int pos = 0;
|
||||
int linesForThisMsg = 0;
|
||||
int maxLinesPerMsg = 3; // Allow up to 3 lines per message
|
||||
int maxLinesPerMsg = 3;
|
||||
|
||||
while (pos < textLen && linesForThisMsg < maxLinesPerMsg && y < display.height() - footerHeight - 2) {
|
||||
display.setCursor(0, y);
|
||||
|
||||
// Find how much text fits on this line
|
||||
int lineEnd = pos + charsPerLine;
|
||||
if (lineEnd >= textLen) {
|
||||
lineEnd = textLen;
|
||||
} else {
|
||||
// Try to break at a space
|
||||
int lastSpace = -1;
|
||||
for (int j = pos; j < lineEnd && j < textLen; j++) {
|
||||
if (msg->text[j] == ' ') lastSpace = j;
|
||||
@@ -149,7 +190,6 @@ public:
|
||||
if (lastSpace > pos) lineEnd = lastSpace;
|
||||
}
|
||||
|
||||
// Print this line segment
|
||||
char lineBuf[42];
|
||||
int lineLen = lineEnd - pos;
|
||||
if (lineLen > 40) lineLen = 40;
|
||||
@@ -158,66 +198,51 @@ public:
|
||||
display.print(lineBuf);
|
||||
|
||||
pos = lineEnd;
|
||||
// Skip space at start of next line
|
||||
while (pos < textLen && msg->text[pos] == ' ') pos++;
|
||||
|
||||
y += lineHeight;
|
||||
linesForThisMsg++;
|
||||
}
|
||||
|
||||
// If we truncated, show ellipsis indicator
|
||||
if (pos < textLen && linesForThisMsg >= maxLinesPerMsg) {
|
||||
// Message was truncated - could add "..." but space is tight
|
||||
}
|
||||
|
||||
y += 2; // Small gap between messages
|
||||
y += 2;
|
||||
msgsDrawn++;
|
||||
_msgsPerPage = msgsDrawn;
|
||||
}
|
||||
}
|
||||
|
||||
// Footer with scroll indicator and controls
|
||||
// Footer with controls
|
||||
int footerY = display.height() - 12;
|
||||
display.drawRect(0, footerY - 2, display.width(), 1);
|
||||
display.setCursor(0, footerY);
|
||||
display.setColor(DisplayDriver::YELLOW);
|
||||
|
||||
// Left side: Q:Exit
|
||||
display.print("Q:Exit");
|
||||
// Left side: Q:Back A/D:Ch
|
||||
display.print("Q:Back A/D:Ch");
|
||||
|
||||
// Middle: scroll position indicator
|
||||
if (_msgCount > _msgsPerPage) {
|
||||
int endMsg = _scrollPos + _msgsPerPage;
|
||||
if (endMsg > _msgCount) endMsg = _msgCount;
|
||||
sprintf(tmp, "%d-%d/%d", _scrollPos + 1, endMsg, _msgCount);
|
||||
// Center it roughly
|
||||
int midX = display.width() / 2 - 15;
|
||||
display.setCursor(midX, footerY);
|
||||
display.print(tmp);
|
||||
}
|
||||
|
||||
// Right side: controls
|
||||
sprintf(tmp, "W/S:Scrl C:New");
|
||||
display.setCursor(display.width() - display.getTextWidth(tmp) - 2, footerY);
|
||||
display.print(tmp);
|
||||
// Right side: C:New
|
||||
const char* rightText = "C:New";
|
||||
display.setCursor(display.width() - display.getTextWidth(rightText) - 2, footerY);
|
||||
display.print(rightText);
|
||||
|
||||
#if AUTO_OFF_MILLIS == 0 // e-ink
|
||||
return 5000; // Refresh every 5s
|
||||
return 5000;
|
||||
#else
|
||||
return 1000; // Refresh every 1s for time updates
|
||||
return 1000;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool handleInput(char c) override {
|
||||
// KEY_PREV (0xF2) or 'w' - scroll up (older messages)
|
||||
int channelMsgCount = getMessageCountForChannel();
|
||||
|
||||
// W or KEY_PREV - scroll up (older messages)
|
||||
if (c == 0xF2 || c == 'w' || c == 'W') {
|
||||
if (_scrollPos + _msgsPerPage < _msgCount) {
|
||||
if (_scrollPos + _msgsPerPage < channelMsgCount) {
|
||||
_scrollPos++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// KEY_NEXT (0xF1) or 's' - scroll down (newer messages)
|
||||
// S or KEY_NEXT - scroll down (newer messages)
|
||||
if (c == 0xF1 || c == 's' || c == 'S') {
|
||||
if (_scrollPos > 0) {
|
||||
_scrollPos--;
|
||||
@@ -225,8 +250,36 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// KEY_ENTER or 'c' - compose (handled by main.cpp keyboard handler)
|
||||
// 'q' - go back (handled by main.cpp keyboard handler)
|
||||
// A - previous channel
|
||||
if (c == 'a' || c == 'A') {
|
||||
if (_viewChannelIdx > 0) {
|
||||
_viewChannelIdx--;
|
||||
} else {
|
||||
// Wrap to last valid channel
|
||||
for (uint8_t i = MAX_GROUP_CHANNELS - 1; i > 0; i--) {
|
||||
ChannelDetails ch;
|
||||
if (the_mesh.getChannel(i, ch) && ch.name[0] != '\0') {
|
||||
_viewChannelIdx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_scrollPos = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// D - next channel
|
||||
if (c == 'd' || c == 'D') {
|
||||
ChannelDetails ch;
|
||||
uint8_t nextIdx = _viewChannelIdx + 1;
|
||||
if (the_mesh.getChannel(nextIdx, ch) && ch.name[0] != '\0') {
|
||||
_viewChannelIdx = nextIdx;
|
||||
} else {
|
||||
_viewChannelIdx = 0;
|
||||
}
|
||||
_scrollPos = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -235,4 +288,4 @@ public:
|
||||
void resetScroll() {
|
||||
_scrollPos = 0;
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -633,8 +633,20 @@ void UITask::newMsg(uint8_t path_len, const char* from_name, const char* text, i
|
||||
// Add to preview screen (for notifications)
|
||||
((MsgPreviewScreen *) msg_preview)->addPreview(path_len, from_name, text);
|
||||
|
||||
// Also add to channel history screen
|
||||
((ChannelScreen *) channel_screen)->addMessage(path_len, from_name, text);
|
||||
// Determine channel index by looking up the channel name
|
||||
// For channel messages, from_name is the channel name
|
||||
// For contact messages, from_name is the contact name (channel_idx = 0xFF)
|
||||
uint8_t channel_idx = 0xFF; // Default: unknown/contact message
|
||||
for (uint8_t i = 0; i < MAX_GROUP_CHANNELS; i++) {
|
||||
ChannelDetails ch;
|
||||
if (the_mesh.getChannel(i, ch) && strcmp(ch.name, from_name) == 0) {
|
||||
channel_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add to channel history screen with channel index
|
||||
((ChannelScreen *) channel_screen)->addMessage(channel_idx, path_len, from_name, text);
|
||||
|
||||
setCurrScreen(msg_preview);
|
||||
|
||||
@@ -950,4 +962,8 @@ void UITask::gotoChannelScreen() {
|
||||
}
|
||||
_auto_off = millis() + AUTO_OFF_MILLIS;
|
||||
_next_refresh = 100;
|
||||
}
|
||||
|
||||
uint8_t UITask::getChannelScreenViewIdx() const {
|
||||
return ((ChannelScreen *) channel_screen)->getViewChannelIdx();
|
||||
}
|
||||
@@ -80,6 +80,7 @@ public:
|
||||
bool hasDisplay() const { return _display != NULL; }
|
||||
bool isButtonPressed() const;
|
||||
bool isOnChannelScreen() const { return curr == channel_screen; }
|
||||
uint8_t getChannelScreenViewIdx() const;
|
||||
|
||||
void toggleBuzzer();
|
||||
bool getGPSState();
|
||||
|
||||
Reference in New Issue
Block a user