mirror of
https://oauth2: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@github.com/m1ngsama/TNT.git
synced 2026-06-26 05:34:39 +08:00
tui: byte-budget gauge in INSERT input line (UX-4)
The chat input is bounded at MAX_MESSAGE_LEN (1024 bytes). Past that
limit the input loop silently drops further keystrokes — which is fine
mechanically but leaves the user typing into the void.
tui_render_input() now appends a right-aligned gauge to the input line
once the buffer crosses 80 % full:
› some long message that goes on and on … 187 B (dim grey)
› this one is almost at the limit … 12 B (bold yellow > 95 %)
Below 80 % the prompt is unchanged. The gauge eats display width from
the available content area so the existing horizontal scroll-truncate
logic keeps working — long input still scrolls cleanly past the gauge.
(Paste handling, which is the other half of the long-input UX gap,
lands separately as UX-13.)
This commit is contained in:
parent
b1353d904b
commit
c66491d4f8
1 changed files with 38 additions and 6 deletions
44
src/tui.c
44
src/tui.c
|
|
@ -467,7 +467,11 @@ void tui_render_screen(client_t *client) {
|
|||
free(buffer);
|
||||
}
|
||||
|
||||
/* Render the input line */
|
||||
/* Render the input line.
|
||||
*
|
||||
* Format: "› <input>" with optional right-aligned length indicator
|
||||
* once the buffer is past 80% full. The indicator turns bold-yellow
|
||||
* past 95% so users can see further keystrokes will be dropped. */
|
||||
void tui_render_input(client_t *client, const char *input) {
|
||||
if (!client || !client->connected) return;
|
||||
|
||||
|
|
@ -478,7 +482,25 @@ void tui_render_input(client_t *client, const char *input) {
|
|||
|
||||
char buffer[2048];
|
||||
int input_width = utf8_string_width(input);
|
||||
int avail = rw - 3;
|
||||
size_t input_bytes = strlen(input);
|
||||
|
||||
/* Decide whether to show the length gauge and how loud. */
|
||||
int gauge_width = 0;
|
||||
char gauge[64] = "";
|
||||
if (input_bytes > (MAX_MESSAGE_LEN * 8) / 10) { /* > 80 % */
|
||||
size_t remaining = (input_bytes < MAX_MESSAGE_LEN)
|
||||
? (MAX_MESSAGE_LEN - 1 - input_bytes) : 0;
|
||||
const char *color =
|
||||
(input_bytes > (MAX_MESSAGE_LEN * 95) / 100) ? "\033[1;33m"
|
||||
: "\033[2;37m";
|
||||
snprintf(gauge, sizeof(gauge), "%s… %zu B\033[0m", color, remaining);
|
||||
/* Plain-text width: " … 1234 B" → 4 + len(digits) + 2 */
|
||||
char digits[12];
|
||||
snprintf(digits, sizeof(digits), "%zu", remaining);
|
||||
gauge_width = 4 + (int)strlen(digits) + 2; /* "… ", digits, " B" + leading space */
|
||||
}
|
||||
|
||||
int avail = rw - 3 - (gauge_width > 0 ? gauge_width + 1 : 0);
|
||||
if (avail < 1) avail = 1;
|
||||
|
||||
/* Truncate from start if too long */
|
||||
|
|
@ -501,10 +523,20 @@ void tui_render_input(client_t *client, const char *input) {
|
|||
strncpy(display, p, sizeof(display) - 1);
|
||||
}
|
||||
|
||||
/* Move to input line and clear it, then write input */
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
"\033[%d;1H" ANSI_CLEAR_LINE "\033[2;37m›\033[0m %s",
|
||||
rh, display);
|
||||
/* Compose: cursor to input row, clear line, "› " prompt, input.
|
||||
* If a gauge is active, append it right-aligned. */
|
||||
if (gauge_width > 0) {
|
||||
int displayed_width = utf8_string_width(display);
|
||||
int padding = rw - 2 - displayed_width - gauge_width;
|
||||
if (padding < 1) padding = 1;
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
"\033[%d;1H" ANSI_CLEAR_LINE "\033[2;37m›\033[0m %s%*s%s",
|
||||
rh, display, padding, "", gauge);
|
||||
} else {
|
||||
snprintf(buffer, sizeof(buffer),
|
||||
"\033[%d;1H" ANSI_CLEAR_LINE "\033[2;37m›\033[0m %s",
|
||||
rh, display);
|
||||
}
|
||||
|
||||
client_send(client, buffer, strlen(buffer));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue