feat(ui-lvgl): AM / PM beside the big clock on a 12-hour clock

It was a muted prefix on the date line, easy to miss. clockFace() -- the
digits and a small AM / PM on their baseline -- is shared by Home and both
lock screens (the PIN card showed no AM / PM at all). The date loses the
prefix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-09-28 15:19:10 +02:00
co-authored by Claude Opus 5.5
parent ed5c903c3b
commit 350393436a
4 changed files with 41 additions and 19 deletions
@@ -321,7 +321,7 @@ void UITask::messageMenu(int idx) {
fmtClock(clk, sizeof(clk), ti, _prefs, true);
if (clockBehind(now, ts)) { // the clock isn't set yet: the date instead of an age
char date[32];
fmtDate(date, sizeof(date), ti, nullptr);
fmtDate(date, sizeof(date), ti);
snprintf(when, sizeof(when), "%s %s", date, clk);
} else snprintf(when, sizeof(when), "%s - %s ago", clk, age);
} else {
@@ -192,7 +192,7 @@ void UITask::lockScreen() {
lv_obj_set_flex_flow(top, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(top, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_pad_column(top, 14, 0);
s_lock_clock = label(top, "--:--", THEME_FONT_LARGE, theme::TEXT);
s_lock_clock = clockFace(top, THEME_FONT_LARGE, THEME_FONT_SMALL);
s_lock_unread = label(top, "", THEME_FONT_BODY, theme::ACCENT);
s_lock_date = nullptr;
_pin_entry[0] = '\0';
@@ -202,7 +202,7 @@ void UITask::lockScreen() {
refreshLock();
return;
}
s_lock_clock = label(s_lock, "--:--", THEME_FONT_CLOCK, theme::TEXT);
s_lock_clock = clockFace(s_lock, THEME_FONT_CLOCK, THEME_FONT_TITLE);
s_lock_date = label(s_lock, "", THEME_FONT_BODY, theme::TEXT_MUTED);
s_lock_unread = label(s_lock, "", THEME_FONT_BODY, theme::ACCENT);
lv_obj_set_style_pad_top(s_lock_unread, 8, 0);
@@ -296,10 +296,9 @@ void UITask::refreshLock() {
if (!s_lock) return;
struct tm ti;
if (localTime(_prefs, ti)) {
char clk[12], date[48];
fmtClock(clk, sizeof(clk), ti, _prefs, false, true);
fmtDate(date, sizeof(date), ti, _prefs);
lv_label_set_text(s_lock_clock, clk);
clockFaceSet(s_lock_clock, &ti, _prefs);
char date[48];
fmtDate(date, sizeof(date), ti);
if (s_lock_date) lv_label_set_text(s_lock_date, date);
}
int unread = unreadTotal();
@@ -249,7 +249,7 @@ void UITask::buildHomeClock(lv_obj_t* box) {
lv_obj_add_flag(clk, LV_OBJ_FLAG_CLICKABLE);
lv_obj_set_style_opa(clk, LV_OPA_70, LV_STATE_PRESSED);
lv_obj_add_event_cb(clk, onClockTap, LV_EVENT_CLICKED, NULL);
_home_clock = label(clk, "--:--", THEME_FONT_CLOCK, theme::TEXT);
_home_clock = clockFace(clk, THEME_FONT_CLOCK, THEME_FONT_TITLE);
_home_date = label(clk, "", THEME_FONT_BODY, theme::TEXT_MUTED);
label(clk, the_mesh.getNodeName(), THEME_FONT_BODY, theme::ACCENT);
@@ -574,14 +574,13 @@ void UITask::refreshHome() {
}
if (!_home_clock) return;
struct tm ti;
if (localTime(_prefs, ti)) {
char clk[12], date[48];
fmtClock(clk, sizeof(clk), ti, _prefs, false, true);
fmtDate(date, sizeof(date), ti, _prefs);
lv_label_set_text(_home_clock, clk);
bool known = localTime(_prefs, ti);
clockFaceSet(_home_clock, known ? &ti : nullptr, _prefs);
if (known) {
char date[48];
fmtDate(date, sizeof(date), ti);
lv_label_set_text(_home_date, date);
} else {
lv_label_set_text(_home_clock, "--:--");
lv_label_set_text(_home_date, "time not synced");
}
for (int i = 0; i < FIELDS; i++) {
+29 -5
View File
@@ -704,14 +704,38 @@ static void fmtClock(char* b, size_t n, const struct tm& ti, const NodePrefs* p,
snprintf(b, n, "%02d:%02d%s", ti.tm_hour, ti.tm_min, sec);
}
}
// "Thu 25 Sep 2026" ("PM Thu 25 Sep 2026" on a 12-hour clock, whose big
// digits have no room for it).
static void fmtDate(char* b, size_t n, const struct tm& ti, const NodePrefs* p) {
// "Thu 25 Sep 2026".
static void fmtDate(char* b, size_t n, const struct tm& ti) {
static const char* DOW[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
static const char* MON[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
snprintf(b, n, "%s%s %d %s %d", (p && p->clock_12h) ? (ti.tm_hour < 12 ? "AM " : "PM ") : "",
DOW[ti.tm_wday], ti.tm_mday, MON[ti.tm_mon], ti.tm_year + 1900);
snprintf(b, n, "%s %d %s %d", DOW[ti.tm_wday], ti.tm_mday, MON[ti.tm_mon], ti.tm_year + 1900);
}
// A big clock (Home, the lock screen): the digits and, on a 12-hour clock,
// AM / PM beside them in `small`, on the digits' baseline. clockFaceSet()
// once a second; "--:--" until the time is known.
static lv_obj_t* clockFace(lv_obj_t* parent, const lv_font_t* big, const lv_font_t* small) {
lv_obj_t* f = flexBox(parent, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(f, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_END, LV_FLEX_ALIGN_END);
lv_obj_set_style_pad_column(f, 4, 0);
label(f, "--:--", big, theme::TEXT);
lv_obj_t* ap = label(f, "", small, theme::TEXT_MUTED);
lv_obj_set_style_pad_bottom(ap, big->base_line - small->base_line, 0);
lv_obj_add_flag(ap, LV_OBJ_FLAG_HIDDEN);
return f;
}
static void clockFaceSet(lv_obj_t* f, const struct tm* ti, const NodePrefs* p) {
lv_obj_t* ap = lv_obj_get_child(f, 1);
char clk[12] = "--:--";
if (ti) fmtClock(clk, sizeof(clk), *ti, p, false, true);
lv_label_set_text(lv_obj_get_child(f, 0), clk);
bool h12 = ti && p && p->clock_12h;
if (h12) lv_label_set_text(ap, ti->tm_hour < 12 ? "AM" : "PM");
if (h12 != !lv_obj_has_flag(ap, LV_OBJ_FLAG_HIDDEN)) {
if (h12) lv_obj_remove_flag(ap, LV_OBJ_FLAG_HIDDEN);
else lv_obj_add_flag(ap, LV_OBJ_FLAG_HIDDEN);
}
}
// A message's age ("12s" / "5m" / "3h" / "2d"). After a restart the clock runs
// from the build date until GPS or the app sets it, so messages restored from