mirror of
https://oauth2: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@github.com/m1ngsama/TNT.git
synced 2026-06-26 05:44:38 +08:00
Mark unread private messages in inbox
This commit is contained in:
parent
1f8fb7acf4
commit
2fca031362
7 changed files with 29 additions and 6 deletions
|
|
@ -114,6 +114,7 @@ Command output pages use `j/k`, `Ctrl+D/U`, and `g/G` for paging. `:inbox`
|
|||
shows incoming and sent private messages newest-first; press `r` to refresh it
|
||||
manually, and it refreshes when a new private message arrives while the inbox
|
||||
is open. `:reply text` and `:r text` send to the latest private-message peer.
|
||||
Unread incoming private messages are marked with `*` until `:inbox` renders.
|
||||
Private messages are per-session only and are not written to `messages.log`.
|
||||
|
||||
**Special messages (INSERT mode)**
|
||||
|
|
|
|||
|
|
@ -167,8 +167,9 @@ persisted to `messages.log` and are not included in exec `tail`, exec `dump`,
|
|||
|
||||
Each participant keeps a bounded in-memory `:inbox` for the current session.
|
||||
Recipients see incoming private messages; senders see local sent-message
|
||||
copies. `:inbox` displays newest messages first, can be refreshed with `r`,
|
||||
and refreshes automatically while open when a new private message arrives.
|
||||
copies. Unread incoming messages are marked with `*` until `:inbox` renders.
|
||||
`:inbox` displays newest messages first, can be refreshed with `r`, and
|
||||
refreshes automatically while open when a new private message arrives.
|
||||
|
||||
### `help`
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ The product path should stay short:
|
|||
reconnect.
|
||||
- `:inbox` is live enough for normal chat use: it can be refreshed with `r`
|
||||
and refreshes automatically when a new private message arrives while the
|
||||
inbox is open.
|
||||
inbox is open. Incoming unread messages are marked with `*` until the inbox
|
||||
renders them.
|
||||
- `:reply` / `:r` keeps the private-message path keyboard-short: it answers
|
||||
the latest private-message peer in the current session without retyping a
|
||||
username.
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ typedef struct {
|
|||
char to[MAX_USERNAME_LEN];
|
||||
char content[MAX_MESSAGE_LEN];
|
||||
bool outgoing;
|
||||
bool unread;
|
||||
} whisper_t;
|
||||
|
||||
typedef enum {
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ static void client_append_whisper(client_t *owner, const char *from,
|
|||
snprintf(owner->whisper_inbox[slot].content,
|
||||
sizeof(owner->whisper_inbox[slot].content), "%s", content);
|
||||
owner->whisper_inbox[slot].outgoing = outgoing;
|
||||
owner->whisper_inbox[slot].unread = count_unread;
|
||||
snprintf(owner->last_whisper_peer, sizeof(owner->last_whisper_peer), "%s",
|
||||
outgoing ? to : from);
|
||||
if (count_unread) {
|
||||
|
|
@ -142,6 +143,9 @@ static void append_inbox_output(client_t *client, char *output,
|
|||
snap_count = client->whisper_inbox_count;
|
||||
memcpy(snapshot, client->whisper_inbox,
|
||||
snap_count * sizeof(whisper_t));
|
||||
for (int i = 0; i < snap_count; i++) {
|
||||
client->whisper_inbox[i].unread = false;
|
||||
}
|
||||
client->unread_whispers = 0;
|
||||
pthread_mutex_unlock(&client->whisper_lock);
|
||||
|
||||
|
|
@ -157,6 +161,7 @@ static void append_inbox_output(client_t *client, char *output,
|
|||
for (int i = snap_count - 1; i >= 0; i--) {
|
||||
char ts[20];
|
||||
char peer[MAX_USERNAME_LEN + 16];
|
||||
const char *marker = snapshot[i].unread ? "\033[1;35m*\033[0m" : " ";
|
||||
struct tm tmi;
|
||||
localtime_r(&snapshot[i].timestamp, &tmi);
|
||||
strftime(ts, sizeof(ts), "%m-%d %H:%M", &tmi);
|
||||
|
|
@ -169,8 +174,8 @@ static void append_inbox_output(client_t *client, char *output,
|
|||
snprintf(peer, sizeof(peer), "%s", snapshot[i].from);
|
||||
}
|
||||
buffer_appendf(output, buf_size, pos,
|
||||
" \033[90m%s\033[0m \033[35m%s\033[0m: %s\n",
|
||||
ts, peer, snapshot[i].content);
|
||||
" %s \033[90m%s\033[0m \033[35m%s\033[0m: %s\n",
|
||||
marker, ts, peer, snapshot[i].content);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -273,6 +273,18 @@ else
|
|||
fi
|
||||
BOB_PID=""
|
||||
|
||||
if grep -q '.*alice.*private lifecycle second' "$STATE_DIR/bob.log" &&
|
||||
grep -q '\*.*alice.*private lifecycle second' "$STATE_DIR/bob.log" &&
|
||||
grep -q '\*.*bob.*private lifecycle reply' "$STATE_DIR/alice.log"; then
|
||||
echo "✓ unread private messages are visibly marked in inbox"
|
||||
PASS=$((PASS + 1))
|
||||
else
|
||||
echo "✗ inbox unread marker missing"
|
||||
sed -n '1,220p' "$STATE_DIR/bob.log"
|
||||
sed -n '1,260p' "$STATE_DIR/alice.log"
|
||||
FAIL=$((FAIL + 1))
|
||||
fi
|
||||
|
||||
TAIL_OUTPUT=$(ssh $SSH_EXEC_OPTS localhost "tail -n 10" 2>/dev/null || true)
|
||||
printf '%s\n' "$TAIL_OUTPUT" | grep -q 'hello lifecycle alpha' &&
|
||||
printf '%s\n' "$TAIL_OUTPUT" | grep -q 'alice2 ships lifecycle'
|
||||
|
|
|
|||
4
tnt.1
4
tnt.1
|
|
@ -253,7 +253,9 @@ The
|
|||
.B :inbox
|
||||
page shows incoming messages and local sent-message copies for the current
|
||||
session. It refreshes automatically when a new private message arrives while
|
||||
it is open. Use
|
||||
it is open. Incoming unread messages are marked with
|
||||
.B *
|
||||
until the inbox renders them. Use
|
||||
.B :reply
|
||||
or
|
||||
.B :r
|
||||
|
|
|
|||
Loading…
Reference in a new issue