Skip to content

Commit 582b4d6

Browse files
authored
Merge pull request #269 from GetStream/recover-state
Recover state
2 parents 374aa53 + 68bbd3d commit 582b4d6

File tree

2 files changed

+57
-3
lines changed

2 files changed

+57
-3
lines changed

projects/stream-chat-angular/src/lib/channel.service.spec.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { fakeAsync, TestBed, tick } from '@angular/core/testing';
22
import { Subject } from 'rxjs';
3-
import { first } from 'rxjs/operators';
3+
import { first, take } from 'rxjs/operators';
44
import {
55
Channel,
66
ChannelMemberResponse,
77
ChannelOptions,
8+
ChannelResponse,
89
ChannelSort,
910
Event,
1011
SendMessageAPIResponse,
@@ -184,10 +185,24 @@ describe('ChannelService', () => {
184185
expect(activeChannelSpy).toHaveBeenCalledWith(undefined);
185186
expect(messageToQuoteSpy).toHaveBeenCalledWith(undefined);
186187
expect(latestMessagesSpy).toHaveBeenCalledWith({});
188+
189+
channelsSpy.calls.reset();
190+
events$.next({
191+
eventType: 'message.new',
192+
event: {
193+
channel: {
194+
id: 'channel',
195+
} as ChannelResponse<DefaultStreamChatGenerics>,
196+
} as Event<DefaultStreamChatGenerics>,
197+
});
198+
199+
expect(channelsSpy).not.toHaveBeenCalled();
187200
});
188201

189202
it('should deselect active channel', async () => {
190203
await init();
204+
let activeChannel!: Channel<DefaultStreamChatGenerics>;
205+
service.activeChannel$.pipe(take(1)).subscribe((c) => (activeChannel = c!));
191206
const messagesSpy = jasmine.createSpy();
192207
service.activeChannelMessages$.subscribe(messagesSpy);
193208
const activeChannelSpy = jasmine.createSpy();
@@ -206,6 +221,11 @@ describe('ChannelService', () => {
206221
expect(activeChannelSpy).toHaveBeenCalledWith(undefined);
207222
expect(messageToQuoteSpy).toHaveBeenCalledWith(undefined);
208223
expect(latestMessagesSpy).toHaveBeenCalledWith({});
224+
225+
messagesSpy.calls.reset();
226+
(activeChannel as MockChannel).handleEvent('message.new', mockMessage());
227+
228+
expect(messagesSpy).not.toHaveBeenCalled();
209229
});
210230

211231
it('should tell if user #hasMoreChannels$', async () => {
@@ -1508,4 +1528,20 @@ describe('ChannelService', () => {
15081528
expect(customFileDeleteRequest).toHaveBeenCalledWith(url, channel);
15091529
expect(channel.deleteFile).not.toHaveBeenCalled();
15101530
});
1531+
1532+
it('should reset state after connection recovered', async () => {
1533+
await init();
1534+
spyOn(service, 'init');
1535+
spyOn(service, 'reset');
1536+
events$.next({ eventType: 'connection.recovered' } as ClientEvent);
1537+
1538+
expect(service.init).toHaveBeenCalledWith(
1539+
service['filters']!,
1540+
service['sort'],
1541+
service['options'],
1542+
service['shouldSetActiveChannel']
1543+
);
1544+
1545+
expect(service.reset).toHaveBeenCalledWith();
1546+
});
15111547
});

projects/stream-chat-angular/src/lib/channel.service.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
combineLatest,
55
Observable,
66
ReplaySubject,
7+
Subscription,
78
} from 'rxjs';
89
import { filter, first, map, shareReplay } from 'rxjs/operators';
910
import {
@@ -258,6 +259,8 @@ export class ChannelService<
258259
[]
259260
);
260261
private _shouldMarkActiveChannelAsRead = true;
262+
private shouldSetActiveChannel: boolean | undefined;
263+
private clientEventsSubscription: Subscription | undefined;
261264

262265
private channelListSetter = (
263266
channels: (Channel<T> | ChannelResponse<T>)[]
@@ -392,6 +395,7 @@ export class ChannelService<
392395
if (!activeChannel) {
393396
return;
394397
}
398+
this.stopWatchForActiveChannelEvents(activeChannel);
395399
this.activeChannelMessagesSubject.next([]);
396400
this.activeChannelSubject.next(undefined);
397401
this.activeParentMessageIdSubject.next(undefined);
@@ -486,8 +490,9 @@ export class ChannelService<
486490
message_limit: this.messagePageSize,
487491
};
488492
this.sort = sort || { last_message_at: -1, updated_at: -1 };
489-
const result = await this.queryChannels(shouldSetActiveChannel);
490-
this.chatClientService.events$.subscribe(
493+
this.shouldSetActiveChannel = shouldSetActiveChannel;
494+
const result = await this.queryChannels(this.shouldSetActiveChannel);
495+
this.clientEventsSubscription = this.chatClientService.events$.subscribe(
491496
(notification) => void this.handleNotification(notification)
492497
);
493498
return result;
@@ -499,6 +504,7 @@ export class ChannelService<
499504
reset() {
500505
this.deselectActiveChannel();
501506
this.channelsSubject.next(undefined);
507+
this.clientEventsSubscription?.unsubscribe();
502508
}
503509

504510
/**
@@ -790,6 +796,18 @@ export class ChannelService<
790796

791797
private handleNotification(clientEvent: ClientEvent<T>) {
792798
switch (clientEvent.eventType) {
799+
case 'connection.recovered': {
800+
this.ngZone.run(() => {
801+
this.reset();
802+
void this.init(
803+
this.filters!,
804+
this.sort,
805+
this.options,
806+
this.shouldSetActiveChannel
807+
);
808+
});
809+
break;
810+
}
793811
case 'notification.message_new': {
794812
this.ngZone.run(() => {
795813
if (this.customNewMessageNotificationHandler) {

0 commit comments

Comments
 (0)