t-echo lite - stripped emoji in contacts and last heard, changed recent adverts list to default 4

This commit is contained in:
pelgraine
2026-04-22 12:54:16 +10:00
parent f461777214
commit 36976e0029
4 changed files with 112 additions and 110 deletions
+102
View File
@@ -154,6 +154,10 @@
#define AUTO_ADD_ROOM_SERVER (1 << 3) // 0x08 - auto-add Room Server (ADV_TYPE_ROOM)
#define AUTO_ADD_SENSOR (1 << 4) // 0x10 - auto-add Sensor (ADV_TYPE_SENSOR)
// All type bits combined (excludes overwrite flag)
#define AUTO_ADD_ALL_TYPES (AUTO_ADD_CHAT | AUTO_ADD_REPEATER | \
AUTO_ADD_ROOM_SERVER | AUTO_ADD_SENSOR)
void MyMesh::writeOKFrame() {
uint8_t buf[1];
buf[0] = RESP_CODE_OK;
@@ -2550,6 +2554,20 @@ void MyMesh::checkCLIRescueCmd() {
Serial.printf(" apn: %s\n", modemManager.getAPN());
Serial.printf(" imei: %s\n", modemManager.getIMEI());
#endif
// Contact auto-add
{
const char* mode = (_prefs.manual_add_contacts & 1) == 0 ? "auto" :
(_prefs.autoadd_config & AUTO_ADD_ALL_TYPES) == 0 ? "manual" : "custom";
Serial.printf(" contacts: %s", mode);
if ((_prefs.manual_add_contacts & 1) != 0 && (_prefs.autoadd_config & AUTO_ADD_ALL_TYPES) != 0) {
Serial.printf(" [%s%s%s%s]",
(_prefs.autoadd_config & AUTO_ADD_CHAT) ? "C" : "",
(_prefs.autoadd_config & AUTO_ADD_REPEATER) ? "R" : "",
(_prefs.autoadd_config & AUTO_ADD_ROOM_SERVER) ? "S" : "",
(_prefs.autoadd_config & AUTO_ADD_SENSOR) ? "N" : "");
}
Serial.printf(" maxhops:%d\n", _prefs.autoadd_max_hops);
}
// Detect current preset
bool presetFound = false;
for (int i = 0; i < (int)NUM_RADIO_PRESETS; i++) {
@@ -2590,6 +2608,30 @@ void MyMesh::checkCLIRescueCmd() {
}
}
if (!chFound) Serial.println(" (none)");
// --- Contact auto-add settings ---
} else if (strcmp(key, "contact.mode") == 0) {
if ((_prefs.manual_add_contacts & 1) == 0) {
Serial.println(" > auto");
} else if ((_prefs.autoadd_config & AUTO_ADD_ALL_TYPES) == 0) {
Serial.println(" > manual");
} else {
Serial.println(" > custom");
}
} else if (strcmp(key, "contact.autoadd") == 0) {
Serial.printf(" > chat:%s rptr:%s room:%s sensor:%s overwrite:%s\n",
(_prefs.autoadd_config & AUTO_ADD_CHAT) ? "on" : "off",
(_prefs.autoadd_config & AUTO_ADD_REPEATER) ? "on" : "off",
(_prefs.autoadd_config & AUTO_ADD_ROOM_SERVER) ? "on" : "off",
(_prefs.autoadd_config & AUTO_ADD_SENSOR) ? "on" : "off",
(_prefs.autoadd_config & AUTO_ADD_OVERWRITE_OLDEST) ? "on" : "off");
} else if (strcmp(key, "contact.maxhops") == 0) {
if (_prefs.autoadd_max_hops == 0) {
Serial.println(" > 0 (no limit)");
} else {
Serial.printf(" > %d\n", _prefs.autoadd_max_hops);
}
} else {
Serial.printf(" Error: unknown key '%s' (try 'help')\n", key);
}
@@ -3049,6 +3091,60 @@ void MyMesh::checkCLIRescueCmd() {
Serial.println(" Error: backlight not available on this device");
#endif
// --- Contact auto-add settings ---
} else if (memcmp(config, "contact.mode ", 13) == 0) {
const char* val = &config[13];
if (strcmp(val, "auto") == 0) {
_prefs.manual_add_contacts &= ~1;
savePrefs();
Serial.println(" > auto-add all");
} else if (strcmp(val, "custom") == 0) {
_prefs.manual_add_contacts |= 1;
if ((_prefs.autoadd_config & AUTO_ADD_ALL_TYPES) == 0) {
_prefs.autoadd_config |= AUTO_ADD_ALL_TYPES;
}
savePrefs();
Serial.println(" > custom (use contact.autoadd to configure)");
} else if (strcmp(val, "manual") == 0) {
_prefs.manual_add_contacts |= 1;
_prefs.autoadd_config &= ~AUTO_ADD_ALL_TYPES;
savePrefs();
Serial.println(" > manual only (no auto-add)");
} else if (strcmp(val, "repeater-only") == 0) {
_prefs.manual_add_contacts |= 1;
_prefs.autoadd_config = (_prefs.autoadd_config & AUTO_ADD_OVERWRITE_OLDEST) | AUTO_ADD_REPEATER;
savePrefs();
Serial.println(" > auto-add repeaters only");
} else {
Serial.println(" Error: auto|custom|manual|repeater-only");
}
} else if (memcmp(config, "contact.autoadd ", 16) == 0) {
const char* rest = &config[16];
uint8_t bit = 0;
const char* val = NULL;
if (memcmp(rest, "chat ", 5) == 0) { bit = AUTO_ADD_CHAT; val = &rest[5]; }
else if (memcmp(rest, "repeater ", 9) == 0) { bit = AUTO_ADD_REPEATER; val = &rest[9]; }
else if (memcmp(rest, "room ", 5) == 0) { bit = AUTO_ADD_ROOM_SERVER; val = &rest[5]; }
else if (memcmp(rest, "sensor ", 7) == 0) { bit = AUTO_ADD_SENSOR; val = &rest[7]; }
else if (memcmp(rest, "overwrite ", 10) == 0) { bit = AUTO_ADD_OVERWRITE_OLDEST; val = &rest[10]; }
if (bit && val) {
if (strcmp(val, "on") == 0) { _prefs.autoadd_config |= bit; savePrefs(); Serial.println(" > OK"); }
else if (strcmp(val, "off") == 0) { _prefs.autoadd_config &= ~bit; savePrefs(); Serial.println(" > OK"); }
else { Serial.println(" Error: on|off"); }
} else {
Serial.println(" Error: chat|repeater|room|sensor|overwrite on|off");
}
} else if (memcmp(config, "contact.maxhops ", 16) == 0) {
int h = atoi(&config[16]);
if (h >= 0 && h <= 64) {
_prefs.autoadd_max_hops = (uint8_t)h;
savePrefs();
Serial.printf(" > maxhops = %d%s\n", h, h == 0 ? " (no limit)" : "");
} else {
Serial.println(" Error: 0-64 (0=no limit)");
}
} else {
Serial.printf(" Error: unknown setting '%s' (try 'help')\n", config);
}
@@ -3146,6 +3242,12 @@ void MyMesh::checkCLIRescueCmd() {
Serial.println(" set region none Clear default region (unscoped)");
Serial.println(" get channel.scope <i> Show scope for channel i");
Serial.println(" set channel.scope <i> <name|none>");
Serial.println("");
Serial.println(" Contact auto-add:");
Serial.println(" contact.mode auto|custom|manual|repeater-only");
Serial.println(" contact.autoadd Show type toggles");
Serial.println(" contact.autoadd <type> on|off chat|repeater|room|sensor|overwrite");
Serial.println(" contact.maxhops <0-64> Max hops for auto-add (0=no limit)");
#ifdef HAS_4G_MODEM
Serial.println("");
Serial.println(" 4G modem:");
+1 -104
View File
@@ -1100,98 +1100,7 @@ public:
}
};
class MsgPreviewScreen : public UIScreen {
UITask* _task;
mesh::RTCClock* _rtc;
struct MsgEntry {
uint32_t timestamp;
char origin[62];
char msg[78];
};
#define MAX_UNREAD_MSGS 32
int num_unread;
MsgEntry unread[MAX_UNREAD_MSGS];
public:
MsgPreviewScreen(UITask* task, mesh::RTCClock* rtc) : _task(task), _rtc(rtc) { num_unread = 0; }
void addPreview(uint8_t path_len, const char* from_name, const char* msg) {
if (num_unread >= MAX_UNREAD_MSGS) return; // full
auto p = &unread[num_unread++];
p->timestamp = _rtc->getCurrentTime();
if (path_len == 0xFF) {
sprintf(p->origin, "(D) %s:", from_name);
} else {
sprintf(p->origin, "(%d) %s:", (uint32_t) path_len, from_name);
}
StrHelper::strncpy(p->msg, msg, sizeof(p->msg));
}
int render(DisplayDriver& display) override {
char tmp[16];
display.setCursor(0, 0);
display.setTextSize(1);
display.setColor(DisplayDriver::GREEN);
sprintf(tmp, "Unread: %d", num_unread);
display.print(tmp);
auto p = &unread[0];
int secs = _rtc->getCurrentTime() - p->timestamp;
if (secs < 60) {
sprintf(tmp, "%ds", secs);
} else if (secs < 60*60) {
sprintf(tmp, "%dm", secs / 60);
} else {
sprintf(tmp, "%dh", secs / (60*60));
}
display.setCursor(display.width() - display.getTextWidth(tmp) - 2, 0);
display.print(tmp);
display.drawRect(0, 11, display.width(), 1); // horiz line
display.setCursor(0, 14);
display.setColor(DisplayDriver::YELLOW);
char filtered_origin[sizeof(p->origin)];
display.translateUTF8ToBlocks(filtered_origin, p->origin, sizeof(filtered_origin));
display.print(filtered_origin);
display.setCursor(0, 25);
display.setColor(DisplayDriver::LIGHT);
char filtered_msg[sizeof(p->msg)];
display.translateUTF8ToBlocks(filtered_msg, p->msg, sizeof(filtered_msg));
display.printWordWrap(filtered_msg, display.width());
#if AUTO_OFF_MILLIS==0 // probably e-ink
return 10000; // 10 s
#else
return 1000; // next render after 1000 ms
#endif
}
bool handleInput(char c) override {
if (c == KEY_NEXT || c == KEY_RIGHT) {
num_unread--;
if (num_unread == 0) {
_task->gotoHomeScreen();
} else {
// delete first/curr item from unread queue
for (int i = 0; i < num_unread; i++) {
unread[i] = unread[i + 1];
}
}
return true;
}
if (c == KEY_ENTER) {
num_unread = 0; // clear unread queue
_task->gotoHomeScreen();
return true;
}
return false;
}
};
// MsgPreviewScreen removed — all platforms now use toast alerts for new messages
// ==========================================================================
// Lock Screen — T5S3 and T-Deck Pro
@@ -1338,7 +1247,6 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no
splash = new SplashScreen(this);
home = new HomeScreen(this, &rtc_clock, sensors, node_prefs);
msg_preview = new MsgPreviewScreen(this, &rtc_clock);
channel_screen = new ChannelScreen(this, &rtc_clock);
((ChannelScreen*)channel_screen)->setDMUnreadPtr(_dmUnread);
channel_picker_screen = new ChannelPickerScreen(this);
@@ -1460,9 +1368,6 @@ switch(t){
void UITask::msgRead(int msgcount) {
_msgcount = msgcount;
if (msgcount == 0 && curr == msg_preview) {
gotoHomeScreen();
}
}
void UITask::newMsg(uint8_t path_len, const char* from_name, const char* text, int msgcount,
@@ -1487,9 +1392,6 @@ void UITask::newMsg(uint8_t path_len, const char* from_name, const char* text, i
_dedup[_dedupIdx].millis = now;
_dedupIdx = (_dedupIdx + 1) % MSG_DEDUP_SIZE;
// Add to preview screen (for notifications on non-keyboard devices)
((MsgPreviewScreen *) msg_preview)->addPreview(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)
@@ -1552,7 +1454,6 @@ void UITask::newMsg(uint8_t path_len, const char* from_name, const char* text, i
}
}
#if defined(LilyGo_TDeck_Pro) || defined(LilyGo_T5S3_EPaper_Pro)
// Don't interrupt user with popup - just show brief notification
// Messages are stored in channel history, accessible via tile/key
// Suppress toasts for room server messages (bulk sync would spam toasts)
@@ -1565,10 +1466,6 @@ void UITask::newMsg(uint8_t path_len, const char* from_name, const char* text, i
if (isOnChannelPickerScreen()) {
forceRefresh();
}
#else
// Other devices: Show full preview screen (legacy behavior, skip room sync)
if (!isRoomMsg) setCurrScreen(msg_preview);
#endif
if (_display != NULL) {
if (!_display->isOn() && !hasConnection()) {
+9 -4
View File
@@ -47,7 +47,12 @@ public:
print(str);
}
// convert UTF-8 characters to displayable block characters for compatibility
// Strip non-ASCII characters (emoji, etc.) from a UTF-8 string.
// Placeholder glyphs aren't safe across our fonts: GFXfonts (FreeSans)
// silently drop anything outside first..last, while the Adafruit built-in
// 5x7 font remaps c>=0xB0 by +1 so \xDB prints as ▄. Stripping the
// codepoint is the only behaviour that renders consistently across
// FastEPD (T5S3) and GxEPD (T-Deck Pro, T-Echo Lite, etc.) builds.
virtual void translateUTF8ToBlocks(char* dest, const char* src, size_t dest_size) {
size_t j = 0;
for (size_t i = 0; src[i] != 0 && j < dest_size - 1; i++) {
@@ -55,9 +60,9 @@ public:
if (c >= 32 && c <= 126) {
dest[j++] = c; // ASCII printable
} else if (c >= 0x80) {
dest[j++] = '\xDB'; // CP437 full block █
while (src[i+1] && (src[i+1] & 0xC0) == 0x80)
i++; // skip UTF-8 continuation bytes
// Skip the whole UTF-8 codepoint (lead byte + continuation bytes)
while (src[i+1] && (src[i+1] & 0xC0) == 0x80)
i++;
}
}
dest[j] = 0;
@@ -88,7 +88,6 @@ build_flags =
; -D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=64
-D MECK_CARDKB
-D UI_RECENT_LIST_SIZE=9
-D UI_SENSORS_PAGE=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
@@ -118,7 +117,6 @@ build_flags =
-D CHANNEL_MSG_HISTORY_SIZE=150
-D OFFLINE_QUEUE_SIZE=1
-D MECK_CARDKB
-D UI_RECENT_LIST_SIZE=9
-D UI_SENSORS_PAGE=1
-D AUTO_SHUTDOWN_MILLIVOLTS=2800
build_src_filter = ${lilygo_techo_lite_meck.build_src_filter}