@snapie/chat-client 0.1.0
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.
- package/README.md +313 -0
- package/dist/client-Bztyx_3e.d.mts +220 -0
- package/dist/client-Bztyx_3e.d.ts +220 -0
- package/dist/index.d.mts +22 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +472 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +467 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react.d.mts +56 -0
- package/dist/react.d.ts +56 -0
- package/dist/react.js +124 -0
- package/dist/react.js.map +1 -0
- package/dist/react.mjs +118 -0
- package/dist/react.mjs.map +1 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
# @snapie/chat-client
|
|
2
|
+
|
|
3
|
+
Hive-authenticated chat SDK for [Snapie](https://snapie.io). Supports DMs, channels, groups, real-time subscriptions (polling + FCM), and typing indicators.
|
|
4
|
+
|
|
5
|
+
Works in any JavaScript/TypeScript environment. React hooks available as a separate entry point.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @snapie/chat-client
|
|
13
|
+
# or
|
|
14
|
+
pnpm add @snapie/chat-client
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import { ChatClient } from '@snapie/chat-client';
|
|
23
|
+
|
|
24
|
+
const client = new ChatClient({ baseUrl: 'https://snapie.io' });
|
|
25
|
+
|
|
26
|
+
// Authenticate with a Hive account (posting key challenge/response)
|
|
27
|
+
await client.authenticate(username, async (challenge) => {
|
|
28
|
+
// Use Hive Keychain, Aioha, or any signing library
|
|
29
|
+
return await keychain.signBuffer(username, challenge, 'Posting');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Get all conversations
|
|
33
|
+
const conversations = await client.getConversations();
|
|
34
|
+
|
|
35
|
+
// Subscribe to live messages (polls every 15s, merges new ones)
|
|
36
|
+
const unsub = client.subscribeToMessages(conversationId, 'dm', (messages) => {
|
|
37
|
+
console.log(messages);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Send a message
|
|
41
|
+
await client.sendMessage(conversationId, 'dm', 'Hello from 3speak!');
|
|
42
|
+
|
|
43
|
+
// Stop subscribing
|
|
44
|
+
unsub();
|
|
45
|
+
|
|
46
|
+
// Clean up everything when done
|
|
47
|
+
client.destroy();
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Configuration
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
const client = new ChatClient({
|
|
56
|
+
baseUrl: 'https://snapie.io', // required — Snapie instance URL
|
|
57
|
+
pollInterval: 15000, // optional — ms between polls (default: 15000)
|
|
58
|
+
storage: customStorage, // optional — custom StorageAdapter (see below)
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Custom storage (React Native / Node)
|
|
63
|
+
|
|
64
|
+
By default the client uses `localStorage`. Override it with any object that implements `getItem`, `setItem`, `removeItem`:
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
68
|
+
|
|
69
|
+
const client = new ChatClient({
|
|
70
|
+
baseUrl: 'https://snapie.io',
|
|
71
|
+
storage: {
|
|
72
|
+
getItem: (key) => AsyncStorage.getItem(key), // note: sync wrapper needed
|
|
73
|
+
setItem: (key, val) => AsyncStorage.setItem(key, val),
|
|
74
|
+
removeItem: (key) => AsyncStorage.removeItem(key),
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Authentication
|
|
82
|
+
|
|
83
|
+
The auth flow uses Hive's posting key signature — no passwords, no OAuth.
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
// 1. Authenticate
|
|
87
|
+
await client.authenticate(username, async (challenge) => {
|
|
88
|
+
return await signingLibrary.sign(challenge);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// 2. Check status
|
|
92
|
+
client.isAuthenticated(); // boolean
|
|
93
|
+
client.getUsername(); // string | null
|
|
94
|
+
|
|
95
|
+
// 3. Logout
|
|
96
|
+
client.logout();
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Conversations
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
// List all conversations (DMs + channels + groups)
|
|
105
|
+
const conversations = await client.getConversations();
|
|
106
|
+
// Conversation { _id, name, type: 'dm'|'channel'|'group', lastMessage, unread, ... }
|
|
107
|
+
|
|
108
|
+
// Open or resume a DM with another Hive user
|
|
109
|
+
const conv = await client.openDm('alice');
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Messages
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// Fetch messages (one-time)
|
|
118
|
+
const { messages } = await client.getMessages(conversationId, 'dm');
|
|
119
|
+
const { messages } = await client.getMessages(channelId, 'channel', { limit: 50 });
|
|
120
|
+
|
|
121
|
+
// Send
|
|
122
|
+
const { message } = await client.sendMessage(conversationId, 'dm', 'Hey!');
|
|
123
|
+
|
|
124
|
+
// Reply
|
|
125
|
+
const { message } = await client.sendMessage(conversationId, 'dm', 'Got it', replyToMessageId);
|
|
126
|
+
|
|
127
|
+
// Edit
|
|
128
|
+
const updated = await client.editMessage(conversationId, 'dm', messageId, 'Edited text');
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Real-time subscriptions
|
|
134
|
+
|
|
135
|
+
All `subscribe*` methods return an **unsubscribe function**. They fire immediately with current data, then refresh on every poll tick.
|
|
136
|
+
|
|
137
|
+
```typescript
|
|
138
|
+
// Messages
|
|
139
|
+
const unsub = client.subscribeToMessages(conv._id, conv.type, (messages) => {
|
|
140
|
+
setMessages(messages); // always the full ordered list
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Conversations list
|
|
144
|
+
const unsub = client.subscribeToConversations((conversations) => {
|
|
145
|
+
setConversations(conversations);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// Unread badge count
|
|
149
|
+
const unsub = client.subscribeToUnreadCount((count) => {
|
|
150
|
+
setBadge(count);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// Stop any subscription
|
|
154
|
+
unsub();
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### FCM foreground integration
|
|
158
|
+
|
|
159
|
+
When a Firebase Cloud Messaging push arrives while the app is open, trigger an immediate refresh instead of waiting for the next poll tick:
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
import { onMessage } from 'firebase/messaging';
|
|
163
|
+
|
|
164
|
+
onMessage(messaging, () => {
|
|
165
|
+
client.onForegroundPush();
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Channels & groups
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
// List public channels
|
|
175
|
+
const channels = await client.getChannels();
|
|
176
|
+
|
|
177
|
+
// Join / leave
|
|
178
|
+
await client.joinChannel(channelId);
|
|
179
|
+
await client.leaveChannel(channelId);
|
|
180
|
+
|
|
181
|
+
// Create a group
|
|
182
|
+
const group = await client.createGroup({
|
|
183
|
+
name: 'My Group',
|
|
184
|
+
description: 'Optional',
|
|
185
|
+
isPublic: false,
|
|
186
|
+
members: ['alice', 'bob'],
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
await client.addGroupMember(group._id, 'charlie');
|
|
190
|
+
await client.removeGroupMember(group._id, 'charlie');
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Typing indicators
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
// Signal that the current user is typing
|
|
199
|
+
await client.setTyping(conversationId, true);
|
|
200
|
+
await client.setTyping(conversationId, false);
|
|
201
|
+
|
|
202
|
+
// Poll who else is typing
|
|
203
|
+
const { users } = await client.getTyping(conversationId);
|
|
204
|
+
// users: string[] — list of usernames currently typing
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Preferences
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
await client.muteUser('spammer');
|
|
213
|
+
await client.unmuteUser('spammer');
|
|
214
|
+
await client.blockUser('troll');
|
|
215
|
+
await client.unblockUser('troll');
|
|
216
|
+
|
|
217
|
+
const prefs = await client.getPreferences();
|
|
218
|
+
// { mutedUsers: string[], blockedUsers: string[] }
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Push notifications (FCM)
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
// Register a device token so this user receives push notifications
|
|
227
|
+
await client.registerDevice(fcmToken);
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## React hooks
|
|
233
|
+
|
|
234
|
+
```tsx
|
|
235
|
+
import { ChatProvider, useConversations, useChatMessages, useUnreadCount, useTyping } from '@snapie/chat-client/react';
|
|
236
|
+
|
|
237
|
+
// Wrap once at the top level
|
|
238
|
+
<ChatProvider client={client}>
|
|
239
|
+
<App />
|
|
240
|
+
</ChatProvider>
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### `useConversations`
|
|
244
|
+
|
|
245
|
+
```tsx
|
|
246
|
+
function ConversationList() {
|
|
247
|
+
const { conversations, loading } = useConversations();
|
|
248
|
+
if (loading) return <Spinner />;
|
|
249
|
+
return conversations.map(conv => <ConvRow key={conv._id} conv={conv} />);
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### `useChatMessages`
|
|
254
|
+
|
|
255
|
+
```tsx
|
|
256
|
+
function MessageView({ conv }) {
|
|
257
|
+
const { messages, loading, sendMessage, editMessage } = useChatMessages(conv._id, conv.type);
|
|
258
|
+
|
|
259
|
+
return (
|
|
260
|
+
<>
|
|
261
|
+
{messages.map(m => <Bubble key={m._id} message={m} />)}
|
|
262
|
+
<Input onSend={sendMessage} />
|
|
263
|
+
</>
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### `useUnreadCount`
|
|
269
|
+
|
|
270
|
+
```tsx
|
|
271
|
+
function ChatButton() {
|
|
272
|
+
const { unreadCount } = useUnreadCount();
|
|
273
|
+
return <Button badge={unreadCount}>Chat</Button>;
|
|
274
|
+
}
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### `useTyping`
|
|
278
|
+
|
|
279
|
+
```tsx
|
|
280
|
+
function TypingIndicator({ convId }) {
|
|
281
|
+
const { typingUsers, setTyping } = useTyping(convId);
|
|
282
|
+
// setTyping(true) when user starts typing — auto-clears after 5s
|
|
283
|
+
return typingUsers.length > 0 ? <Text>{typingUsers.join(', ')} is typing...</Text> : null;
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## TypeScript types
|
|
290
|
+
|
|
291
|
+
All types are exported from the main entry point:
|
|
292
|
+
|
|
293
|
+
```typescript
|
|
294
|
+
import type {
|
|
295
|
+
ChatClient,
|
|
296
|
+
ChatClientOptions,
|
|
297
|
+
Conversation,
|
|
298
|
+
Message,
|
|
299
|
+
Channel,
|
|
300
|
+
MessagesResult,
|
|
301
|
+
DmDeliveryInfo,
|
|
302
|
+
DmStatusInfo,
|
|
303
|
+
TypingStatusInfo,
|
|
304
|
+
ChatPreferences,
|
|
305
|
+
StorageAdapter,
|
|
306
|
+
} from '@snapie/chat-client';
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## Backend
|
|
312
|
+
|
|
313
|
+
The SDK communicates with the Snapie chat API at `{baseUrl}/api/chat/*`. The backend is hosted at `https://snapie.io`. Auth tokens are JWTs issued after Hive posting-key signature verification and are stored in the configured storage adapter.
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
interface Channel {
|
|
2
|
+
_id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
type: string;
|
|
6
|
+
conversationKind?: 'channel' | 'group';
|
|
7
|
+
owner?: string;
|
|
8
|
+
members?: string[];
|
|
9
|
+
memberCount: number;
|
|
10
|
+
isPublic: boolean;
|
|
11
|
+
}
|
|
12
|
+
interface Message {
|
|
13
|
+
_id: string;
|
|
14
|
+
sender: string;
|
|
15
|
+
content: string;
|
|
16
|
+
replyTo?: string | null;
|
|
17
|
+
editedAt?: string | null;
|
|
18
|
+
createdAt: string;
|
|
19
|
+
}
|
|
20
|
+
interface Conversation {
|
|
21
|
+
_id: string;
|
|
22
|
+
name: string;
|
|
23
|
+
description?: string;
|
|
24
|
+
type: 'channel' | 'group' | 'dm';
|
|
25
|
+
isPublic: boolean;
|
|
26
|
+
owner?: string;
|
|
27
|
+
members?: string[];
|
|
28
|
+
memberCount?: number;
|
|
29
|
+
peer?: string;
|
|
30
|
+
lastMessage?: Message | null;
|
|
31
|
+
unread?: boolean;
|
|
32
|
+
}
|
|
33
|
+
interface DmDeliveryInfo {
|
|
34
|
+
hasFcm: boolean;
|
|
35
|
+
memoSuggested: boolean;
|
|
36
|
+
cooldownMs: number;
|
|
37
|
+
}
|
|
38
|
+
interface DmStatusInfo {
|
|
39
|
+
meSeenAt: string;
|
|
40
|
+
peerSeenAt: string | null;
|
|
41
|
+
peerLastSeenAt: string | null;
|
|
42
|
+
peerOnline: boolean;
|
|
43
|
+
}
|
|
44
|
+
interface TypingStatusInfo {
|
|
45
|
+
users: string[];
|
|
46
|
+
ttlMs: number;
|
|
47
|
+
}
|
|
48
|
+
interface ChatPreferences {
|
|
49
|
+
mutedUsers: string[];
|
|
50
|
+
blockedUsers: string[];
|
|
51
|
+
}
|
|
52
|
+
interface MessagesResult {
|
|
53
|
+
messages: Message[];
|
|
54
|
+
status?: DmStatusInfo | null;
|
|
55
|
+
}
|
|
56
|
+
interface StorageAdapter {
|
|
57
|
+
getItem(key: string): string | null;
|
|
58
|
+
setItem(key: string, value: string): void;
|
|
59
|
+
removeItem(key: string): void;
|
|
60
|
+
}
|
|
61
|
+
interface ChatClientOptions {
|
|
62
|
+
/** Base URL of the Snapie instance, e.g. "https://snapie.io" */
|
|
63
|
+
baseUrl: string;
|
|
64
|
+
/** Override default localStorage — useful for React Native or Node */
|
|
65
|
+
storage?: StorageAdapter;
|
|
66
|
+
/** How often to poll for new messages when FCM is not available (ms, default 15000) */
|
|
67
|
+
pollInterval?: number;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
declare class ChatService {
|
|
71
|
+
private token;
|
|
72
|
+
private tokenUsername;
|
|
73
|
+
private base;
|
|
74
|
+
private storage;
|
|
75
|
+
constructor(baseUrl: string, storage: StorageAdapter);
|
|
76
|
+
isAuthenticated(): boolean;
|
|
77
|
+
getTokenUsername(): string | null;
|
|
78
|
+
authenticate(username: string, signMessage: (msg: string) => Promise<string>): Promise<void>;
|
|
79
|
+
logout(): void;
|
|
80
|
+
getChannels(): Promise<Channel[]>;
|
|
81
|
+
getConversations(): Promise<Conversation[]>;
|
|
82
|
+
getChannelMessages(channelId: string, opts?: {
|
|
83
|
+
before?: string;
|
|
84
|
+
after?: string;
|
|
85
|
+
limit?: number;
|
|
86
|
+
}): Promise<Message[]>;
|
|
87
|
+
sendChannelMessage(channelId: string, content: string, replyTo?: string): Promise<Message>;
|
|
88
|
+
editChannelMessage(channelId: string, messageId: string, content: string): Promise<Message>;
|
|
89
|
+
joinChannel(channelId: string): Promise<void>;
|
|
90
|
+
leaveChannel(channelId: string): Promise<void>;
|
|
91
|
+
getDmMessages(conversationId: string, opts?: {
|
|
92
|
+
before?: string;
|
|
93
|
+
after?: string;
|
|
94
|
+
limit?: number;
|
|
95
|
+
}): Promise<MessagesResult>;
|
|
96
|
+
sendDmMessage(conversationId: string, content: string, replyTo?: string): Promise<{
|
|
97
|
+
message: Message;
|
|
98
|
+
delivery?: DmDeliveryInfo;
|
|
99
|
+
}>;
|
|
100
|
+
editDmMessage(conversationId: string, messageId: string, content: string): Promise<Message>;
|
|
101
|
+
openDm(targetUser: string): Promise<Conversation>;
|
|
102
|
+
createGroup(payload: {
|
|
103
|
+
name: string;
|
|
104
|
+
description?: string;
|
|
105
|
+
isPublic?: boolean;
|
|
106
|
+
members?: string[];
|
|
107
|
+
}): Promise<Channel>;
|
|
108
|
+
getGroups(): Promise<Channel[]>;
|
|
109
|
+
addGroupMember(groupId: string, member: string): Promise<Channel>;
|
|
110
|
+
removeGroupMember(groupId: string, member: string): Promise<Channel>;
|
|
111
|
+
getUnreadCount(): Promise<number>;
|
|
112
|
+
setTyping(conversationId: string, isTyping: boolean): Promise<void>;
|
|
113
|
+
getTyping(conversationId: string): Promise<TypingStatusInfo>;
|
|
114
|
+
getPreferences(): Promise<ChatPreferences>;
|
|
115
|
+
muteUser(username: string): Promise<void>;
|
|
116
|
+
unmuteUser(username: string): Promise<void>;
|
|
117
|
+
blockUser(username: string): Promise<void>;
|
|
118
|
+
unblockUser(username: string): Promise<void>;
|
|
119
|
+
registerDevice(fcmToken: string): Promise<void>;
|
|
120
|
+
markDmMemoFallbackSent(conversationId: string): Promise<void>;
|
|
121
|
+
private buildQS;
|
|
122
|
+
private get;
|
|
123
|
+
private post;
|
|
124
|
+
request<T>(url: string, opts: RequestInit, auth: boolean): Promise<T>;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
type ConversationsCallback = (conversations: Conversation[]) => void;
|
|
128
|
+
type MessagesCallback = (messages: Message[]) => void;
|
|
129
|
+
type UnreadCallback = (count: number) => void;
|
|
130
|
+
/**
|
|
131
|
+
* High-level Snapie chat client.
|
|
132
|
+
*
|
|
133
|
+
* Usage:
|
|
134
|
+
* const client = new ChatClient({ baseUrl: 'https://snapie.io' });
|
|
135
|
+
* await client.authenticate(username, msg => keychain.sign(msg));
|
|
136
|
+
* const conversations = await client.getConversations();
|
|
137
|
+
* const unsub = client.subscribeToMessages(convId, 'dm', msgs => setMessages(msgs));
|
|
138
|
+
*/
|
|
139
|
+
declare class ChatClient {
|
|
140
|
+
readonly service: ChatService;
|
|
141
|
+
private poller;
|
|
142
|
+
/** Cache of messages per conversationId — avoids re-rendering unchanged data */
|
|
143
|
+
private messageCache;
|
|
144
|
+
constructor(options: ChatClientOptions);
|
|
145
|
+
isAuthenticated(): boolean;
|
|
146
|
+
getUsername(): string | null;
|
|
147
|
+
/**
|
|
148
|
+
* Authenticate with a Hive account.
|
|
149
|
+
* `signMessage` should call Hive Keychain or equivalent with the posting key.
|
|
150
|
+
*/
|
|
151
|
+
authenticate(username: string, signMessage: (challenge: string) => Promise<string>): Promise<void>;
|
|
152
|
+
logout(): void;
|
|
153
|
+
getConversations(): Promise<Conversation[]>;
|
|
154
|
+
openDm(targetUser: string): Promise<Conversation>;
|
|
155
|
+
getChannels(): Promise<Channel[]>;
|
|
156
|
+
getGroups(): Promise<Channel[]>;
|
|
157
|
+
joinChannel(channelId: string): Promise<void>;
|
|
158
|
+
leaveChannel(channelId: string): Promise<void>;
|
|
159
|
+
createGroup(payload: {
|
|
160
|
+
name: string;
|
|
161
|
+
description?: string;
|
|
162
|
+
isPublic?: boolean;
|
|
163
|
+
members?: string[];
|
|
164
|
+
}): Promise<Channel>;
|
|
165
|
+
addGroupMember(groupId: string, member: string): Promise<Channel>;
|
|
166
|
+
removeGroupMember(groupId: string, member: string): Promise<Channel>;
|
|
167
|
+
getMessages(conversationId: string, type: 'channel' | 'dm' | 'group', opts?: {
|
|
168
|
+
before?: string;
|
|
169
|
+
after?: string;
|
|
170
|
+
limit?: number;
|
|
171
|
+
}): Promise<MessagesResult>;
|
|
172
|
+
sendMessage(conversationId: string, type: 'channel' | 'dm' | 'group', content: string, replyTo?: string): Promise<{
|
|
173
|
+
message: Message;
|
|
174
|
+
delivery?: DmDeliveryInfo;
|
|
175
|
+
}>;
|
|
176
|
+
editMessage(conversationId: string, type: 'channel' | 'dm' | 'group', messageId: string, content: string): Promise<Message>;
|
|
177
|
+
/**
|
|
178
|
+
* Subscribe to live updates for a conversation's message list.
|
|
179
|
+
* Calls `callback` immediately with the current messages, then again on every poll tick.
|
|
180
|
+
* Returns an unsubscribe function.
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* const unsub = client.subscribeToMessages(conv._id, conv.type, msgs => setMessages(msgs));
|
|
184
|
+
* // later:
|
|
185
|
+
* unsub();
|
|
186
|
+
*/
|
|
187
|
+
subscribeToMessages(conversationId: string, type: 'channel' | 'dm' | 'group', callback: MessagesCallback): () => void;
|
|
188
|
+
/**
|
|
189
|
+
* Subscribe to the full conversations list, refreshed on every poll tick.
|
|
190
|
+
* Returns an unsubscribe function.
|
|
191
|
+
*/
|
|
192
|
+
subscribeToConversations(callback: ConversationsCallback): () => void;
|
|
193
|
+
/**
|
|
194
|
+
* Subscribe to the unread message count, refreshed on every poll tick.
|
|
195
|
+
* Returns an unsubscribe function.
|
|
196
|
+
*/
|
|
197
|
+
subscribeToUnreadCount(callback: UnreadCallback): () => void;
|
|
198
|
+
/**
|
|
199
|
+
* Notify the client of an incoming FCM foreground message.
|
|
200
|
+
* Call this from your FCM `onMessage` handler to trigger an immediate refresh
|
|
201
|
+
* rather than waiting for the next poll tick.
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* onMessage(messaging, () => client.onForegroundPush());
|
|
205
|
+
*/
|
|
206
|
+
onForegroundPush(): void;
|
|
207
|
+
setTyping(conversationId: string, isTyping: boolean): Promise<void>;
|
|
208
|
+
getTyping(conversationId: string): Promise<TypingStatusInfo>;
|
|
209
|
+
getUnreadCount(): Promise<number>;
|
|
210
|
+
getPreferences(): Promise<ChatPreferences>;
|
|
211
|
+
muteUser(username: string): Promise<void>;
|
|
212
|
+
unmuteUser(username: string): Promise<void>;
|
|
213
|
+
blockUser(username: string): Promise<void>;
|
|
214
|
+
unblockUser(username: string): Promise<void>;
|
|
215
|
+
registerDevice(fcmToken: string): Promise<void>;
|
|
216
|
+
markDmMemoFallbackSent(conversationId: string): Promise<void>;
|
|
217
|
+
destroy(): void;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export { ChatClient as C, type DmDeliveryInfo as D, type Message as M, type StorageAdapter as S, type TypingStatusInfo as T, ChatService as a, type ChatClientOptions as b, type Channel as c, type Conversation as d, type MessagesResult as e, type DmStatusInfo as f, type ChatPreferences as g };
|