@antzsoft/chat-core 1.1.0 → 1.1.1

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.
@@ -457,6 +457,48 @@ section.sec>h2:hover{color:#fff}
457
457
  </div>
458
458
  </div>
459
459
 
460
+ <div class="wn-item" id="wn-109-7">
461
+ <div class="wn-item-header" onclick="toggleItem('wn-109-7')">
462
+ <span class="wn-tag fix">Fix</span>
463
+ <span class="wn-item-title">Removed user could re-enter conversation room via <code>join_room</code></span>
464
+ <span class="wn-chevron-sm">▾</span>
465
+ </div>
466
+ <div class="wn-item-body">
467
+ <p>The socket access check for <code>join_room</code> was missing the <code>isActive</code> participant check. A removed user whose client re-emitted <code>joinRoom</code> (e.g. on reconnect or by navigating back to the chat screen) would be silently re-admitted to the conversation room and continue receiving <code>new_message</code> events. The check now requires <code>isActive: true</code>, consistent with the write-access check.</p>
468
+ <p><strong>Action required:</strong> None. Server-side fix only.</p>
469
+ </div>
470
+ </div>
471
+
472
+ <div class="wn-item" id="wn-109-8">
473
+ <div class="wn-item-header" onclick="toggleItem('wn-109-8')">
474
+ <span class="wn-tag fix">Fix</span>
475
+ <span class="wn-item-title">Re-added user's conversation missing from list when they had previously deleted it</span>
476
+ <span class="wn-chevron-sm">▾</span>
477
+ </div>
478
+ <div class="wn-item-body">
479
+ <p>When a user deleted a conversation (<code>isHidden: true</code>), was then removed from the group, and later re-added by an admin, the conversation never reappeared in their list. The reactivation path now resets <code>isHidden</code> to <code>false</code> alongside <code>isActive</code>.</p>
480
+ <p>Additionally, the server now server-side joins the re-added user's active sockets into the conversation room and emits <code>conversation_created</code> to their personal room so the conversation appears immediately — no reconnect or <code>joinRoom</code> call needed.</p>
481
+ <p><strong>Action required:</strong> None. Server-side fix only. Existing <code>conversation_created → joinRoom</code> listeners remain safe (idempotent).</p>
482
+ </div>
483
+ </div>
484
+
485
+ <div class="wn-item" id="wn-109-9">
486
+ <div class="wn-item-header" onclick="toggleItem('wn-109-9')">
487
+ <span class="wn-tag new">New</span>
488
+ <span class="wn-item-title">Optional <code>role</code> parameter on <code>addParticipants</code></span>
489
+ <span class="wn-chevron-sm">▾</span>
490
+ </div>
491
+ <div class="wn-item-body">
492
+ <p><code>addParticipants</code> now accepts an optional <code>role</code> parameter (<code>'admin' | 'member'</code>, default <code>'member'</code>). This applies to both newly added users and previously removed users being re-added. A former admin who is re-added without specifying <code>role: 'admin'</code> will come back as a member — their previous role is never silently restored.</p>
493
+ <pre><code><span class="cm">// Default — added as member (backward compatible)</span>
494
+ <span class="kw">await</span> conversationsApi.<span class="fn">addParticipants</span>(conversationId, [<span class="str">'user-3'</span>]);
495
+
496
+ <span class="cm">// Explicitly add as admin</span>
497
+ <span class="kw">await</span> conversationsApi.<span class="fn">addParticipants</span>(conversationId, [<span class="str">'user-3'</span>], <span class="str">'admin'</span>);</code></pre>
498
+ <p><strong>Action required:</strong> None for existing code — the parameter is optional and defaults to <code>'member'</code>. No call sites need updating unless you want to add members as admins directly.</p>
499
+ </div>
500
+ </div>
501
+
460
502
  </div>
461
503
  </div>
462
504
 
@@ -1536,7 +1578,8 @@ chatClient.<span class="fn">disconnect</span>();
1536
1578
 
1537
1579
  <span class="cm">// Participants</span>
1538
1580
  <span class="kw">const</span> members = <span class="kw">await</span> conversationsApi.<span class="fn">getMembers</span>(conversationId);
1539
- <span class="kw">await</span> conversationsApi.<span class="fn">addParticipants</span>(conversationId, [<span class="str">'user-3'</span>]);
1581
+ <span class="kw">await</span> conversationsApi.<span class="fn">addParticipants</span>(conversationId, [<span class="str">'user-3'</span>]); <span class="cm">// added as member (default)</span>
1582
+ <span class="kw">await</span> conversationsApi.<span class="fn">addParticipants</span>(conversationId, [<span class="str">'user-3'</span>], <span class="str">'admin'</span>); <span class="cm">// added as admin</span>
1540
1583
  <span class="kw">await</span> conversationsApi.<span class="fn">removeParticipant</span>(conversationId, <span class="str">'user-2'</span>);
1541
1584
  <span class="kw">await</span> conversationsApi.<span class="fn">updateParticipantRole</span>(conversationId, <span class="str">'user-1'</span>, <span class="str">'admin'</span>);
1542
1585
 
@@ -1582,16 +1625,15 @@ chatClient.<span class="fn">disconnect</span>();
1582
1625
 
1583
1626
  <h4>When to call <code>joinRoom</code></h4>
1584
1627
  <p>
1585
- There is only one real use case — when the <strong>user is added to a conversation while their socket is already connected</strong>
1586
- (either someone created a new group and added them, or they were added to an existing group at runtime).
1587
- The server does <strong>not</strong> auto-join the user's socket to the new room — it only emits <code>conversation_created</code>
1588
- to the user's personal room. Without calling <code>joinRoom</code>, the socket will not receive any
1589
- <code>new_message</code>, <code>typing_indicator</code>, or other room events for that conversation.
1628
+ When the <strong>user is added to a conversation while their socket is already connected</strong>, the server now automatically joins their active sockets into the new room and emits <code>conversation_created</code> to their personal room. No <code>joinRoom</code> call is required — <code>new_message</code>, <code>typing_indicator</code>, and all other room events will arrive immediately.
1629
+ </p>
1630
+ <p>
1631
+ Calling <code>joinRoom</code> on <code>conversation_created</code> is still safe (idempotent) and can be kept for defensive compatibility, but is no longer necessary:
1590
1632
  </p>
1591
1633
 
1592
- <pre><code><span class="cm">// Fires when you're added to a new or existing conversation at runtime</span>
1634
+ <pre><code><span class="cm">// Optional server already handles this automatically</span>
1593
1635
  client.socket.<span class="fn">on</span>(<span class="str">'conversation_created'</span>, (conv) => {
1594
- client.socket.emit.<span class="fn">joinRoom</span>(conv.id);
1636
+ client.socket.emit.<span class="fn">joinRoom</span>(conv.id); <span class="cm">// safe no-op if already in room</span>
1595
1637
  });</code></pre>
1596
1638
 
1597
1639
  <p><code>leaveRoom</code> is only needed if you want to intentionally stop receiving events for a room the user is still a member of (e.g. archiving client-side). It is not needed when navigating away from a screen.</p>
@@ -1622,9 +1664,9 @@ client.socket.<span class="fn">on</span>(<span class="str">'new_message'</span>,
1622
1664
  });
