@c8y/ngx-components 1016.0.379 → 1016.0.383

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.
Files changed (45) hide show
  1. package/NOTICES +1 -1
  2. package/core/range-display/range-display.component.d.ts +19 -1
  3. package/core/realtime/realtime-subject.service.d.ts +4 -0
  4. package/core/realtime/realtime.service.d.ts +10 -0
  5. package/device-protocols/device-protocols.factory.d.ts +14 -0
  6. package/device-protocols/device-protocols.guard.d.ts +12 -0
  7. package/device-protocols/device-protocols.module.d.ts +8 -0
  8. package/device-protocols/device-type-detail-edited.service.d.ts +8 -0
  9. package/device-protocols/device-type-detail.component.d.ts +12 -0
  10. package/device-protocols/device-type-detail.directive.d.ts +9 -0
  11. package/device-protocols/index.d.ts +6 -0
  12. package/esm2020/core/range-display/range-display.component.mjs +87 -4
  13. package/esm2020/core/realtime/realtime-subject.service.mjs +47 -4
  14. package/esm2020/core/realtime/realtime.service.mjs +15 -1
  15. package/esm2020/device-protocols/c8y-ngx-components-device-protocols.mjs +5 -0
  16. package/esm2020/device-protocols/device-protocols.factory.mjs +31 -0
  17. package/esm2020/device-protocols/device-protocols.guard.mjs +40 -0
  18. package/esm2020/device-protocols/device-protocols.module.mjs +38 -0
  19. package/esm2020/device-protocols/device-type-detail-edited.service.mjs +19 -0
  20. package/esm2020/device-protocols/device-type-detail.component.mjs +45 -0
  21. package/esm2020/device-protocols/device-type-detail.directive.mjs +19 -0
  22. package/esm2020/device-protocols/index.mjs +7 -0
  23. package/esm2020/ecosystem/application-properties/subscription-modal/subscription-modal.component.mjs +4 -1
  24. package/esm2020/upgrade/ng1/downgraded.services.mjs +6 -4
  25. package/esm2020/upgrade/ng1/index.mjs +6 -5
  26. package/esm2020/upgrade/upgrade.module.mjs +10 -10
  27. package/fesm2015/c8y-ngx-components-device-protocols.mjs +180 -0
  28. package/fesm2015/c8y-ngx-components-device-protocols.mjs.map +1 -0
  29. package/fesm2015/c8y-ngx-components-ecosystem.mjs +3 -0
  30. package/fesm2015/c8y-ngx-components-ecosystem.mjs.map +1 -1
  31. package/fesm2015/c8y-ngx-components-upgrade.mjs +91 -88
  32. package/fesm2015/c8y-ngx-components-upgrade.mjs.map +1 -1
  33. package/fesm2015/c8y-ngx-components.mjs +144 -4
  34. package/fesm2015/c8y-ngx-components.mjs.map +1 -1
  35. package/fesm2020/c8y-ngx-components-device-protocols.mjs +177 -0
  36. package/fesm2020/c8y-ngx-components-device-protocols.mjs.map +1 -0
  37. package/fesm2020/c8y-ngx-components-ecosystem.mjs +3 -0
  38. package/fesm2020/c8y-ngx-components-ecosystem.mjs.map +1 -1
  39. package/fesm2020/c8y-ngx-components-upgrade.mjs +90 -87
  40. package/fesm2020/c8y-ngx-components-upgrade.mjs.map +1 -1
  41. package/fesm2020/c8y-ngx-components.mjs +142 -4
  42. package/fesm2020/c8y-ngx-components.mjs.map +1 -1
  43. package/locales/locales.pot +1 -1
  44. package/package.json +10 -2
  45. package/upgrade/ng1/downgraded.services.d.ts +1 -0
