diff --git a/npm/ng-packs/packages/core/src/lib/core.module.ts b/npm/ng-packs/packages/core/src/lib/core.module.ts index 4bf3fae3a1..298e3c5352 100644 --- a/npm/ng-packs/packages/core/src/lib/core.module.ts +++ b/npm/ng-packs/packages/core/src/lib/core.module.ts @@ -38,6 +38,8 @@ import { ShortDateTimePipe } from './pipes/short-date-time.pipe'; import { ShortTimePipe } from './pipes/short-time.pipe'; import { ShortDatePipe } from './pipes/short-date.pipe'; import { TimeoutLimitedOAuthService } from './services/timeout-limited-oauth.service'; +import { QUEUE_MANAGER } from './tokens/queue.token'; +import { DefaultQueueManager } from './utils/queue'; export function storageFactory(): OAuthStorage { return oAuthStorage; @@ -193,6 +195,10 @@ export class CoreModule { useValue: localizationContributor(options.localizations), deps: [LocalizationService], }, + { + provide: QUEUE_MANAGER, + useClass: DefaultQueueManager, + }, ], }; } diff --git a/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts b/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts index e06c6d404c..f277bf50ee 100644 --- a/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts +++ b/npm/ng-packs/packages/core/src/lib/directives/permission.directive.ts @@ -2,6 +2,7 @@ import { AfterViewInit, ChangeDetectorRef, Directive, + Inject, Input, OnChanges, OnDestroy, @@ -12,6 +13,8 @@ import { import { ReplaySubject, Subscription } from 'rxjs'; import { distinctUntilChanged, take } from 'rxjs/operators'; import { PermissionService } from '../services/permission.service'; +import { QUEUE_MANAGER } from '../tokens/queue.token'; +import { QueueManager } from '../utils/queue'; @Directive({ selector: '[abpPermission]', @@ -32,6 +35,7 @@ export class PermissionDirective implements OnDestroy, OnChanges, AfterViewInit private vcRef: ViewContainerRef, private permissionService: PermissionService, private cdRef: ChangeDetectorRef, + @Inject(QUEUE_MANAGER) public queue: QueueManager, ) {} private check() { @@ -66,7 +70,7 @@ export class PermissionDirective implements OnDestroy, OnChanges, AfterViewInit } ngAfterViewInit() { - this.cdrSubject.pipe(take(1)).subscribe(() => this.cdRef.detectChanges()); + this.cdrSubject.pipe(take(1)).subscribe(() => this.queue.add(() => this.cdRef.detectChanges())); this.rendered = true; } } diff --git a/npm/ng-packs/packages/core/src/lib/tokens/index.ts b/npm/ng-packs/packages/core/src/lib/tokens/index.ts index da1ea9bdad..98985107f3 100644 --- a/npm/ng-packs/packages/core/src/lib/tokens/index.ts +++ b/npm/ng-packs/packages/core/src/lib/tokens/index.ts @@ -5,4 +5,5 @@ export * from './localization.token'; export * from './lodaer-delay.token'; export * from './manage-profile.token'; export * from './options.token'; +export * from './queue.token'; export * from './tenant-key.token'; diff --git a/npm/ng-packs/packages/core/src/lib/tokens/queue.token.ts b/npm/ng-packs/packages/core/src/lib/tokens/queue.token.ts new file mode 100644 index 0000000000..66c0efa7d6 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/tokens/queue.token.ts @@ -0,0 +1,4 @@ +import { QueueManager } from "../utils/queue"; +import { InjectionToken } from "@angular/core"; + +export const QUEUE_MANAGER = new InjectionToken("QUEUE_MANAGER"); diff --git a/npm/ng-packs/packages/core/src/lib/utils/index.ts b/npm/ng-packs/packages/core/src/lib/utils/index.ts index 56378f664f..1e218e0619 100644 --- a/npm/ng-packs/packages/core/src/lib/utils/index.ts +++ b/npm/ng-packs/packages/core/src/lib/utils/index.ts @@ -15,6 +15,7 @@ export * from './localization-utils'; export * from './multi-tenancy-utils'; export * from './number-utils'; export * from './object-utils'; +export * from './queue'; export * from './route-utils'; export * from './string-utils'; export * from './tree-utils'; diff --git a/npm/ng-packs/packages/core/src/lib/utils/queue.ts b/npm/ng-packs/packages/core/src/lib/utils/queue.ts new file mode 100644 index 0000000000..33525d83e1 --- /dev/null +++ b/npm/ng-packs/packages/core/src/lib/utils/queue.ts @@ -0,0 +1,48 @@ +export interface QueueManager { + add(fn: () => void): void; + init(interval: number, stackSize: number): void; +} + +export class DefaultQueueManager implements QueueManager { + private queue: Array<() => void> = []; + private isRunning = false; + private stack = 0; + private interval = 0; + private stackSize = 100; + + public init(interval: number, stackSize: number) { + this.interval = interval; + this.stackSize = stackSize; + } + + public add(fn: () => void) { + this.queue.push(fn); + this.run(); + } + + private run() { + if (this.isRunning) return; + this.stack++; + + this.isRunning = true; + + const fn = this.queue.shift(); + + if (!fn) { + this.isRunning = false; + return; + } + + fn(); + if (this.stack > this.stackSize) { + setTimeout(() => { + this.isRunning = false; + this.run(); + this.stack = 0; + }, this.interval); + } else { + this.isRunning = false; + this.run(); + } + } +}