1623
1665
  });
1624
1666
 
1625
- <span class="cm">// Only case where joinRoom is needed</span>
1667
+ <span class="cm">// Optional server auto-joins the room, but this is safe to keep</span>
1626
1668
  client.socket.<span class="fn">on</span>(<span class="str">'conversation_created'</span>, (conv) => {
1627
- client.socket.emit.<span class="fn">joinRoom</span>(conv.id);
1669
+ client.socket.emit.<span class="fn">joinRoom</span>(conv.id); <span class="cm">// idempotent no-op if already joined</span>
1628
1670
  });</code></pre>
1629
1671
  </div>
1630
1672
  <div data-p="node">
@@ -1635,6 +1677,7 @@ client.socket.<span class="fn">on</span>(<span class="str">'new_message'</span>,
1635
1677
  client.socket.emit.<span class="fn">markRead</span>(message.conversationId, message.id);
1636
1678
  });
1637
1679
 
1680
+ <span class="cm">// Optional — server auto-joins the room, but safe to keep</span>
1638
1681
  client.socket.<span class="fn">on</span>(<span class="str">'conversation_created'</span>, (conv) => {
1639
1682
  client.socket.emit.<span class="fn">joinRoom</span>(conv.id);
1640
1683
  });</code></pre>
@@ -1644,7 +1687,7 @@ client.socket.<span class="fn">on</span>(<span class="str">'conversation_created
1644
1687
  <strong>Summary of rules:</strong>
1645
1688
  <ul>
1646
1689
  <li>All existing rooms are auto-joined on socket connect — no <code>joinRoom</code> needed on screen open.</li>
1647
- <li>Call <code>joinRoom</code> only after a <code>conversation_created</code> event.</li>
1690
+ <li>When added to a conversation at runtime, the server now auto-joins the socket room and emits <code>conversation_created</code>. No <code>joinRoom</code> call needed, but safe to keep for compatibility.</li>
1648
1691
  <li>Add the <code>new_message</code> listener once at app root, never per screen.</li>
1649
1692
  <li>Use <code>message.conversationId</code> to route to the right view or badge update.</li>
1650
1693
  <li>Track <code>activeConversationId</code> to decide whether to increment the unread count.</li>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antzsoft/chat-core",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
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",