mirror of
https://github.com/pelgraine/Meck.git
synced 2026-05-07 13:54:52 +02:00
t-echo lite - stripped emoji in contacts and last heard, changed recent adverts list to default 4
This commit is contained in:
@@ -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:");
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user