Commit graph

118 commits

Author SHA1 Message Date
d3002dbfde Deepen TUI lifecycle and runtime readiness 2026-05-26 11:15:55 +08:00
33e2dc4f13 Build public release readiness foundation 2026-05-26 09:42:14 +08:00
94b602613f i18n: use shared initializer for text catalog
Some checks failed
CI / build-and-test (macos-latest) (push) Has been cancelled
CI / build-and-test (ubuntu-latest) (push) Has been cancelled
2026-05-24 20:15:12 +08:00
cd49519058 exec: use localized strings for catalog chrome 2026-05-24 16:28:56 +08:00
6c8ea56e8d help: use shared localized string helper 2026-05-24 16:22:23 +08:00
ed92aeb1e6 manual: use shared localized string helper 2026-05-24 16:15:27 +08:00
f196bfaf6d cli: use shared localized string helper 2026-05-24 16:10:44 +08:00
aa2b8b1b23 exec: use shared localized string helper 2026-05-24 15:32:20 +08:00
d1d44d0914 i18n: share localized string helper 2026-05-24 15:27:19 +08:00
46f5780057 i18n: index text catalog by language 2026-05-24 15:20:01 +08:00
f99103ede6 i18n: centralize language definitions 2026-05-24 15:10:54 +08:00
155e535b8a i18n: cycle help language with one key 2026-05-24 15:06:34 +08:00
f2942e9c9e commands: centralize usage validation in catalog 2026-05-24 15:00:41 +08:00
0aaba8e1f9 exec: centralize usage validation in catalog 2026-05-24 14:33:48 +08:00
bfaafb4b35 exec: centralize command matching in catalog 2026-05-24 13:12:47 +08:00
e911a2d469 exec: extract help text into catalog 2026-05-24 12:41:05 +08:00
5eda6ed127 tests: guard localized command placeholders 2026-05-24 12:34:23 +08:00
00fc944da8 ux: standardize private message terminology 2026-05-24 12:30:08 +08:00
01439507d5 i18n: keep command placeholders locale neutral 2026-05-24 12:26:16 +08:00
8fbd789dfb i18n: split text catalog from language parsing 2026-05-24 12:18:21 +08:00
06a10e2df8 i18n: rename help language state to ui language 2026-05-24 12:11:54 +08:00
1f1c2398b6 tui: make command output scrollable 2026-05-24 11:55:26 +08:00
57bf3cfc67 commands: centralize interactive command catalog 2026-05-24 11:25:46 +08:00
8eb311e54b i18n: restore code-based language syntax 2026-05-24 11:09:17 +08:00
a693d281f8 ux: collapse help surface around manual 2026-05-24 10:17:25 +08:00
86e1ec8e32 i18n: tolerate whitespace in language parsing 2026-05-24 08:58:51 +08:00
095491927a test: cover connection limit regressions 2026-05-23 21:38:27 +08:00
6ec86eb016 i18n: localize idle timeout notice 2026-05-23 20:10:51 +08:00
73655d0e70 i18n: localize startup cli text 2026-05-23 20:08:18 +08:00
fd6cdbf627 i18n: localize exec guidance text 2026-05-23 20:03:31 +08:00
81c3f45864 support: move guide copy into text module 2026-05-23 19:55:44 +08:00
0cf8ac6759 i18n: centralize command guidance text 2026-05-23 19:45:53 +08:00
4fb531771b help: move bilingual help text into module 2026-05-23 19:41:38 +08:00
8009887be9 i18n: localize welcome screen 2026-05-23 19:33:21 +08:00
07e47e65c8 i18n: module system event messages 2026-05-23 19:30:11 +08:00
1d8fcea3fa i18n: localize title bar status 2026-05-23 19:21:01 +08:00
aca68824ac i18n: centralize command output text 2026-05-23 19:11:29 +08:00
9159586716 i18n: localize command usage errors 2026-05-23 18:36:44 +08:00
4c8ef99880 i18n: localize modal screen chrome 2026-05-23 18:32:26 +08:00
22ab85acef i18n: localize common command outputs 2026-05-23 18:29:30 +08:00
92123d208d i18n: localize help screen chrome 2026-05-23 18:25:30 +08:00
f535b928d1 i18n: localize command mode guidance 2026-05-23 18:17:53 +08:00
2e69283e5c i18n: add session language command 2026-05-23 18:10:54 +08:00
0c27976763 i18n: select interactive language from locale 2026-05-23 18:06:39 +08:00
36dbe8d549 tui: guide first-time users 2026-05-21 12:36:06 +08:00
69ddcd2d95 ssh: use non-deprecated host key generation api 2026-05-21 12:20:41 +08:00
169ba1a150 tui: preserve ansi styling when truncating output 2026-05-21 12:12:14 +08:00
67d21ad0e9 tui: improve history browsing and support guide 2026-05-21 11:57:59 +08:00
87d6572156 chat: whisper inbox with :inbox view + ✉ unread chip (UX-12)
Whispers used to flash on the recipient's terminal and disappear with
the next redraw.  No history, no record, no signal if you weren't
looking.

Now whispers are stored per-recipient in a bounded inbox (16 slots,
FIFO eviction):

  typedef struct { time_t timestamp; char from[]; char content[]; } whisper_t;
  whisper_t whisper_inbox[16];
  int       whisper_inbox_count;
  _Atomic int unread_whispers;

Sender side (:msg / :w):
  - resolves target as before
  - pushes the whisper into target->whisper_inbox under target->io_lock
    (so two simultaneous senders to the same recipient don't tear the
    ring)
  - bumps target->unread_whispers atomically
  - sends a single \a bell + triggers redraw_pending
  - no longer writes whisper text directly to the channel (which used
    to get clobbered by the next redraw)

Recipient side:
  - new :inbox command in COMMAND mode prints the snapshot under
    io_lock, in M7 chat-list style:

      悄悄话 · whispers  · 3
        05-17 13:42  alice: 一会儿要不要喝咖啡
        ...

  - viewing :inbox resets unread_whispers to 0

Title bar (extends UX-11):
  - bright magenta "✉ N" chip alongside the yellow "★ N" mention chip
  - same priority / degradation rules as ★

Whispers remain private — they're never broadcast to the room and
never persisted to messages.log.  The inbox lives only in client_t,
so disconnecting drops it.
2026-05-17 14:35:16 +08:00
ddcecbea81 tui: persistent @mention unread counter in title bar (UX-11)
The bell + brief yellow highlight on the chat line meant that if you
weren't looking at the screen the moment someone @-mentioned you, you
had no way to know.

Now the title bar carries a sticky chip:

    tester · 在线 3 · NORMAL  ★ 2                ? 帮助

- bright yellow "★ N" appears whenever client->unread_mentions > 0
- count is bumped atomically in notify_mentions() for each target
- cleared automatically when the user returns to attention:
  * pressing 'i' in NORMAL to re-enter INSERT mode
  * pressing 'G' in NORMAL to jump to the live tail
- never dropped by the narrow-terminal degradation (UX-6) unless
  every other optional chip has already been shed — it's the highest
  priority signal in the bar

Counter is _Atomic int so the cross-thread bump in notify_mentions
doesn't tear against the local thread's reads / resets.
2026-05-17 14:27:46 +08:00