@droponair/sdk-js 0.29.0 → 0.30.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/CHANGELOG.md +14 -0
- package/README.md +16 -0
- package/dist/core/messaging-client.d.ts +15 -1
- package/dist/core/messaging-client.js +47 -1
- package/dist/core/types.d.ts +18 -0
- package/dist/index.d.ts +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.30.0
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **Typing indicators.** `sendTyping(conversationId, isTyping)` and `onTyping(callback)`. Nothing in the platform carried this before, so an
|
|
8
|
+
app that wanted to show someone composing had nowhere to send it.
|
|
9
|
+
- Typing is never stored. It describes this moment and is worth nothing after it,
|
|
10
|
+
so it reaches only those connected at the time and is never replayed. Treat a
|
|
11
|
+
start as expiring on its own after a few seconds rather than waiting for the
|
|
12
|
+
matching stop, which is lost if the sender disconnects mid-sentence.
|
|
13
|
+
- Gated separately from read receipts, which name a message that was read and are
|
|
14
|
+
opted into per group. Typing says only that somebody is composing and discloses
|
|
15
|
+
nothing about what, so it needs no per-group opt-in.
|
|
16
|
+
|
|
3
17
|
## 0.29.0
|
|
4
18
|
|
|
5
19
|
### Fixed
|
package/README.md
CHANGED
|
@@ -380,6 +380,22 @@ on `SERVER_RECEIVED`, which is about the relay rather than any member.
|
|
|
380
380
|
was closed or disconnected is drained automatically when it reconnects and delivered
|
|
381
381
|
through `onGroupMessage` just like a live message. There is nothing to call.
|
|
382
382
|
|
|
383
|
+
### Typing indicators
|
|
384
|
+
|
|
385
|
+
Say when someone starts and stops composing, and hear it about others. Nothing is
|
|
386
|
+
stored: it reaches only those connected at the time and is never replayed, so
|
|
387
|
+
treat a start as expiring on its own rather than waiting for the stop, which is
|
|
388
|
+
lost if the sender disconnects mid-sentence.
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
client.sendTyping(groupId, true);
|
|
392
|
+
client.sendTyping(groupId, false);
|
|
393
|
+
|
|
394
|
+
client.onTyping((event) => {
|
|
395
|
+
// event.conversationId, event.fromUserId, event.isTyping
|
|
396
|
+
});
|
|
397
|
+
```
|
|
398
|
+
|
|
383
399
|
### 1-to-1 Calls
|
|
384
400
|
|
|
385
401
|
| Method | Returns | Description |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CryptoService } from '../crypto/crypto-service';
|
|
2
2
|
import { SessionManager } from './session-manager';
|
|
3
|
-
import { BroadcastCallback, CallEventCallback, DropOnAirClient, EventCallback, CreateRoomOptions, GroupCallEventCallback, GroupInfo, GroupMessageCallback, Room, UpdateRoomOptions, SfuToken, SfuRecording, InitializeOptions, MessageCallback, MessageDeleteCallback, MessageEditCallback, TurnCredentials, DeviceInfo, ReadReceiptCallback, NotificationClearCallback, DraftSyncCallback, KeyCustody, PushPayload } from './types';
|
|
3
|
+
import { BroadcastCallback, CallEventCallback, DropOnAirClient, EventCallback, CreateRoomOptions, GroupCallEventCallback, GroupInfo, GroupMessageCallback, Room, UpdateRoomOptions, SfuToken, SfuRecording, InitializeOptions, MessageCallback, MessageDeleteCallback, MessageEditCallback, TurnCredentials, DeviceInfo, ReadReceiptCallback, TypingCallback, NotificationClearCallback, DraftSyncCallback, KeyCustody, PushPayload } from './types';
|
|
4
4
|
import { AttachmentRef, CreateUploadSessionOptions, DownloadedAttachment, PrepareAttachmentOptions, UploadSession } from '../attachment/attachment-types';
|
|
5
5
|
export declare class MessagingClient implements DropOnAirClient {
|
|
6
6
|
private readonly options;
|
|
@@ -90,6 +90,7 @@ export declare class MessagingClient implements DropOnAirClient {
|
|
|
90
90
|
private readonly broadcastListeners;
|
|
91
91
|
private readonly messageEditListeners;
|
|
92
92
|
private readonly readReceiptListeners;
|
|
93
|
+
private readonly typingListeners;
|
|
93
94
|
private readonly notificationClearListeners;
|
|
94
95
|
private readonly draftSyncListeners;
|
|
95
96
|
private readonly messageDeleteListeners;
|
|
@@ -146,6 +147,11 @@ export declare class MessagingClient implements DropOnAirClient {
|
|
|
146
147
|
* reported. Fires when another device of the same user calls markRead();
|
|
147
148
|
* use it to clear the unread state your app maintains for that message.
|
|
148
149
|
*/
|
|
150
|
+
/**
|
|
151
|
+
* Listen for someone starting or stopping typing in a conversation. Nothing is
|
|
152
|
+
* stored, so this only fires while both sides are connected.
|
|
153
|
+
*/
|
|
154
|
+
onTyping(callback: TypingCallback): () => void;
|
|
149
155
|
onReadReceipt(callback: ReadReceiptCallback): () => void;
|
|
150
156
|
editMessage(originalMessageId: string, toUserId: string, newPlaintext: string): Promise<{
|
|
151
157
|
editId: string;
|
|
@@ -217,6 +223,14 @@ export declare class MessagingClient implements DropOnAirClient {
|
|
|
217
223
|
* @param conversationId optional peer userId / group id, echoed back to
|
|
218
224
|
* other devices so they can bucket the receipt
|
|
219
225
|
*/
|
|
226
|
+
/**
|
|
227
|
+
* Say this user started or stopped composing in a conversation.
|
|
228
|
+
*
|
|
229
|
+
* Never stored, so it reaches only those connected at the time. Send `false`
|
|
230
|
+
* when they stop, but treat the indicator as expiring on its own: if the sender
|
|
231
|
+
* disconnects mid-sentence, the stop never arrives.
|
|
232
|
+
*/
|
|
233
|
+
sendTyping(conversationId: string, isTyping: boolean): void;
|
|
220
234
|
markRead(messageId: string, conversationId?: string): void;
|
|
221
235
|
/**
|
|
222
236
|
* Tell this user's other devices that the notification(s) for a
|
|
@@ -282,6 +282,7 @@ class MessagingClient {
|
|
|
282
282
|
this.broadcastListeners = new Set();
|
|
283
283
|
this.messageEditListeners = new Set();
|
|
284
284
|
this.readReceiptListeners = new Set();
|
|
285
|
+
this.typingListeners = new Set();
|
|
285
286
|
this.notificationClearListeners = new Set();
|
|
286
287
|
this.draftSyncListeners = new Set();
|
|
287
288
|
this.messageDeleteListeners = new Set();
|
|
@@ -519,6 +520,14 @@ class MessagingClient {
|
|
|
519
520
|
* reported. Fires when another device of the same user calls markRead();
|
|
520
521
|
* use it to clear the unread state your app maintains for that message.
|
|
521
522
|
*/
|
|
523
|
+
/**
|
|
524
|
+
* Listen for someone starting or stopping typing in a conversation. Nothing is
|
|
525
|
+
* stored, so this only fires while both sides are connected.
|
|
526
|
+
*/
|
|
527
|
+
onTyping(callback) {
|
|
528
|
+
this.typingListeners.add(callback);
|
|
529
|
+
return () => this.typingListeners.delete(callback);
|
|
530
|
+
}
|
|
522
531
|
onReadReceipt(callback) {
|
|
523
532
|
this.readReceiptListeners.add(callback);
|
|
524
533
|
return () => this.readReceiptListeners.delete(callback);
|
|
@@ -777,6 +786,26 @@ class MessagingClient {
|
|
|
777
786
|
* @param conversationId optional peer userId / group id, echoed back to
|
|
778
787
|
* other devices so they can bucket the receipt
|
|
779
788
|
*/
|
|
789
|
+
/**
|
|
790
|
+
* Say this user started or stopped composing in a conversation.
|
|
791
|
+
*
|
|
792
|
+
* Never stored, so it reaches only those connected at the time. Send `false`
|
|
793
|
+
* when they stop, but treat the indicator as expiring on its own: if the sender
|
|
794
|
+
* disconnects mid-sentence, the stop never arrives.
|
|
795
|
+
*/
|
|
796
|
+
sendTyping(conversationId, isTyping) {
|
|
797
|
+
if (!this.transport?.isOpen()) {
|
|
798
|
+
return;
|
|
799
|
+
}
|
|
800
|
+
const frame = {
|
|
801
|
+
type: 'SYNC_TYPING',
|
|
802
|
+
messageId: '',
|
|
803
|
+
conversationId,
|
|
804
|
+
timestamp: Date.now(),
|
|
805
|
+
payload: isTyping ? 'start' : 'stop',
|
|
806
|
+
};
|
|
807
|
+
this.transport.send(this.codec.encodeSyncFrame(frame));
|
|
808
|
+
}
|
|
780
809
|
markRead(messageId, conversationId) {
|
|
781
810
|
if (!this.transport?.isOpen()) {
|
|
782
811
|
throw new Error('DropOnAir websocket is not connected');
|
|
@@ -838,7 +867,24 @@ class MessagingClient {
|
|
|
838
867
|
return () => this.draftSyncListeners.delete(callback);
|
|
839
868
|
}
|
|
840
869
|
handleIncomingSync(frame) {
|
|
841
|
-
if (frame.type === '
|
|
870
|
+
if (frame.type === 'SYNC_TYPING') {
|
|
871
|
+
if (!frame.conversationId || !frame.fromUserId) {
|
|
872
|
+
return;
|
|
873
|
+
}
|
|
874
|
+
const event = {
|
|
875
|
+
conversationId: frame.conversationId,
|
|
876
|
+
fromUserId: frame.fromUserId,
|
|
877
|
+
isTyping: frame.payload !== 'stop',
|
|
878
|
+
timestamp: frame.timestamp,
|
|
879
|
+
};
|
|
880
|
+
for (const listener of this.typingListeners) {
|
|
881
|
+
try {
|
|
882
|
+
listener(event);
|
|
883
|
+
}
|
|
884
|
+
catch { /* listener errors must not break the socket */ }
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
else if (frame.type === 'SYNC_READ_RECEIPT') {
|
|
842
888
|
const event = {
|
|
843
889
|
messageId: frame.messageId,
|
|
844
890
|
conversationId: frame.conversationId || undefined,
|
package/dist/core/types.d.ts
CHANGED
|
@@ -109,6 +109,24 @@ export interface ReadReceiptEvent {
|
|
|
109
109
|
fromUserId?: string;
|
|
110
110
|
}
|
|
111
111
|
export type ReadReceiptCallback = (event: ReadReceiptEvent) => void;
|
|
112
|
+
/**
|
|
113
|
+
* Someone in a conversation started or stopped composing.
|
|
114
|
+
*
|
|
115
|
+
* Ephemeral by design: the platform never stores it, so it arrives only while
|
|
116
|
+
* both sides are connected and nothing is replayed afterwards. Treat a `true` as
|
|
117
|
+
* expiring on its own after a few seconds rather than waiting for the matching
|
|
118
|
+
* `false`, which is lost if the sender disconnects mid-sentence.
|
|
119
|
+
*/
|
|
120
|
+
export interface TypingEvent {
|
|
121
|
+
/** The group or peer the typing is happening in. */
|
|
122
|
+
conversationId: string;
|
|
123
|
+
/** Who is typing. */
|
|
124
|
+
fromUserId: string;
|
|
125
|
+
/** Whether they started or stopped. */
|
|
126
|
+
isTyping: boolean;
|
|
127
|
+
timestamp: number;
|
|
128
|
+
}
|
|
129
|
+
export type TypingCallback = (event: TypingEvent) => void;
|
|
112
130
|
/**
|
|
113
131
|
* Delivered to the user's OTHER devices when one device calls
|
|
114
132
|
* clearNotification(). Use it to clear the conversation's notification badge.
|
package/dist/index.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export { SDK_VERSION, PROTOCOL_VERSION, PAYLOAD_FORMAT_VERSION } from './version
|
|
|
22
22
|
*/
|
|
23
23
|
export declare function createSecureIdentity(store?: IdentityRecordStore): Promise<WebCryptoIdentityProvider | null>;
|
|
24
24
|
export declare function initialize(options: InitializeOptions): Promise<DropOnAirClient>;
|
|
25
|
-
export type { InitializeOptions, DropOnAirClient, DropOnAirEvent, MessageCallback, EventCallback, DecryptedMessage, KeyStorageAdapter, CallEvent, CallEventType, CallEventCallback, TurnCredentials, BroadcastMessage, BroadcastCallback, GroupInfo, GroupMemberInfo, DecryptedGroupMessage, GroupMessageCallback, GroupCallEvent, GroupCallEventType, GroupCallEventCallback, Room, RoomPolicy, CreateRoomOptions, UpdateRoomOptions, SfuToken, SfuRecording, MessageEditEvent, MessageEditCallback, MessageDeleteEvent, MessageDeleteCallback, DeviceInfo, ReadReceiptEvent, ReadReceiptCallback, NotificationClearEvent, NotificationClearCallback, DraftSyncEvent, DraftSyncCallback, } from './core/types';
|
|
25
|
+
export type { InitializeOptions, DropOnAirClient, DropOnAirEvent, MessageCallback, EventCallback, DecryptedMessage, KeyStorageAdapter, CallEvent, CallEventType, CallEventCallback, TurnCredentials, BroadcastMessage, BroadcastCallback, GroupInfo, GroupMemberInfo, DecryptedGroupMessage, GroupMessageCallback, GroupCallEvent, GroupCallEventType, GroupCallEventCallback, Room, RoomPolicy, CreateRoomOptions, UpdateRoomOptions, SfuToken, SfuRecording, MessageEditEvent, MessageEditCallback, MessageDeleteEvent, MessageDeleteCallback, DeviceInfo, ReadReceiptEvent, ReadReceiptCallback, TypingEvent, TypingCallback, NotificationClearEvent, NotificationClearCallback, DraftSyncEvent, DraftSyncCallback, } from './core/types';
|
|
26
26
|
export type { AttachmentEncryptionType, AttachmentConversationType, AttachmentRef, DeviceWrappedKey, CreateUploadSessionOptions, UploadSession, PrepareAttachmentOptions, DownloadedAttachment, } from './attachment/attachment-types';
|
|
27
27
|
export { SseTransport, type SseTransportOptions, type SseFrameHandler, type SseStateHandler, } from './transport/sse-transport';
|
|
28
28
|
export { WebTransportTransport, type WebTransportTransportOptions, type WTFrameHandler, type WTStateHandler, } from './transport/webtransport-transport';
|
package/dist/version.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* MINOR, additive feature (e.g. multi-device payloads, new call event type)
|
|
8
8
|
* PATCH, bug-fix / perf improvement with no wire or API change
|
|
9
9
|
*/
|
|
10
|
-
export declare const SDK_VERSION = "0.
|
|
10
|
+
export declare const SDK_VERSION = "0.30.0";
|
|
11
11
|
/**
|
|
12
12
|
* Binary encrypted-payload format version.
|
|
13
13
|
* Included as the first byte of every encrypted payload so receivers can
|
package/dist/version.js
CHANGED
|
@@ -10,7 +10,7 @@ exports.PROTOCOL_VERSION = exports.PAYLOAD_FORMAT_VERSION = exports.SDK_VERSION
|
|
|
10
10
|
* MINOR, additive feature (e.g. multi-device payloads, new call event type)
|
|
11
11
|
* PATCH, bug-fix / perf improvement with no wire or API change
|
|
12
12
|
*/
|
|
13
|
-
exports.SDK_VERSION = '0.
|
|
13
|
+
exports.SDK_VERSION = '0.30.0';
|
|
14
14
|
/**
|
|
15
15
|
* Binary encrypted-payload format version.
|
|
16
16
|
* Included as the first byte of every encrypted payload so receivers can
|
package/package.json
CHANGED