From 2610bba76d32c3061ec3eaab3fdf5c08e14e1b39 Mon Sep 17 00:00:00 2001 From: m1ngsama Date: Sun, 17 May 2026 13:10:24 +0800 Subject: [PATCH] tui: dim date divider between messages from different days (M7-4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the rendered message snapshot crosses a date boundary, insert a single dim grey divider line before the first message of each new day: ── 2026-05-14 ────────────────────────────────────────── 16:00 alice: 早! 16:01 bob: 早呀 ── 2026-05-15 ────────────────────────────────────────── 04:30 alice: 晚上一起吃饭? ... The divider also fires for the *first* visible date, so the user always knows what day the top of their viewport belongs to. Dividers and messages share the fixed msg_height budget — dividers don't push other content off the bottom. In the worst case a viewport with one message per day shows half the rows as dividers, which is the intended trade for readability. Real win for a long-lived public chat where messages span many days and timestamps alone only show HH:MM. --- src/tui.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/src/tui.c b/src/tui.c index 15dec34..0d3cb3a 100644 --- a/src/tui.c +++ b/src/tui.c @@ -364,19 +364,50 @@ void tui_render_screen(client_t *client) { } buffer_appendf(buffer, buf_size, &pos, "\033[2;37m%s\033[0m \033[K\r\n", hint); - /* Render messages from snapshot */ + /* Render messages from snapshot. Insert a dim "── YYYY-MM-DD ──" divider + * before the first message of each new day so the eye can land on dates + * when scrolling through a long-lived room. + * + * We track rows_written separately from snapshot index so dividers + * compete with messages for the fixed message-area height — they do not + * push other content off the bottom. */ + int rows_written = 0; if (msg_snapshot) { - for (int i = 0; i < snapshot_count; i++) { + char last_date[11] = ""; /* "YYYY-MM-DD" */ + for (int i = 0; i < snapshot_count && rows_written < msg_height; i++) { + char this_date[11]; + struct tm tmi; + localtime_r(&msg_snapshot[i].timestamp, &tmi); + strftime(this_date, sizeof(this_date), "%Y-%m-%d", &tmi); + + if (strcmp(this_date, last_date) != 0) { + /* Build divider: "── YYYY-MM-DD " then fill the rest with ─ */ + int prefix_w = 3 + 10 + 1; /* "── 2026-05-17 " in display columns */ + int dash_fill = render_width - prefix_w; + if (dash_fill < 0) dash_fill = 0; + + buffer_appendf(buffer, buf_size, &pos, "\033[2;37m── %s ", this_date); + for (int j = 0; j < dash_fill; j++) { + buffer_append_bytes(buffer, buf_size, &pos, "─", strlen("─")); + } + buffer_appendf(buffer, buf_size, &pos, "\033[0m\033[K\r\n"); + + memcpy(last_date, this_date, sizeof(last_date)); + rows_written++; + if (rows_written >= msg_height) break; + } + char msg_line[2048]; format_message_colored(&msg_snapshot[i], msg_line, sizeof(msg_line), render_width, client->username); buffer_appendf(buffer, buf_size, &pos, "%s\033[K\r\n", msg_line); + rows_written++; } free(msg_snapshot); } /* Fill empty lines and clear them */ - for (int i = snapshot_count; i < msg_height; i++) { + for (int i = rows_written; i < msg_height; i++) { buffer_appendf(buffer, buf_size, &pos, "\033[K\r\n"); }