@@ -3897,6 +3897,20 @@ class RealtimeService {
3897
3897
  get active() {
3898
3898
  return this.isActive.value;
3899
3899
  }
3900
+ /**
3901
+ * An observable emitting a value in case the realtime connection has been interrupted.
3902
+ * Can be used to reload data of e.g. a datapoint graph that wasn't received while realtime was interrupted.
3903
+ */
3904
+ get reconnect$() {
3905
+ return this.realtimeSubject.reconnect$;
3906
+ }
3907
+ /**
3908
+ * An observable emitting either `connected` or `disconnected` depending on the state of the realtime connection.
3909
+ * Can be used to e.g. inform the user about the interrupted realtime connection.
3910
+ */
3911
+ get connectionStatus$() {
3912
+ return this.realtimeSubject.connectionStatus$;
3913
+ }
3900
3914
  /**
3901
3915
  * Get an Observable of all realtime notifications.
3902
3916
  *
@@ -24227,6 +24241,13 @@ class RangeDisplayComponent {
24227
24241
  this.sanitizer = sanitizer;
24228
24242
  this.config = {};
24229
24243
  this.display = 'full';
24244
+ this.currentRangeWidthChanged = new Subject();
24245
+ // width of current range is changing within 150ms, see style declaration for .range-display__range__current
24246
+ this.CURRENT_RANGE_WIDTH_TRANSITION_TIME = 150;
24247
+ this.DEFAULT_TOOLTIP_SHIFT = '50%';
24248
+ this.MIN_TOOLTIP_SHIFT = 10;
24249
+ this.tooltipShift = this.DEFAULT_TOOLTIP_SHIFT;
24250
+ this.destroyed$ = new Subject();
24230
24251
  }
24231
24252
  get inlineStyle() {
24232
24253
  this.config = this.config || {};
@@ -24242,6 +24263,8 @@ class RangeDisplayComponent {
24242
24263
  return this.sanitizer.bypassSecurityTrustStyle(`
24243
24264
  --range-min: ${this.config.min};
24244
24265
  --range-max: ${this.config.max};
24266
+ --range-display-tooltip-translate: translate(${this.tooltipShift}, -56px);
24267
+ --range-display-tooltip-bg: ${this.getTooltipBackground()};
24245
24268
  --full-range: ${this.config.max - this.config.min};
24246
24269
  --measurement-target: ${((this.config.target - this.config.min) * 100) / (this.config.max - this.config.min)}%;
24247
24270
  --measurement-current: ${((this.config.current - this.config.min) * 100) / (this.config.max - this.config.min)}%;
@@ -24255,6 +24278,20 @@ class RangeDisplayComponent {
24255
24278
  100}%;
24256
24279
  `);
24257
24280
  }
24281
+ ngOnChanges() {
24282
+ // It's necessary to handle tooltip shifting both in OnChanges and AfterViewInit. In case of Linear gauge widget, view is
24283
+ // rendered first (so as elements needed for calculating shifting) and config orientation is set later on.
24284
+ // In other cases it's possible that orientation is defined on initialization of class and view elements are rendered later.
24285
+ this.setupTooltipShiftingIfPossible();
24286
+ }
24287
+ ngAfterViewInit() {
24288
+ this.setupTooltipShiftingIfPossible();
24289
+ }
24290
+ ngOnDestroy() {
24291
+ this.currentRangeWidthObserver?.disconnect();
24292
+ this.destroyed$.next();
24293
+ this.destroyed$.complete();
24294
+ }
24258
24295
  checkTarget() {
24259
24296
  return (this.config.target !== undefined &&
24260
24297
  this.config.target !== null &&
@@ -24282,12 +24319,64 @@ class RangeDisplayComponent {
24282
24319
  isRangeDisplayed(rangeMin, rangeMax) {
24283
24320
  return rangeMin === 0 || rangeMax === 0 || (rangeMin && rangeMax);
24284
24321
  }
24322
+ setupTooltipShifting() {
24323
+ this.currentRangeWidthObserver = new ResizeObserver(([val]) => {
24324
+ if (getComputedStyle(val.target, null).display === 'block') {
24325
+ this.currentRangeWidthChanged.next(val.target);
24326
+ }
24327
+ });
24328
+ this.currentRangeWidthObserver.observe(this.currentRangeElement.nativeElement);
24329
+ this.currentRangeWidthChanged
24330
+ .pipe(debounceTime(this.CURRENT_RANGE_WIDTH_TRANSITION_TIME), map((rangeElement) => parseInt(getComputedStyle(rangeElement, null).width)), distinctUntilChanged(), takeUntil(this.destroyed$))
24331
+ .subscribe(rangeElementWidth => {
24332
+ this.setTooltipShiftValue(rangeElementWidth);
24333
+ });
24334
+ }
24335
+ setTooltipShiftValue(rangeElementWidth) {
24336
+ const tooltipWidth = parseInt(getComputedStyle(this.currentRangeElement.nativeElement, ':after').width);
24337
+ const currentRangeWidth = rangeElementWidth;
24338
+ const rangeDisplayWidth = parseInt(getComputedStyle(this.rangeDisplay.nativeElement, null).getPropertyValue('width'));
24339
+ const rangeDisplayPaddingLeft = parseInt(getComputedStyle(this.rangeDisplay.nativeElement, null).getPropertyValue('padding-left'));
24340
+ const tooltipOverflowsLeftEdge = tooltipWidth / 2 > rangeDisplayPaddingLeft + currentRangeWidth;
24341
+ const tooltipOverflowsRightEdge = tooltipWidth / 2 > rangeDisplayWidth - rangeDisplayPaddingLeft - currentRangeWidth;
24342
+ if (tooltipOverflowsLeftEdge) {
24343
+ this.tooltipShift = `${tooltipWidth - this.MIN_TOOLTIP_SHIFT}px`;
24344
+ }
24345
+ else if (tooltipOverflowsRightEdge) {
24346
+ this.tooltipShift = `${this.MIN_TOOLTIP_SHIFT}px`;
24347
+ }
24348
+ else {
24349
+ this.tooltipShift = this.DEFAULT_TOOLTIP_SHIFT;
24350
+ }
24351
+ }
24352
+ setupTooltipShiftingIfPossible() {
24353
+ if (this.config?.orientation === 'horizontal' &&
24354
+ !this.currentRangeWidthObserver &&
24355
+ this.rangeDisplay &&
24356
+ this.currentRangeElement) {
24357
+ this.setupTooltipShifting();
24358
+ }
24359
+ }
24360
+ getTooltipBackground() {
24361
+ const current = this.config.current;
24362
+ switch (true) {
24363
+ case this.isValueInRange(current, this.config.redRangeMin, this.config.redRangeMax):
24364
+ return 'var(--input-validation-error, #E0000E)';
24365
+ case this.isValueInRange(current, this.config.yellowRangeMin, this.config.yellowRangeMax):
24366
+ return 'var(--input-validation-warning, #FF801F)';
24367
+ default:
24368
+ return 'var(--gray-3, #394852)';
24369
+ }
24370
+ }
24371
+ isValueInRange(value, min, max) {
24372
+ return min != null && max != null && value >= min && value <= max;
24373
+ }
24285
24374
  }
24286
24375
  RangeDisplayComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: RangeDisplayComponent, deps: [{ token: i2$5.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
24287
- RangeDisplayComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: RangeDisplayComponent, selector: "c8y-range-display", inputs: { config: "config", display: "display" }, host: { properties: { "attr.style": "this.inlineStyle" } }, ngImport: i0, template: "<div [ngClass]=\"{ 'range-display--vertical': config.orientation === 'vertical',\n 'range-display--compact' : display ==='compact',\n 'range-display--inline' : display ==='inline' }\" \n attr.data-label=\"{{ config.unit }}\"\n>\n <div class=\"range-display\">\n <div class=\"range-display__range\">\n <div class=\"range-display__range__unit\">\n {{ config.unit }}\n </div>\n <div *ngIf=\"isYellowRangeDisplayed()\" class=\"range-display__range__min\"></div>\n <div *ngIf=\"isRedRangeDisplayed()\" class=\"range-display__range__max\"></div>\n <div\n *ngIf=\"checkTarget()\"\n class=\"range-display__range__target\"\n attr.data-label=\"{{ config.target }} {{ config.unit }}\"\n title=\"{{ 'Target' | translate }}: {{ config.target }} {{ config.unit }}\"\n ></div>\n <div\n *ngIf=\"\n config.current != undefined &&\n config.current >= config.min &&\n config.current <= config.max\n \"\n class=\"range-display__range__current\"\n attr.data-label=\"{{ config.current }} {{ config.unit }} &#xa; {{ config.time | c8yDate }}\"\n title=\"{{ 'Current' | translate }}: {{ config.current }} {{ config.unit }} | {{\n config.time | c8yDate\n }}\"\n ></div>\n </div>\n <div class=\"range-display__ruler\">\n <div\n *ngFor=\"let x of [].constructor(10); let index = index; trackBy: trackByIndex\"\n attr.data-label=\"{{ rulerCalc(index) }}\"\n class=\"range-display__tick\"\n ></div>\n <div attr.data-label=\"{{ config.max || 100 | number }}\" class=\"range-display__tick\"></div>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i2$1.DecimalPipe, name: "number" }, { kind: "pipe", type: DatePipe, name: "c8yDate" }] });
24376
+ RangeDisplayComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.0.6", type: RangeDisplayComponent, selector: "c8y-range-display", inputs: { config: "config", display: "display" }, host: { properties: { "attr.style": "this.inlineStyle" } }, viewQueries: [{ propertyName: "rangeDisplay", first: true, predicate: ["rangeDisplay"], descendants: true }, { propertyName: "currentRangeElement", first: true, predicate: ["currentRangeElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n [ngClass]=\"{\n 'range-display--vertical': config.orientation === 'vertical',\n 'range-display--compact': display === 'compact',\n 'range-display--inline': display === 'inline'\n }\"\n attr.data-label=\"{{ config.unit }}\"\n>\n <div\n class=\"range-display\"\n #rangeDisplay\n >\n <div class=\"range-display__range\">\n <div class=\"range-display__range__unit\">\n {{ config.unit }}\n </div>\n <div\n *ngIf=\"isYellowRangeDisplayed()\"\n class=\"range-display__range__min\"\n ></div>\n <div\n *ngIf=\"isRedRangeDisplayed()\"\n class=\"range-display__range__max\"\n ></div>\n <div\n *ngIf=\"checkTarget()\"\n class=\"range-display__range__target\"\n attr.data-label=\"{{ config.target }} {{ config.unit }}\"\n title=\"{{ 'Target' | translate }}: {{ config.target }} {{ config.unit }}\"\n ></div>\n <div\n [ngStyle]=\"{\n display:\n config.current != undefined &&\n config.current >= config.min &&\n config.current <= config.max\n ? 'block'\n : 'none'\n }\"\n #currentRangeElement\n class=\"range-display__range__current\"\n attr.data-label=\"{{ config.current }} {{ config.unit }} &#xa;{{ config.time | c8yDate }}\"\n title=\"{{ 'Current' | translate }}: {{ config.current }} {{ config.unit }} | {{\n config.time | c8yDate\n }}\"\n ></div>\n </div>\n <div class=\"range-display__ruler\">\n <div\n *ngFor=\"let x of [].constructor(10); let index = index; trackBy: trackByIndex\"\n attr.data-label=\"{{ rulerCalc(index) }}\"\n class=\"range-display__tick\"\n ></div>\n <div\n attr.data-label=\"{{ config.max || 100 | number }}\"\n class=\"range-display__tick\"\n ></div>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i2$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i2$1.DecimalPipe, name: "number" }, { kind: "pipe", type: DatePipe, name: "c8yDate" }] });
24288
24377
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: RangeDisplayComponent, decorators: [{
24289
24378
  type: Component,
24290
- args: [{ selector: 'c8y-range-display', template: "<div [ngClass]=\"{ 'range-display--vertical': config.orientation === 'vertical',\n 'range-display--compact' : display ==='compact',\n 'range-display--inline' : display ==='inline' }\" \n attr.data-label=\"{{ config.unit }}\"\n>\n <div class=\"range-display\">\n <div class=\"range-display__range\">\n <div class=\"range-display__range__unit\">\n {{ config.unit }}\n </div>\n <div *ngIf=\"isYellowRangeDisplayed()\" class=\"range-display__range__min\"></div>\n <div *ngIf=\"isRedRangeDisplayed()\" class=\"range-display__range__max\"></div>\n <div\n *ngIf=\"checkTarget()\"\n class=\"range-display__range__target\"\n attr.data-label=\"{{ config.target }} {{ config.unit }}\"\n title=\"{{ 'Target' | translate }}: {{ config.target }} {{ config.unit }}\"\n ></div>\n <div\n *ngIf=\"\n config.current != undefined &&\n config.current >= config.min &&\n config.current <= config.max\n \"\n class=\"range-display__range__current\"\n attr.data-label=\"{{ config.current }} {{ config.unit }} &#xa; {{ config.time | c8yDate }}\"\n title=\"{{ 'Current' | translate }}: {{ config.current }} {{ config.unit }} | {{\n config.time | c8yDate\n }}\"\n ></div>\n </div>\n <div class=\"range-display__ruler\">\n <div\n *ngFor=\"let x of [].constructor(10); let index = index; trackBy: trackByIndex\"\n attr.data-label=\"{{ rulerCalc(index) }}\"\n class=\"range-display__tick\"\n ></div>\n <div attr.data-label=\"{{ config.max || 100 | number }}\" class=\"range-display__tick\"></div>\n </div>\n </div>\n</div>\n" }]
24379
+ args: [{ selector: 'c8y-range-display', template: "<div\n [ngClass]=\"{\n 'range-display--vertical': config.orientation === 'vertical',\n 'range-display--compact': display === 'compact',\n 'range-display--inline': display === 'inline'\n }\"\n attr.data-label=\"{{ config.unit }}\"\n>\n <div\n class=\"range-display\"\n #rangeDisplay\n >\n <div class=\"range-display__range\">\n <div class=\"range-display__range__unit\">\n {{ config.unit }}\n </div>\n <div\n *ngIf=\"isYellowRangeDisplayed()\"\n class=\"range-display__range__min\"\n ></div>\n <div\n *ngIf=\"isRedRangeDisplayed()\"\n class=\"range-display__range__max\"\n ></div>\n <div\n *ngIf=\"checkTarget()\"\n class=\"range-display__range__target\"\n attr.data-label=\"{{ config.target }} {{ config.unit }}\"\n title=\"{{ 'Target' | translate }}: {{ config.target }} {{ config.unit }}\"\n ></div>\n <div\n [ngStyle]=\"{\n display:\n config.current != undefined &&\n config.current >= config.min &&\n config.current <= config.max\n ? 'block'\n : 'none'\n }\"\n #currentRangeElement\n class=\"range-display__range__current\"\n attr.data-label=\"{{ config.current }} {{ config.unit }} &#xa;{{ config.time | c8yDate }}\"\n title=\"{{ 'Current' | translate }}: {{ config.current }} {{ config.unit }} | {{\n config.time | c8yDate\n }}\"\n ></div>\n </div>\n <div class=\"range-display__ruler\">\n <div\n *ngFor=\"let x of [].constructor(10); let index = index; trackBy: trackByIndex\"\n attr.data-label=\"{{ rulerCalc(index) }}\"\n class=\"range-display__tick\"\n ></div>\n <div\n attr.data-label=\"{{ config.max || 100 | number }}\"\n class=\"range-display__tick\"\n ></div>\n </div>\n </div>\n</div>\n" }]
24291
24380
  }], ctorParameters: function () { return [{ type: i2$5.DomSanitizer }]; }, propDecorators: { config: [{
24292
24381
  type: Input
24293
24382
  }], display: [{
@@ -24295,6 +24384,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.6", ngImpor
24295
24384
  }], inlineStyle: [{
24296
24385
  type: HostBinding,
24297
24386
  args: ['attr.style']
24387
+ }], rangeDisplay: [{
24388
+ type: ViewChild,
24389
+ args: ['rangeDisplay', { static: false }]
24390
+ }], currentRangeElement: [{
24391
+ type: ViewChild,
24392
+ args: ['currentRangeElement', { static: false }]
24298
24393
  }] } });
24299
24394
 
24300
24395
  /**
@@ -25555,6 +25650,8 @@ class RealtimeSubjectService {
25555
25650
  constructor(realtime) {
25556
25651
  this.realtime = realtime;
25557
25652
  this.subjects$ = new Map();
25653
+ this.reconnect$ = this.createObservableForReconnect().pipe(share());
25654
+ this.connectionStatus$ = this.createObservableForConnectionStatus().pipe(distinctUntilChanged(), shareReplay({ refCount: true, bufferSize: 1 }));
25558
25655
  }
25559
25656
  getObservableForChannel(channel) {
25560
25657
  if (this.subjects$.has(channel)) {
@@ -25567,7 +25664,7 @@ class RealtimeSubjectService {
25567
25664
  }
25568
25665
  createObservableForChannel(channel, realtime) {
25569
25666
  return new Observable(observer => {
25570
- const realtimeSubscription = realtime.subscribe(channel, msg => {
25667
+ let realtimeSubscription = realtime.subscribe(channel, msg => {
25571
25668
  const data = {
25572
25669
  channel: msg.channel,
25573
25670
  data: msg.data.data,
@@ -25576,13 +25673,54 @@ class RealtimeSubjectService {
25576
25673
  };
25577
25674
  observer.next(data);
25578
25675
  });
25676
+ /**
25677
+ * In (rare) case of a re-handshake, resubscribe valid subscriptions.
25678
+ * @see https://docs.cometd.org/current/reference/#_javascript_subscribe_resubscribe
25679
+ */
25680
+ const reconnectSubscription = this.reconnect$.subscribe(() => {
25681
+ try {
25682
+ realtimeSubscription = this.realtime.resubscribe(realtimeSubscription);
25683
+ }
25684
+ catch (e) {
25685
+ console.warn(`Failed to resubscribe to channel: "${channel}" after reconnect.`, e);
25686
+ observer.error(e);
25687
+ }
25688
+ });
25579
25689
  return {
25580
- unsubscribe() {
25690
+ unsubscribe: () => {
25691
+ reconnectSubscription.unsubscribe();
25581
25692
  realtime.unsubscribe(realtimeSubscription);
25582
25693
  }
25583
25694
  };
25584
25695
  });
