feat: add 12h/24h clock format setting (default 24h)

Toggle in Settings > Display > Format. In 12h mode the clock shows
h:mm AM/PM (or h:mm:ss AM/PM with seconds, no space before AM/PM).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-05-21 21:04:43 +02:00
co-authored by Claude Sonnet 4.6
parent e0312c2b6b
commit 38cd0fada3
4 changed files with 31 additions and 5 deletions
+4
View File
@@ -285,6 +285,9 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no
file.read((uint8_t *)_prefs.dm_melody, sizeof(_prefs.dm_melody)); file.read((uint8_t *)_prefs.dm_melody, sizeof(_prefs.dm_melody));
if (file.available()) { if (file.available()) {
file.read((uint8_t *)&_prefs.auto_lock, sizeof(_prefs.auto_lock)); file.read((uint8_t *)&_prefs.auto_lock, sizeof(_prefs.auto_lock));
if (file.available()) {
file.read((uint8_t *)&_prefs.clock_12h, sizeof(_prefs.clock_12h));
}
} }
} }
} }
@@ -375,6 +378,7 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_
file.write((uint8_t *)&_prefs.ch_notif_melody_2, sizeof(_prefs.ch_notif_melody_2)); file.write((uint8_t *)&_prefs.ch_notif_melody_2, sizeof(_prefs.ch_notif_melody_2));
file.write((uint8_t *)_prefs.dm_melody, sizeof(_prefs.dm_melody)); file.write((uint8_t *)_prefs.dm_melody, sizeof(_prefs.dm_melody));
file.write((uint8_t *)&_prefs.auto_lock, sizeof(_prefs.auto_lock)); file.write((uint8_t *)&_prefs.auto_lock, sizeof(_prefs.auto_lock));
file.write((uint8_t *)&_prefs.clock_12h, sizeof(_prefs.clock_12h));
file.close(); file.close();
} }
+1
View File
@@ -57,6 +57,7 @@ struct NodePrefs { // persisted to file
char bot_reply_dm[140]; // auto-reply text for DM char bot_reply_dm[140]; // auto-reply text for DM
char bot_reply_ch[140]; // auto-reply text for channel char bot_reply_ch[140]; // auto-reply text for channel
uint8_t clock_hide_seconds; // 0=show HH:MM:SS/refresh 1s (default), 1=hide/refresh 60s uint8_t clock_hide_seconds; // 0=show HH:MM:SS/refresh 1s (default), 1=hide/refresh 60s
uint8_t clock_12h; // 0=24h (default), 1=12h with AM/PM
uint8_t buzzer_auto; // 0=manual (default), 1=auto-mute when BT connected uint8_t buzzer_auto; // 0=manual (default), 1=auto-mute when BT connected
struct DmNotifEntry { uint8_t prefix[4]; uint8_t state; }; // state: 0=default,1=muted,2=force-on struct DmNotifEntry { uint8_t prefix[4]; uint8_t state; }; // state: 0=default,1=muted,2=force-on
static const int DM_NOTIF_TABLE_MAX = 16; static const int DM_NOTIF_TABLE_MAX = 16;
@@ -13,6 +13,7 @@ class SettingsScreen : public UIScreen {
AUTO_LOCK, AUTO_LOCK,
BATT_DISPLAY, BATT_DISPLAY,
CLOCK_SECONDS, CLOCK_SECONDS,
CLOCK_FORMAT,
// Sound section // Sound section
SECTION_SOUND, SECTION_SOUND,
BUZZER, BUZZER,
@@ -311,6 +312,10 @@ class SettingsScreen : public UIScreen {
display.print("Seconds"); display.print("Seconds");
display.setCursor(VAL_X, y); display.setCursor(VAL_X, y);
display.print((p && p->clock_hide_seconds) ? "OFF" : "ON"); display.print((p && p->clock_hide_seconds) ? "OFF" : "ON");
} else if (item == CLOCK_FORMAT) {
display.print("Format");
display.setCursor(VAL_X, y);
display.print((p && p->clock_12h) ? "12h" : "24h");
} else if (item == DM_FILTER) { } else if (item == DM_FILTER) {
display.print("DM"); display.print("DM");
display.setCursor(VAL_X, y); display.setCursor(VAL_X, y);
@@ -496,6 +501,11 @@ public:
_dirty = true; _dirty = true;
return true; return true;
} }
if (_selected == CLOCK_FORMAT && p && (left || right || enter)) {
p->clock_12h ^= 1;
_dirty = true;
return true;
}
if (_selected == DM_FILTER && p && (left || right || enter)) { if (_selected == DM_FILTER && p && (left || right || enter)) {
p->dm_show_all = p->dm_show_all ? 0 : 1; p->dm_show_all = p->dm_show_all ? 0 : 1;
_dirty = true; _dirty = true;
+16 -5
View File
@@ -389,10 +389,16 @@ public:
display.setColor(DisplayDriver::LIGHT); display.setColor(DisplayDriver::LIGHT);
display.setTextSize(2); display.setTextSize(2);
bool show_sec = !_node_prefs || !_node_prefs->clock_hide_seconds; bool show_sec = !_node_prefs || !_node_prefs->clock_hide_seconds;
if (show_sec) bool h12 = _node_prefs && _node_prefs->clock_12h;
sprintf(buf, "%02d:%02d:%02d", ti->tm_hour, ti->tm_min, ti->tm_sec); if (h12) {
else int h = ti->tm_hour % 12; if (h == 0) h = 12;
sprintf(buf, "%02d:%02d", ti->tm_hour, ti->tm_min); const char* ap = ti->tm_hour < 12 ? "AM" : "PM";
if (show_sec) sprintf(buf, "%d:%02d:%02d%s", h, ti->tm_min, ti->tm_sec, ap);
else sprintf(buf, "%d:%02d %s", h, ti->tm_min, ap);
} else {
if (show_sec) sprintf(buf, "%02d:%02d:%02d", ti->tm_hour, ti->tm_min, ti->tm_sec);
else sprintf(buf, "%02d:%02d", ti->tm_hour, ti->tm_min);
}
display.drawTextCentered(display.width() / 2, 0, buf); display.drawTextCentered(display.width() / 2, 0, buf);
display.setTextSize(1); display.setTextSize(1);
@@ -1334,7 +1340,12 @@ void UITask::loop() {
struct tm* ti = gmtime(&t); struct tm* ti = gmtime(&t);
char buf[12]; char buf[12];
_display->setTextSize(2); _display->setTextSize(2);
sprintf(buf, "%02d:%02d", ti->tm_hour, ti->tm_min); if (_node_prefs && _node_prefs->clock_12h) {
int h = ti->tm_hour % 12; if (h == 0) h = 12;
sprintf(buf, "%d:%02d %s", h, ti->tm_min, ti->tm_hour < 12 ? "AM" : "PM");
} else {
sprintf(buf, "%02d:%02d", ti->tm_hour, ti->tm_min);
}
_display->drawTextCentered(_display->width() / 2, 8, buf); _display->drawTextCentered(_display->width() / 2, 8, buf);
_display->setTextSize(1); _display->setTextSize(1);
static const char* wd[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; static const char* wd[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};