@unicitylabs/sphere-sdk 0.6.1 → 0.6.2

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.
@@ -63,6 +63,17 @@ interface GroupChatModuleConfig {
63
63
  /** Max reconnect attempts (default: 5) */
64
64
  maxReconnectAttempts?: number;
65
65
  }
66
+ interface GroupMessagesPage {
67
+ messages: GroupMessageData[];
68
+ hasMore: boolean;
69
+ oldestTimestamp: number | null;
70
+ }
71
+ interface GetGroupMessagesPageOptions {
72
+ /** Max messages to return (default: 20) */
73
+ limit?: number;
74
+ /** Return messages older than this timestamp */
75
+ before?: number;
76
+ }
66
77
  interface CreateGroupOptions {
67
78
  name: string;
68
79
  description?: string;
@@ -762,7 +773,7 @@ interface TrackedAddress extends TrackedAddressEntry {
762
773
  /** Primary nametag (from nametag cache, without @ prefix) */
763
774
  readonly nametag?: string;
764
775
  }
765
- type SphereEventType = 'transfer:incoming' | 'transfer:confirmed' | 'transfer:failed' | 'payment_request:incoming' | 'payment_request:accepted' | 'payment_request:rejected' | 'payment_request:paid' | 'payment_request:response' | 'message:dm' | 'message:read' | 'message:typing' | 'composing:started' | 'message:broadcast' | 'sync:started' | 'sync:completed' | 'sync:provider' | 'sync:error' | 'connection:changed' | 'nametag:registered' | 'nametag:recovered' | 'identity:changed' | 'address:activated' | 'address:hidden' | 'address:unhidden' | 'sync:remote-update' | 'groupchat:message' | 'groupchat:joined' | 'groupchat:left' | 'groupchat:kicked' | 'groupchat:group_deleted' | 'groupchat:updated' | 'groupchat:connection' | 'history:updated';
776
+ type SphereEventType = 'transfer:incoming' | 'transfer:confirmed' | 'transfer:failed' | 'payment_request:incoming' | 'payment_request:accepted' | 'payment_request:rejected' | 'payment_request:paid' | 'payment_request:response' | 'message:dm' | 'message:read' | 'message:typing' | 'composing:started' | 'message:broadcast' | 'sync:started' | 'sync:completed' | 'sync:provider' | 'sync:error' | 'connection:changed' | 'nametag:registered' | 'nametag:recovered' | 'identity:changed' | 'address:activated' | 'address:hidden' | 'address:unhidden' | 'sync:remote-update' | 'groupchat:message' | 'groupchat:joined' | 'groupchat:left' | 'groupchat:kicked' | 'groupchat:group_deleted' | 'groupchat:updated' | 'groupchat:connection' | 'groupchat:ready' | 'communications:ready' | 'history:updated';
766
777
  interface SphereEventMap {
767
778
  'transfer:incoming': IncomingTransfer;
768
779
  'transfer:confirmed': TransferResult;
@@ -862,6 +873,12 @@ interface SphereEventMap {
862
873
  'groupchat:connection': {
863
874
  connected: boolean;
864
875
  };
876
+ 'groupchat:ready': {
877
+ groupCount: number;
878
+ };
879
+ 'communications:ready': {
880
+ conversationCount: number;
881
+ };
865
882
  'history:updated': TransactionHistoryEntry;
866
883
  }
867
884
  type SphereEventHandler<T extends SphereEventType> = (data: SphereEventMap[T]) => void;
@@ -1389,6 +1406,14 @@ interface TransportProvider extends BaseProvider {
1389
1406
  * and resolves after EOSE (End Of Stored Events).
1390
1407
  */
1391
1408
  fetchPendingEvents?(): Promise<void>;
1409
+ /**
1410
+ * Register a handler to be called when the chat subscription receives EOSE
1411
+ * (End Of Stored Events), indicating that historical DMs have been delivered.
1412
+ * The handler fires at most once per subscription lifecycle.
1413
+ *
1414
+ * @returns Unsubscribe function
1415
+ */
1416
+ onChatReady?(handler: () => void): () => void;
1392
1417
  }
1393
1418
  /**
1394
1419
  * Payload for sending instant split bundles
@@ -2951,6 +2976,7 @@ declare class GroupChatModule {
2951
2976
  getGroups(): GroupData[];
2952
2977
  getGroup(groupId: string): GroupData | null;
2953
2978
  getMessages(groupId: string): GroupMessageData[];
2979
+ getMessagesPage(groupId: string, options?: GetGroupMessagesPageOptions): GroupMessagesPage;
2954
2980
  getMembers(groupId: string): GroupMemberData[];
2955
2981
  getMember(groupId: string, pubkey: string): GroupMemberData | null;
2956
2982
  getTotalUnreadCount(): number;
@@ -63,6 +63,17 @@ interface GroupChatModuleConfig {
63
63
  /** Max reconnect attempts (default: 5) */
64
64
  maxReconnectAttempts?: number;
65
65
  }
66
+ interface GroupMessagesPage {
67
+ messages: GroupMessageData[];
68
+ hasMore: boolean;
69
+ oldestTimestamp: number | null;
70
+ }
71
+ interface GetGroupMessagesPageOptions {
72
+ /** Max messages to return (default: 20) */
73
+ limit?: number;
74
+ /** Return messages older than this timestamp */
75
+ before?: number;
76
+ }
66
77
  interface CreateGroupOptions {
67
78
  name: string;
68
79
  description?: string;
@@ -762,7 +773,7 @@ interface TrackedAddress extends TrackedAddressEntry {
762
773
  /** Primary nametag (from nametag cache, without @ prefix) */
763
774
  readonly nametag?: string;
764
775
  }
765
- type SphereEventType = 'transfer:incoming' | 'transfer:confirmed' | 'transfer:failed' | 'payment_request:incoming' | 'payment_request:accepted' | 'payment_request:rejected' | 'payment_request:paid' | 'payment_request:response' | 'message:dm' | 'message:read' | 'message:typing' | 'composing:started' | 'message:broadcast' | 'sync:started' | 'sync:completed' | 'sync:provider' | 'sync:error' | 'connection:changed' | 'nametag:registered' | 'nametag:recovered' | 'identity:changed' | 'address:activated' | 'address:hidden' | 'address:unhidden' | 'sync:remote-update' | 'groupchat:message' | 'groupchat:joined' | 'groupchat:left' | 'groupchat:kicked' | 'groupchat:group_deleted' | 'groupchat:updated' | 'groupchat:connection' | 'history:updated';
776
+ type SphereEventType = 'transfer:incoming' | 'transfer:confirmed' | 'transfer:failed' | 'payment_request:incoming' | 'payment_request:accepted' | 'payment_request:rejected' | 'payment_request:paid' | 'payment_request:response' | 'message:dm' | 'message:read' | 'message:typing' | 'composing:started' | 'message:broadcast' | 'sync:started' | 'sync:completed' | 'sync:provider' | 'sync:error' | 'connection:changed' | 'nametag:registered' | 'nametag:recovered' | 'identity:changed' | 'address:activated' | 'address:hidden' | 'address:unhidden' | 'sync:remote-update' | 'groupchat:message' | 'groupchat:joined' | 'groupchat:left' | 'groupchat:kicked' | 'groupchat:group_deleted' | 'groupchat:updated' | 'groupchat:connection' | 'groupchat:ready' | 'communications:ready' | 'history:updated';
766
777
  interface SphereEventMap {
767
778
  'transfer:incoming': IncomingTransfer;
768
779
  'transfer:confirmed': TransferResult;
@@ -862,6 +873,12 @@ interface SphereEventMap {
862
873
  'groupchat:connection': {
863
874
  connected: boolean;
864
875
  };
876
+ 'groupchat:ready': {
877
+ groupCount: number;
878
+ };
879
+ 'communications:ready': {
880
+ conversationCount: number;
881
+ };
865
882
  'history:updated': TransactionHistoryEntry;
866
883
  }
867
884
  type SphereEventHandler<T extends SphereEventType> = (data: SphereEventMap[T]) => void;
@@ -1389,6 +1406,14 @@ interface TransportProvider extends BaseProvider {
1389
1406
  * and resolves after EOSE (End Of Stored Events).
1390
1407
  */
1391
1408
  fetchPendingEvents?(): Promise<void>;
1409
+ /**
1410
+ * Register a handler to be called when the chat subscription receives EOSE
1411
+ * (End Of Stored Events), indicating that historical DMs have been delivered.
1412
+ * The handler fires at most once per subscription lifecycle.
1413
+ *
1414
+ * @returns Unsubscribe function
1415
+ */
1416
+ onChatReady?(handler: () => void): () => void;
1392
1417
  }
1393
1418
  /**
1394
1419
  * Payload for sending instant split bundles
@@ -2951,6 +2976,7 @@ declare class GroupChatModule {
2951
2976
  getGroups(): GroupData[];
2952
2977
  getGroup(groupId: string): GroupData | null;
2953
2978
  getMessages(groupId: string): GroupMessageData[];
2979
+ getMessagesPage(groupId: string, options?: GetGroupMessagesPageOptions): GroupMessagesPage;
2954
2980
  getMembers(groupId: string): GroupMemberData[];
2955
2981
  getMember(groupId: string, pubkey: string): GroupMemberData | null;
2956
2982
  getTotalUnreadCount(): number;
@@ -8299,6 +8299,12 @@ var CommunicationsModule = class {
8299
8299
  this.unsubscribeComposing = deps.transport.onComposing?.((indicator) => {
8300
8300
  this.handleComposingIndicator(indicator);
8301
8301
  }) ?? null;
8302
+ if (deps.transport.onChatReady) {
8303
+ deps.transport.onChatReady(() => {
8304
+ const conversations = this.getConversations();
8305
+ deps.emitEvent("communications:ready", { conversationCount: conversations.size });
8306
+ });
8307
+ }
8302
8308
  }
8303
8309
  /**
8304
8310
  * Load messages from storage.
@@ -8945,6 +8951,7 @@ var GroupChatModule = class {
8945
8951
  await this.subscribeToJoinedGroups();
8946
8952
  }
8947
8953
  this.deps.emitEvent("groupchat:connection", { connected: true });
8954
+ this.deps.emitEvent("groupchat:ready", { groupCount: this.groups.size });
8948
8955
  } catch (error) {
8949
8956
  logger.error("GroupChat", "Failed to connect to relays", error);
8950
8957
  this.deps.emitEvent("groupchat:connection", { connected: false });
@@ -9579,6 +9586,19 @@ var GroupChatModule = class {
9579
9586
  getMessages(groupId) {
9580
9587
  return (this.messages.get(groupId) || []).sort((a, b) => a.timestamp - b.timestamp);
9581
9588
  }
9589
+ getMessagesPage(groupId, options) {
9590
+ const limit = options?.limit ?? 20;
9591
+ const before = options?.before ?? Infinity;
9592
+ const groupMessages = this.messages.get(groupId) ?? [];
9593
+ const filtered = groupMessages.filter((m) => m.timestamp < before).sort((a, b) => b.timestamp - a.timestamp);
9594
+ const page = filtered.slice(0, limit);
9595
+ return {
9596
+ messages: page.reverse(),
9597
+ // chronological order
9598
+ hasMore: filtered.length > limit,
9599
+ oldestTimestamp: page.length > 0 ? page[0].timestamp : null
9600
+ };
9601
+ }
9582
9602
  getMembers(groupId) {
9583
9603
  return (this.members.get(groupId) || []).sort((a, b) => a.joinedAt - b.joinedAt);
9584
9604
  }