RED-6802, fixed the reconnect notification changing rapidly.

This commit is contained in:
George 2023-06-09 17:10:15 +03:00
parent 8ebd5f760d
commit 58d4ece28d
2 changed files with 60 additions and 27 deletions

View File

@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
import { connectionStatusTranslations } from '../../translations';
import { animate, state, style, transition, trigger } from '@angular/animations';
import { ErrorService } from '../error.service';
@ -19,6 +19,5 @@ import { ErrorService } from '../error.service';
})
export class ConnectionStatusComponent {
connectionStatusTranslations = connectionStatusTranslations;
constructor(readonly errorService: ErrorService) {}
protected readonly errorService = inject(ErrorService);
}

View File

@ -1,10 +1,11 @@
import { Injectable } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { fromEvent, merge, Observable, Subject } from 'rxjs';
import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
import { LoadingService } from '../loading';
import { delay, filter, map } from 'rxjs/operators';
import { filter, map, tap } from 'rxjs/operators';
import { NavigationStart, Router } from '@angular/router';
import { shareLast } from '../utils';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
export class CustomError {
readonly label: string;
@ -39,41 +40,72 @@ export class ErrorService {
readonly offline$: Observable<Event>;
readonly online$: Observable<Event>;
readonly connectionStatus$: Observable<string | undefined>;
private readonly _error$ = new Subject<ErrorType>();
readonly error$ = this._error$.pipe(filter(error => !error || !isOffline(error)));
private readonly _online$ = new Subject();
readonly #error$ = new Subject<ErrorType>();
readonly error$ = this.#error$.pipe(filter(error => !error || !isOffline(error)));
readonly #online$ = new Subject();
readonly #loadingService = inject(LoadingService);
readonly #router = inject(Router);
readonly #clearNotification$ = new Subject<undefined>();
// eslint-disable-next-line no-undef
#timeout: NodeJS.Timeout | undefined;
constructor(private readonly _loadingService: LoadingService, private readonly _router: Router) {
_router.events.pipe(filter(event => event instanceof NavigationStart)).subscribe(() => {
this.clear();
});
this.offline$ = this._offline();
this.online$ = this._online();
const removeIndicator$ = this.online$.pipe(
delay(3000),
map(() => undefined),
constructor() {
this.#router.events
.pipe(
filter(event => event instanceof NavigationStart),
tap(() => this.clear()),
takeUntilDestroyed(),
)
// eslint-disable-next-line rxjs/no-ignored-subscription
.subscribe();
this.offline$ = this.#offline();
this.online$ = this.#online();
this.connectionStatus$ = merge(this.online$, this.offline$, this.#clearNotification$.asObservable()).pipe(
map(event => event?.type),
filter(type => {
if (type === 'online') {
this.#setOnlineTimeout();
return false;
}
this.#clearOnlineTimeout();
return true;
}),
// used display-online when I manually generate a new event to bypass the above filter
map(type => (type === 'display-online' ? 'online' : type)),
);
this.connectionStatus$ = merge(this.online$, this.offline$, removeIndicator$).pipe(map(event => event?.type));
}
set(error: ErrorType): void {
this._loadingService.stop();
this._error$.next(error);
this.#loadingService.stop();
this.#error$.next(error);
}
setOnline(): void {
this._online$.next(true);
this.#online$.next(true);
}
clear(): void {
this._error$.next(undefined);
this.#error$.next(undefined);
}
private _offline() {
#setOnlineTimeout() {
this.#timeout ??= setTimeout(() => {
this.#online$.next(new Event('display-online'));
setTimeout(() => this.#clearNotification$.next(undefined), 3000);
}, 3000);
}
#clearOnlineTimeout() {
clearTimeout(this.#timeout);
this.#timeout = undefined;
}
#offline() {
return merge(
fromEvent(window, 'offline'),
this._error$.pipe(
this.#error$.pipe(
filter(isOffline),
map(() => new Event('offline')),
shareLast(),
@ -81,7 +113,9 @@ export class ErrorService {
);
}
private _online() {
return merge(fromEvent(window, 'online'), this._online$.pipe(map(() => new Event('online')))).pipe(shareLast());
#online() {
return merge(fromEvent(window, 'online'), this.#online$.pipe(map(v => (v instanceof Event ? v : new Event('online'))))).pipe(
shareLast(),
);
}
}