@antzsoft/chat-core 1.2.7 → 1.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -150,6 +150,7 @@ interface Message {
150
150
  pinnedBy?: string;
151
151
  pinnedAt?: string;
152
152
  uploadProgress?: number;
153
+ seq?: number;
153
154
  sentAt: string;
154
155
  createdAt: string;
155
156
  sender?: User;
@@ -389,6 +390,8 @@ interface MessageAckEvent {
389
390
  tempId: string;
390
391
  messageId: string;
391
392
  status: MessageStatus;
393
+ /** Present when server supports seq — monotonic counter for this conversation. */
394
+ seq?: number;
392
395
  }
393
396
  interface MessageDeliveredEvent {
394
397
  messageId: string;
@@ -458,6 +461,10 @@ interface CrossConversationSyncResponse {
458
461
  }
459
462
  interface ConversationSyncResponse {
460
463
  syncedAt: string;
464
+ /** Present when server supports seq-based sync. Use as afterSeq in next call. */
465
+ nextSeq?: number;
466
+ /** True when more pages are available — call again with updated afterSeq. */
467
+ hasMore?: boolean;
461
468
  messages: Message[];
462
469
  deletedForMe: SyncDeletedForMe[];
463
470
  reactions: SyncReactions;
@@ -150,6 +150,7 @@ interface Message {
150
150
  pinnedBy?: string;
151
151
  pinnedAt?: string;
152
152
  uploadProgress?: number;
153
+ seq?: number;
153
154
  sentAt: string;
154
155
  createdAt: string;
155
156
  sender?: User;
@@ -389,6 +390,8 @@ interface MessageAckEvent {
389
390
  tempId: string;
390
391
  messageId: string;
391
392
  status: MessageStatus;
393
+ /** Present when server supports seq — monotonic counter for this conversation. */
394
+ seq?: number;
392
395
  }
393
396
  interface MessageDeliveredEvent {
394
397
  messageId: string;
@@ -458,6 +461,10 @@ interface CrossConversationSyncResponse {
458
461
  }
459
462
  interface ConversationSyncResponse {
460
463
  syncedAt: string;
464
+ /** Present when server supports seq-based sync. Use as afterSeq in next call. */
465
+ nextSeq?: number;
466
+ /** True when more pages are available — call again with updated afterSeq. */
467
+ hasMore?: boolean;
461
468
  messages: Message[];
462
469
  deletedForMe: SyncDeletedForMe[];
463
470
  reactions: SyncReactions;
@@ -155,7 +155,7 @@ section.sec>h2:hover{color:#fff}
155
155
 
156
156
  <div class="section-label">What's New</div>
157
157
  <ul>
158
- <li><a href="#whats-new">v1.2.7 Release Notes</a></li>
158
+ <li><a href="#whats-new">v1.2.8 Release Notes</a></li>
159
159
  </ul>
160
160
 
161
161
  <div class="section-label">Getting Started</div>
@@ -250,12 +250,75 @@ section.sec>h2:hover{color:#fff}
250
250
  <h2>What's New</h2>
251
251
  <p style="color:var(--muted);font-size:13px;margin-bottom:20px">Version history and release notes. Click a version to expand.</p>
252
252
 
253
- <!-- ── v1.2.7 (current) ── -->
253
+ <!-- ── v1.2.8 (current) ── -->
254
+ <div class="wn-version open" id="wn-128">
255
+ <div class="wn-header" onclick="toggleVersion('wn-128')">
256
+ <div class="wn-title">
257
+ <span class="wn-ver">v1.2.8</span>
258
+ <span class="wn-badge current">Current</span>
259
+ <span class="wn-date">June 2026</span>
260
+ </div>
261
+ <span class="wn-chevron">▲</span>
262
+ </div>
263
+ <div class="wn-body">
264
+
265
+ <div class="wn-item" id="wn-128-delivery-status">
266
+ <div class="wn-item-header" onclick="toggleItem('wn-128-delivery-status')">
267
+ <span class="wn-tag new">New</span>
268
+ <span class="wn-item-title"><code>deliveryStatus</code> on <code>Conversation.lastMessage</code> — tick state in conversation list</span>
269
+ <span class="wn-chevron-sm">▾</span>
270
+ </div>
271
+ <div class="wn-item-body">
272
+ <p>The conversation list API (<code>GET /conversations</code>) and the <code>conversation_updated</code> socket event now include <code>deliveryStatus</code> on the <code>lastMessage</code> object. This is the tick state of the last message as seen by the sender — stored directly on the conversation document and kept current by the server on every read and delivery event.</p>
273
+
274
+ <table>
275
+ <thead><tr><th>Value</th><th>Meaning</th></tr></thead>
276
+ <tbody>
277
+ <tr><td><code>'sent'</code></td><td>Message written to the server — not yet delivered to all recipients</td></tr>
278
+ <tr><td><code>'delivered'</code></td><td>All active recipients have received the message on at least one device</td></tr>
279
+ <tr><td><code>'read'</code></td><td>All active recipients have opened and read the message</td></tr>
280
+ </tbody>
281
+ </table>
282
+
283
+ <p><strong>Usage — rendering tick marks in a conversation list (custom UI):</strong></p>
284
+ <pre><code><span class="kw">const</span> { data: conversations } = <span class="kw">await</span> conversationsApi.<span class="fn">list</span>();
285
+
286
+ <span class="kw">for</span> (<span class="kw">const</span> conv <span class="kw">of</span> conversations) {
287
+ <span class="kw">const</span> lm = conv.lastMessage;
288
+ <span class="kw">if</span> (!lm) <span class="kw">continue</span>;
289
+
290
+ <span class="cm">// Only show ticks on messages sent by the current user</span>
291
+ <span class="kw">const</span> isMyMessage = lm.senderId === currentUserId;
292
+ <span class="kw">if</span> (!isMyMessage) <span class="kw">continue</span>;
293
+
294
+ <span class="cm">// deliveryStatus: 'sent' | 'delivered' | 'read'</span>
295
+ <span class="fn">renderTick</span>(conv.id, lm.deliveryStatus ?? <span class="str">'sent'</span>);
296
+ }</code></pre>
297
+
298
+ <p><strong>Live updates</strong> — the existing <code>read_receipt</code> socket event continues to carry real-time tick updates while a conversation room is open. <code>deliveryStatus</code> on <code>lastMessage</code> is the cold-start / list-load source of truth; socket events keep it live after that.</p>
299
+
300
+ <p><strong>Server-side changes:</strong></p>
301
+ <ul>
302
+ <li><code>lastMessage.deliveryStatus</code> is set to <code>'sent'</code> when a new message is written</li>
303
+ <li>Promoted to <code>'delivered'</code> when all active recipients have a delivery record for that message</li>
304
+ <li>Promoted to <code>'read'</code> when <code>fullyReadMessageIds</code> includes the last message (i.e. all active recipients have read it)</li>
305
+ <li>Status never demotes — a conditional update ensures it only advances: <code>sent → delivered → read</code></li>
306
+ </ul>
307
+
308
+ <p><strong>Migration</strong> — existing conversations are backfilled automatically by <code>005_backfill_last_message_delivery_status</code> on first deploy. It queries <code>chat_message_reads</code> and <code>chat_message_deliveries</code> to compute the correct status for each conversation's current last message. No manual step required.</p>
309
+
310
+ <p><strong>Backward compatibility</strong> — <code>deliveryStatus</code> defaults to <code>'sent'</code> when absent (<code>lm.deliveryStatus ?? 'sent'</code>). The field was already defined as optional on the <code>Message</code> type — it is now also populated on the <code>lastMessage</code> snapshot. No breaking changes.</p>
311
+ </div>
312
+ </div>
313
+
314
+ </div>
315
+ </div><!-- /.wn-version -->
316
+
317
+ <!-- ── v1.2.7 ── -->
254
318
  <div class="wn-version open" id="wn-127">
255
319
  <div class="wn-header" onclick="toggleVersion('wn-127')">
256
320
  <div class="wn-title">
257
321
  <span class="wn-ver">v1.2.7</span>
258
- <span class="wn-badge current">Current</span>
259
322
  <span class="wn-date">June 2026</span>
260
323
  </div>
261
324
  <span class="wn-chevron">▲</span>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antzsoft/chat-core",
3
- "version": "1.2.7",
3
+ "version": "1.2.9",
4
4
  "description": "Platform-agnostic core for Antz Chat — API, socket, stores, types. Works in browser, React Native (Expo or bare), and Node.js.",
5
5
  "author": "Antz",
6
6
  "license": "MIT",