25585
25696
  }
25697
+ createObservableForReconnect() {
25698
+ return new Observable(observer => {
25699
+ const handle = this.realtime.addHandshakeListener(msg => {
25700
+ if (msg.successful && msg.reestablish) {
25701
+ observer.next();
25702
+ }
25703
+ });
25704
+ return {
25705
+ unsubscribe: () => {
25706
+ this.realtime.removeListener(handle);
25707
+ }
25708
+ };
25709
+ });
25710
+ }
25711
+ createObservableForConnectionStatus() {
25712
+ return new Observable(observer => {
25713
+ observer.next(!this.realtime.isDisconnected() ? 'connected' : 'disconnected');
25714
+ const handle = this.realtime.addConnectListener(msg => {
25715
+ observer.next(msg.successful ? 'connected' : 'disconnected');
25716
+ });
25717
+ return {
25718
+ unsubscribe: () => {
25719
+ this.realtime.removeListener(handle);
25720
+ }
25721
+ };
25722
+ });
25723
+ }
25586
25724
  }
25587
25725
  RealtimeSubjectService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: RealtimeSubjectService, deps: [{ token: i1$2.Realtime }], target: i0.ɵɵFactoryTarget.Injectable });
25588
25726
  RealtimeSubjectService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.6", ngImport: i0, type: RealtimeSubjectService, providedIn: 'root' });