@jupyter/chat 0.25.0-alpha.6 → 0.25.0-rc.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/lib/__tests__/writers.spec.js +6 -8
- package/lib/model.d.ts +7 -10
- package/lib/model.js +2 -23
- package/package.json +1 -1
- package/src/__tests__/writers.spec.ts +6 -8
- package/src/model.ts +8 -42
|
@@ -35,18 +35,16 @@ describe('writers state', () => {
|
|
|
35
35
|
model.setWritingStatus(userA, { typingIndicator: 'x' });
|
|
36
36
|
expect(changes.length).toBe(count);
|
|
37
37
|
});
|
|
38
|
-
it('
|
|
38
|
+
it('keeps a writer until it is explicitly cleared (no auto-expiry)', () => {
|
|
39
39
|
jest.useFakeTimers();
|
|
40
40
|
try {
|
|
41
|
-
model.setWritingStatus(userA
|
|
41
|
+
model.setWritingStatus(userA);
|
|
42
42
|
expect(model.writers).toHaveLength(1);
|
|
43
|
-
//
|
|
44
|
-
jest.advanceTimersByTime(
|
|
45
|
-
model.setWritingStatus(userA, undefined, 2000);
|
|
46
|
-
jest.advanceTimersByTime(1500);
|
|
43
|
+
// A single call persists like any other update: no timer drops it.
|
|
44
|
+
jest.advanceTimersByTime(60000);
|
|
47
45
|
expect(model.writers).toHaveLength(1);
|
|
48
|
-
//
|
|
49
|
-
|
|
46
|
+
// Only an explicit clear removes it.
|
|
47
|
+
model.clearWritingStatus(userA);
|
|
50
48
|
expect(model.writers).toHaveLength(0);
|
|
51
49
|
}
|
|
52
50
|
finally {
|
package/lib/model.d.ts
CHANGED
|
@@ -169,14 +169,14 @@ export interface IChatModel extends IDisposable {
|
|
|
169
169
|
/**
|
|
170
170
|
* Mark a user as currently writing (add or update their writer entry).
|
|
171
171
|
*
|
|
172
|
+
* The writer stays until explicitly removed via {@link clearWritingStatus}
|
|
173
|
+
* (or replaced by a new snapshot in {@link updateWriters}); there is no
|
|
174
|
+
* auto-expiry, so a single call persists like any other update.
|
|
175
|
+
*
|
|
172
176
|
* @param user - the writing user.
|
|
173
177
|
* @param status - optional writing status (messageID, custom typingIndicator).
|
|
174
|
-
* @param timeout - optional auto-clear delay in ms. When set, the user is
|
|
175
|
-
* automatically cleared after `timeout` unless refreshed by another call.
|
|
176
|
-
* Used by transports without their own liveness signal (e.g. WebSocket) to
|
|
177
|
-
* avoid a stuck "is typing" if a clear message is never received.
|
|
178
178
|
*/
|
|
179
|
-
setWritingStatus(user: IUser, status?: IChatModel.IWritingStatus
|
|
179
|
+
setWritingStatus(user: IUser, status?: IChatModel.IWritingStatus): void;
|
|
180
180
|
/**
|
|
181
181
|
* Remove a user from the writers list.
|
|
182
182
|
*/
|
|
@@ -184,7 +184,7 @@ export interface IChatModel extends IDisposable {
|
|
|
184
184
|
/**
|
|
185
185
|
* Broadcast the *current user's* writing status to other clients, or clear it
|
|
186
186
|
* with `null`. Implemented per transport (RTC sets awareness; WebSocket sends
|
|
187
|
-
* a
|
|
187
|
+
* a single writing frame). Default implementation is a no-op.
|
|
188
188
|
*/
|
|
189
189
|
broadcastWritingStatus(status: IChatModel.IWritingStatus | null): void;
|
|
190
190
|
/**
|
|
@@ -375,7 +375,7 @@ export declare abstract class AbstractChatModel implements IChatModel {
|
|
|
375
375
|
/**
|
|
376
376
|
* Mark a user as currently writing. See IChatModel.setWritingStatus.
|
|
377
377
|
*/
|
|
378
|
-
setWritingStatus(user: IUser, status?: IChatModel.IWritingStatus
|
|
378
|
+
setWritingStatus(user: IUser, status?: IChatModel.IWritingStatus): void;
|
|
379
379
|
/**
|
|
380
380
|
* Remove a user from the writers list. See IChatModel.clearWritingStatus.
|
|
381
381
|
*/
|
|
@@ -386,8 +386,6 @@ export declare abstract class AbstractChatModel implements IChatModel {
|
|
|
386
386
|
*/
|
|
387
387
|
broadcastWritingStatus(_status: IChatModel.IWritingStatus | null): void;
|
|
388
388
|
private _removeWriter;
|
|
389
|
-
private _clearWriterTimer;
|
|
390
|
-
private _clearAllWriterTimers;
|
|
391
389
|
/**
|
|
392
390
|
* Create the chat context that will be passed to the input model.
|
|
393
391
|
*/
|
|
@@ -438,7 +436,6 @@ export declare abstract class AbstractChatModel implements IChatModel {
|
|
|
438
436
|
private _documentManager;
|
|
439
437
|
private _notificationId;
|
|
440
438
|
private _writers;
|
|
441
|
-
private _writerTimers;
|
|
442
439
|
private _messageEditions;
|
|
443
440
|
private _messagesUpdated;
|
|
444
441
|
private _messageChanged;
|
package/lib/model.js
CHANGED
|
@@ -30,7 +30,6 @@ export class AbstractChatModel {
|
|
|
30
30
|
this._isDisposed = false;
|
|
31
31
|
this._notificationId = null;
|
|
32
32
|
this._writers = new Map();
|
|
33
|
-
this._writerTimers = new Map();
|
|
34
33
|
this._messageEditions = new Map();
|
|
35
34
|
this._messagesUpdated = new Signal(this);
|
|
36
35
|
this._messageChanged = new Signal(this);
|
|
@@ -402,9 +401,7 @@ export class AbstractChatModel {
|
|
|
402
401
|
*/
|
|
403
402
|
updateWriters(writers) {
|
|
404
403
|
// Reconcile the writers map with the provided snapshot (used by
|
|
405
|
-
// snapshot-style transports such as RTC awareness).
|
|
406
|
-
// are dropped, since the snapshot is authoritative.
|
|
407
|
-
this._clearAllWriterTimers();
|
|
404
|
+
// snapshot-style transports such as RTC awareness).
|
|
408
405
|
const next = new Map();
|
|
409
406
|
for (const writer of writers) {
|
|
410
407
|
next.set(writer.user.username, writer);
|
|
@@ -417,16 +414,12 @@ export class AbstractChatModel {
|
|
|
417
414
|
/**
|
|
418
415
|
* Mark a user as currently writing. See IChatModel.setWritingStatus.
|
|
419
416
|
*/
|
|
420
|
-
setWritingStatus(user, status
|
|
417
|
+
setWritingStatus(user, status) {
|
|
421
418
|
const writer = {
|
|
422
419
|
user,
|
|
423
420
|
messageID: status === null || status === void 0 ? void 0 : status.messageID,
|
|
424
421
|
typingIndicator: status === null || status === void 0 ? void 0 : status.typingIndicator
|
|
425
422
|
};
|
|
426
|
-
this._clearWriterTimer(user.username);
|
|
427
|
-
if (timeout !== undefined) {
|
|
428
|
-
this._writerTimers.set(user.username, window.setTimeout(() => this._removeWriter(user.username), timeout));
|
|
429
|
-
}
|
|
430
423
|
const previous = this._writers.get(user.username);
|
|
431
424
|
this._writers.set(user.username, writer);
|
|
432
425
|
if (!previous || !Private.writerEqual(previous, writer)) {
|
|
@@ -447,24 +440,10 @@ export class AbstractChatModel {
|
|
|
447
440
|
// no-op by default
|
|
448
441
|
}
|
|
449
442
|
_removeWriter(username) {
|
|
450
|
-
this._clearWriterTimer(username);
|
|
451
443
|
if (this._writers.delete(username)) {
|
|
452
444
|
this._writersChanged.emit(this.writers);
|
|
453
445
|
}
|
|
454
446
|
}
|
|
455
|
-
_clearWriterTimer(username) {
|
|
456
|
-
const timer = this._writerTimers.get(username);
|
|
457
|
-
if (timer !== undefined) {
|
|
458
|
-
window.clearTimeout(timer);
|
|
459
|
-
this._writerTimers.delete(username);
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
_clearAllWriterTimers() {
|
|
463
|
-
for (const timer of this._writerTimers.values()) {
|
|
464
|
-
window.clearTimeout(timer);
|
|
465
|
-
}
|
|
466
|
-
this._writerTimers.clear();
|
|
467
|
-
}
|
|
468
447
|
/**
|
|
469
448
|
* Get the input model of the edited message, given its id.
|
|
470
449
|
*/
|
package/package.json
CHANGED
|
@@ -47,20 +47,18 @@ describe('writers state', () => {
|
|
|
47
47
|
expect(changes.length).toBe(count);
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
-
it('
|
|
50
|
+
it('keeps a writer until it is explicitly cleared (no auto-expiry)', () => {
|
|
51
51
|
jest.useFakeTimers();
|
|
52
52
|
try {
|
|
53
|
-
model.setWritingStatus(userA
|
|
53
|
+
model.setWritingStatus(userA);
|
|
54
54
|
expect(model.writers).toHaveLength(1);
|
|
55
55
|
|
|
56
|
-
//
|
|
57
|
-
jest.advanceTimersByTime(
|
|
58
|
-
model.setWritingStatus(userA, undefined, 2000);
|
|
59
|
-
jest.advanceTimersByTime(1500);
|
|
56
|
+
// A single call persists like any other update: no timer drops it.
|
|
57
|
+
jest.advanceTimersByTime(60_000);
|
|
60
58
|
expect(model.writers).toHaveLength(1);
|
|
61
59
|
|
|
62
|
-
//
|
|
63
|
-
|
|
60
|
+
// Only an explicit clear removes it.
|
|
61
|
+
model.clearWritingStatus(userA);
|
|
64
62
|
expect(model.writers).toHaveLength(0);
|
|
65
63
|
} finally {
|
|
66
64
|
jest.useRealTimers();
|
package/src/model.ts
CHANGED
|
@@ -226,18 +226,14 @@ export interface IChatModel extends IDisposable {
|
|
|
226
226
|
/**
|
|
227
227
|
* Mark a user as currently writing (add or update their writer entry).
|
|
228
228
|
*
|
|
229
|
+
* The writer stays until explicitly removed via {@link clearWritingStatus}
|
|
230
|
+
* (or replaced by a new snapshot in {@link updateWriters}); there is no
|
|
231
|
+
* auto-expiry, so a single call persists like any other update.
|
|
232
|
+
*
|
|
229
233
|
* @param user - the writing user.
|
|
230
234
|
* @param status - optional writing status (messageID, custom typingIndicator).
|
|
231
|
-
* @param timeout - optional auto-clear delay in ms. When set, the user is
|
|
232
|
-
* automatically cleared after `timeout` unless refreshed by another call.
|
|
233
|
-
* Used by transports without their own liveness signal (e.g. WebSocket) to
|
|
234
|
-
* avoid a stuck "is typing" if a clear message is never received.
|
|
235
235
|
*/
|
|
236
|
-
setWritingStatus(
|
|
237
|
-
user: IUser,
|
|
238
|
-
status?: IChatModel.IWritingStatus,
|
|
239
|
-
timeout?: number
|
|
240
|
-
): void;
|
|
236
|
+
setWritingStatus(user: IUser, status?: IChatModel.IWritingStatus): void;
|
|
241
237
|
|
|
242
238
|
/**
|
|
243
239
|
* Remove a user from the writers list.
|
|
@@ -247,7 +243,7 @@ export interface IChatModel extends IDisposable {
|
|
|
247
243
|
/**
|
|
248
244
|
* Broadcast the *current user's* writing status to other clients, or clear it
|
|
249
245
|
* with `null`. Implemented per transport (RTC sets awareness; WebSocket sends
|
|
250
|
-
* a
|
|
246
|
+
* a single writing frame). Default implementation is a no-op.
|
|
251
247
|
*/
|
|
252
248
|
broadcastWritingStatus(status: IChatModel.IWritingStatus | null): void;
|
|
253
249
|
|
|
@@ -722,9 +718,7 @@ export abstract class AbstractChatModel implements IChatModel {
|
|
|
722
718
|
*/
|
|
723
719
|
updateWriters(writers: IChatModel.IWriter[]): void {
|
|
724
720
|
// Reconcile the writers map with the provided snapshot (used by
|
|
725
|
-
// snapshot-style transports such as RTC awareness).
|
|
726
|
-
// are dropped, since the snapshot is authoritative.
|
|
727
|
-
this._clearAllWriterTimers();
|
|
721
|
+
// snapshot-style transports such as RTC awareness).
|
|
728
722
|
const next = new Map<string, IChatModel.IWriter>();
|
|
729
723
|
for (const writer of writers) {
|
|
730
724
|
next.set(writer.user.username, writer);
|
|
@@ -738,23 +732,12 @@ export abstract class AbstractChatModel implements IChatModel {
|
|
|
738
732
|
/**
|
|
739
733
|
* Mark a user as currently writing. See IChatModel.setWritingStatus.
|
|
740
734
|
*/
|
|
741
|
-
setWritingStatus(
|
|
742
|
-
user: IUser,
|
|
743
|
-
status?: IChatModel.IWritingStatus,
|
|
744
|
-
timeout?: number
|
|
745
|
-
): void {
|
|
735
|
+
setWritingStatus(user: IUser, status?: IChatModel.IWritingStatus): void {
|
|
746
736
|
const writer: IChatModel.IWriter = {
|
|
747
737
|
user,
|
|
748
738
|
messageID: status?.messageID,
|
|
749
739
|
typingIndicator: status?.typingIndicator
|
|
750
740
|
};
|
|
751
|
-
this._clearWriterTimer(user.username);
|
|
752
|
-
if (timeout !== undefined) {
|
|
753
|
-
this._writerTimers.set(
|
|
754
|
-
user.username,
|
|
755
|
-
window.setTimeout(() => this._removeWriter(user.username), timeout)
|
|
756
|
-
);
|
|
757
|
-
}
|
|
758
741
|
const previous = this._writers.get(user.username);
|
|
759
742
|
this._writers.set(user.username, writer);
|
|
760
743
|
if (!previous || !Private.writerEqual(previous, writer)) {
|
|
@@ -778,27 +761,11 @@ export abstract class AbstractChatModel implements IChatModel {
|
|
|
778
761
|
}
|
|
779
762
|
|
|
780
763
|
private _removeWriter(username: string): void {
|
|
781
|
-
this._clearWriterTimer(username);
|
|
782
764
|
if (this._writers.delete(username)) {
|
|
783
765
|
this._writersChanged.emit(this.writers);
|
|
784
766
|
}
|
|
785
767
|
}
|
|
786
768
|
|
|
787
|
-
private _clearWriterTimer(username: string): void {
|
|
788
|
-
const timer = this._writerTimers.get(username);
|
|
789
|
-
if (timer !== undefined) {
|
|
790
|
-
window.clearTimeout(timer);
|
|
791
|
-
this._writerTimers.delete(username);
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
private _clearAllWriterTimers(): void {
|
|
796
|
-
for (const timer of this._writerTimers.values()) {
|
|
797
|
-
window.clearTimeout(timer);
|
|
798
|
-
}
|
|
799
|
-
this._writerTimers.clear();
|
|
800
|
-
}
|
|
801
|
-
|
|
802
769
|
/**
|
|
803
770
|
* Create the chat context that will be passed to the input model.
|
|
804
771
|
*/
|
|
@@ -914,7 +881,6 @@ export abstract class AbstractChatModel implements IChatModel {
|
|
|
914
881
|
private _documentManager: IDocumentManager | null;
|
|
915
882
|
private _notificationId: string | null = null;
|
|
916
883
|
private _writers = new Map<string, IChatModel.IWriter>();
|
|
917
|
-
private _writerTimers = new Map<string, number>();
|
|
918
884
|
private _messageEditions = new Map<string, IInputModel>();
|
|
919
885
|
private _messagesUpdated = new Signal<IChatModel, void>(this);
|
|
920
886
|
private _messageChanged = new Signal<IChatModel, IMessage>(this);
|