@banta/sdk 4.7.10 → 4.7.11

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.
@@ -2,6 +2,8 @@ import { Observable, Subject, BehaviorSubject, Subscription } from 'rxjs';
2
2
  import { publish, take } from 'rxjs/operators';
3
3
  import * as i0 from '@angular/core';
4
4
  import { Component, Input, ViewChild, Pipe, Inject, Optional, Output, HostBinding, NgModule, ViewChildren, Directive, TemplateRef, ContentChild, Injectable } from '@angular/core';
5
+ import * as i1 from 'projects/sdk/src/lib/common/timer-pool.service';
6
+ import { TimerPool } from 'projects/sdk/src/lib/common/timer-pool.service';
5
7
  import * as i2 from '@angular/common';
6
8
  import { CommonModule } from '@angular/common';
7
9
  import * as i2$1 from '@angular/material/icon';
@@ -9,7 +11,7 @@ import { MatIconModule } from '@angular/material/icon';
9
11
  import * as marked from 'marked';
10
12
  import createDOMPurify from 'dompurify';
11
13
  import twemoji$1 from 'twemoji';
12
- import * as i1 from '@angular/platform-browser';
14
+ import * as i1$1 from '@angular/platform-browser';
13
15
  import * as i3 from '@angular/cdk/bidi';
14
16
  import * as i4 from '@angular/material/progress-spinner';
15
17
  import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
@@ -21,7 +23,7 @@ import * as i6$1 from '@angular/material/form-field';
21
23
  import { MatFormFieldModule } from '@angular/material/form-field';
22
24
  import * as i7 from '@angular/material/input';
23
25
  import { MatInputModule } from '@angular/material/input';
24
- import * as i1$1 from '@angular/cdk/overlay';
26
+ import * as i1$2 from '@angular/cdk/overlay';
25
27
  import { OverlayModule } from '@angular/cdk/overlay';
26
28
  import * as i4$2 from '@angular/cdk/portal';
27
29
  import { PortalModule } from '@angular/cdk/portal';
@@ -32,7 +34,7 @@ import * as i7$1 from '@angular/material/menu';
32
34
  import { MatMenuModule } from '@angular/material/menu';
33
35
  import * as i11 from '@angular/material/tooltip';
34
36
  import { MatTooltipModule } from '@angular/material/tooltip';
35
- import * as i1$2 from '@banta/common';
37
+ import * as i1$3 from '@banta/common';
36
38
  import { CommentsOrder, SocketRPC, RpcEvent, DurableSocket } from '@banta/common';
37
39
  import * as i2$3 from '@angular/router';
38
40
  import * as i3$3 from '@angular/material/snack-bar';
@@ -57,20 +59,26 @@ function lazyConnection(options) {
57
59
  }
58
60
 
59
61
  class TimestampComponent {
60
- constructor() {
62
+ constructor(timerPool) {
63
+ this.timerPool = timerPool;
61
64
  this.relative = '';
62
65
  this.tooltip = '';
63
- this.updateInterval = null;
66
+ this.timerInterval = 0;
67
+ this._destroyed = false;
64
68
  this.showAbsolute = false;
65
69
  }
66
70
  ngOnDestroy() {
67
- if (this.updateInterval)
68
- clearInterval(this.updateInterval);
71
+ var _a;
72
+ this._destroyed = true;
73
+ (_a = this.timerUnsubscribe) === null || _a === void 0 ? void 0 : _a.call(this);
69
74
  }
70
75
  get value() {
71
76
  return this._value;
72
77
  }
73
78
  update() {
79
+ var _a;
80
+ if (this._destroyed)
81
+ return;
74
82
  let now = Date.now();
75
83
  let diff = now - this.value;
76
84
  let minute = 1000 * 60;
@@ -132,18 +140,23 @@ class TimestampComponent {
132
140
  updateTime = 1000 * 30;
133
141
  }
134
142
  if (typeof window !== 'undefined') {
135
- clearInterval(this.updateInterval);
136
- if (updateTime > 0) {
137
- this.updateInterval = setInterval(() => this.update());
143
+ if (this.timerInterval !== updateTime) {
144
+ this.timerInterval = updateTime;
145
+ (_a = this.timerUnsubscribe) === null || _a === void 0 ? void 0 : _a.call(this);
146
+ if (updateTime > 0) {
147
+ this.timerUnsubscribe = this.timerPool.addTimer(updateTime, () => this.update());
148
+ }
138
149
  }
139
150
  }
140
151
  }
141
152
  set value(v) {
142
- this._value = v;
143
- this.update();
153
+ if (this._value !== v) {
154
+ this._value = v;
155
+ this.update();
156
+ }
144
157
  }
145
158
  }
146
- TimestampComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TimestampComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
159
+ TimestampComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TimestampComponent, deps: [{ token: i1.TimerPool }], target: i0.ɵɵFactoryTarget.Component });
147
160
  TimestampComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: TimestampComponent, selector: "banta-timestamp", inputs: { value: "value" }, ngImport: i0, template: `
148
161
  <span *ngIf="showAbsolute" [title]="value | date : 'short'">
149
162
  {{value | date : 'shortDate'}}
@@ -162,7 +175,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
162
175
  {{relative}}
163
176
  </span>
164
177
  ` }]
165
- }], propDecorators: { value: [{
178
+ }], ctorParameters: function () { return [{ type: i1.TimerPool }]; }, propDecorators: { value: [{
166
179
  type: Input
167
180
  }] } });
168
181
 
@@ -265,7 +278,7 @@ class BantaMarkdownToHtmlPipe {
265
278
  }));
266
279
  }
267
280
  }
268
- BantaMarkdownToHtmlPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: BantaMarkdownToHtmlPipe, deps: [{ token: i1.DomSanitizer }, { token: BANTA_SDK_OPTIONS, optional: true }], target: i0.ɵɵFactoryTarget.Pipe });
281
+ BantaMarkdownToHtmlPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: BantaMarkdownToHtmlPipe, deps: [{ token: i1$1.DomSanitizer }, { token: BANTA_SDK_OPTIONS, optional: true }], target: i0.ɵɵFactoryTarget.Pipe });
269
282
  BantaMarkdownToHtmlPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "14.2.12", ngImport: i0, type: BantaMarkdownToHtmlPipe, name: "markdownToHtml" });
270
283
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: BantaMarkdownToHtmlPipe, decorators: [{
271
284
  type: Pipe,
@@ -273,7 +286,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
273
286
  name: 'markdownToHtml'
274
287
  }]
275
288
  }], ctorParameters: function () {
276
- return [{ type: i1.DomSanitizer }, { type: undefined, decorators: [{
289
+ return [{ type: i1$1.DomSanitizer }, { type: undefined, decorators: [{
277
290
  type: Inject,
278
291
  args: [BANTA_SDK_OPTIONS]
279
292
  }, {
@@ -291,14 +304,14 @@ class BantaTrustResourceUrlPipe {
291
304
  return this.sanitizer.bypassSecurityTrustResourceUrl(value);
292
305
  }
293
306
  }
294
- BantaTrustResourceUrlPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: BantaTrustResourceUrlPipe, deps: [{ token: i1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe });
307
+ BantaTrustResourceUrlPipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: BantaTrustResourceUrlPipe, deps: [{ token: i1$1.DomSanitizer }], target: i0.ɵɵFactoryTarget.Pipe });
295
308
  BantaTrustResourceUrlPipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "14.2.12", ngImport: i0, type: BantaTrustResourceUrlPipe, name: "trustResourceUrl" });
296
309
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: BantaTrustResourceUrlPipe, decorators: [{
297
310
  type: Pipe,
298
311
  args: [{
299
312
  name: 'trustResourceUrl'
300
313
  }]
301
- }], ctorParameters: function () { return [{ type: i1.DomSanitizer }]; } });
314
+ }], ctorParameters: function () { return [{ type: i1$1.DomSanitizer }]; } });
302
315
 
303
316
  class BantaMentionLinkerPipe {
304
317
  transform(value, links) {
@@ -521,6 +534,14 @@ const COMPONENTS$3 = [
521
534
  BantaAttachmentsComponent
522
535
  ];
523
536
  class BantaCommonModule {
537
+ static forRoot() {
538
+ return {
539
+ ngModule: BantaCommonModule,
540
+ providers: [
541
+ TimerPool
542
+ ]
543
+ };
544
+ }
524
545
  }
525
546
  BantaCommonModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: BantaCommonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
526
547
  BantaCommonModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.12", ngImport: i0, type: BantaCommonModule, declarations: [TimestampComponent,
@@ -7138,13 +7159,13 @@ class EmojiSelectorPanelComponent {
7138
7159
  this.categories = this.pairs(cats).map(pair => pair[1]);
7139
7160
  }
7140
7161
  }
7141
- EmojiSelectorPanelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: EmojiSelectorPanelComponent, deps: [{ token: i1.DomSanitizer }, { token: BANTA_SDK_OPTIONS, optional: true }], target: i0.ɵɵFactoryTarget.Component });
7162
+ EmojiSelectorPanelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: EmojiSelectorPanelComponent, deps: [{ token: i1$1.DomSanitizer }, { token: BANTA_SDK_OPTIONS, optional: true }], target: i0.ɵɵFactoryTarget.Component });
7142
7163
  EmojiSelectorPanelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: EmojiSelectorPanelComponent, selector: "emoji-selector-panel", outputs: { selected: "selected" }, ngImport: i0, template: "<div class=\"search-box\" *ngIf=\"searchVisible\">\r\n\t<a mat-icon-button href=\"javascript:;\" (click)=\"hideSearch()\">\r\n\t\t<mat-icon>arrow_back</mat-icon>\r\n\t</a>\r\n\t<mat-form-field appearance=\"outline\" floatLabel=\"always\">\r\n\t\t<mat-label>Search for emoji</mat-label>\r\n\t\t<input name=\"search\" type=\"text\" matInput placeholder=\"Start typing\" [(ngModel)]=\"searchQuery\" />\r\n\t</mat-form-field>\r\n</div>\r\n\r\n<div class=\"selector\">\r\n\t<ng-container *ngIf=\"searchVisible\">\r\n\t\t<div class=\"emoji-list\">\r\n\t\t\t<a href=\"javascript:;\" (click)=\"select(emoji.char)\" \r\n\t\t\t\t*ngFor=\"let emoji of searchResults\" [innerHtml]=\"emoji.html || ''\">\r\n\t\t\t</a>\r\n\t\t</div>\r\n\t</ng-container>\r\n\t<ng-container *ngIf=\"!searchVisible\">\r\n\t\t<div class=\"categories\">\r\n\t\t\t<ng-container *ngIf=\"!searchVisible\">\r\n\t\t\t\t<a [title]=\"humanize(category.name)\" [class.active]=\"activeCategory === category.name\" mat-icon-button *ngFor=\"let category of categories\" (click)=\"activeCategory = category.name\">\r\n\t\t\t\t\t<mat-icon>{{category.icon}}</mat-icon>\r\n\t\t\t\t</a>\r\n\r\n\t\t\t\t<a title=\"Search\" [class.active] mat-icon-button (click)=\"showSearch()\">\r\n\t\t\t\t\t<mat-icon>search</mat-icon>\r\n\t\t\t\t</a>\r\n\t\t\t</ng-container>\r\n\t\t</div>\r\n\t\t<ng-container *ngFor=\"let category of categories\">\r\n\t\t\t<div class=\"emoji-list\" *ngIf=\"activeCategory && activeCategory == category.name\">\r\n\t\t\t\t<a href=\"javascript:;\" (click)=\"select(emoji.char)\" \r\n\t\t\t\t\t*ngFor=\"let emoji of category.emojis\" [innerHtml]=\"emoji.html || ''\">\r\n\t\t\t\t</a>\r\n\t\t\t</div>\r\n\t\t</ng-container>\r\n\t</ng-container>\r\n</div>", styles: [":host{background:#111;color:#fff;border:1px solid #333;border-radius:5px;padding:.5em;width:calc(9*(32px + 1em));max-width:calc(100vw - 1.5em - 5px)}.selector{display:flex;flex-direction:column}.categories a{opacity:.25;transition:.4s opacity ease-in-out}.categories a:hover{opacity:.5}.categories a.active{opacity:1}.emoji-list{flex-grow:1;overflow-y:auto;height:20em}.emoji-list a{display:inline-block;padding:2px;margin:4px;background-color:#111}.emoji-list a ::ng-deep .emoji{width:32px;height:32px}.emoji-list a:hover{background-color:#333}.search-box{display:flex;align-items:baseline}.search-box mat-form-field{flex-grow:1}@media (max-width: 500px){.selector{flex-direction:row;height:27em}.emoji-list{height:auto}}:host-context(.banta-mobile) .selector{flex-direction:row;height:27em}:host-context(.banta-mobile) .emoji-list{height:auto}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i6.MatAnchor, selector: "a[mat-button], a[mat-raised-button], a[mat-icon-button], a[mat-fab], a[mat-mini-fab], a[mat-stroked-button], a[mat-flat-button]", inputs: ["disabled", "disableRipple", "color", "tabIndex"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6$1.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }] });
7143
7164
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: EmojiSelectorPanelComponent, decorators: [{
7144
7165
  type: Component,
7145
7166
  args: [{ selector: 'emoji-selector-panel', template: "<div class=\"search-box\" *ngIf=\"searchVisible\">\r\n\t<a mat-icon-button href=\"javascript:;\" (click)=\"hideSearch()\">\r\n\t\t<mat-icon>arrow_back</mat-icon>\r\n\t</a>\r\n\t<mat-form-field appearance=\"outline\" floatLabel=\"always\">\r\n\t\t<mat-label>Search for emoji</mat-label>\r\n\t\t<input name=\"search\" type=\"text\" matInput placeholder=\"Start typing\" [(ngModel)]=\"searchQuery\" />\r\n\t</mat-form-field>\r\n</div>\r\n\r\n<div class=\"selector\">\r\n\t<ng-container *ngIf=\"searchVisible\">\r\n\t\t<div class=\"emoji-list\">\r\n\t\t\t<a href=\"javascript:;\" (click)=\"select(emoji.char)\" \r\n\t\t\t\t*ngFor=\"let emoji of searchResults\" [innerHtml]=\"emoji.html || ''\">\r\n\t\t\t</a>\r\n\t\t</div>\r\n\t</ng-container>\r\n\t<ng-container *ngIf=\"!searchVisible\">\r\n\t\t<div class=\"categories\">\r\n\t\t\t<ng-container *ngIf=\"!searchVisible\">\r\n\t\t\t\t<a [title]=\"humanize(category.name)\" [class.active]=\"activeCategory === category.name\" mat-icon-button *ngFor=\"let category of categories\" (click)=\"activeCategory = category.name\">\r\n\t\t\t\t\t<mat-icon>{{category.icon}}</mat-icon>\r\n\t\t\t\t</a>\r\n\r\n\t\t\t\t<a title=\"Search\" [class.active] mat-icon-button (click)=\"showSearch()\">\r\n\t\t\t\t\t<mat-icon>search</mat-icon>\r\n\t\t\t\t</a>\r\n\t\t\t</ng-container>\r\n\t\t</div>\r\n\t\t<ng-container *ngFor=\"let category of categories\">\r\n\t\t\t<div class=\"emoji-list\" *ngIf=\"activeCategory && activeCategory == category.name\">\r\n\t\t\t\t<a href=\"javascript:;\" (click)=\"select(emoji.char)\" \r\n\t\t\t\t\t*ngFor=\"let emoji of category.emojis\" [innerHtml]=\"emoji.html || ''\">\r\n\t\t\t\t</a>\r\n\t\t\t</div>\r\n\t\t</ng-container>\r\n\t</ng-container>\r\n</div>", styles: [":host{background:#111;color:#fff;border:1px solid #333;border-radius:5px;padding:.5em;width:calc(9*(32px + 1em));max-width:calc(100vw - 1.5em - 5px)}.selector{display:flex;flex-direction:column}.categories a{opacity:.25;transition:.4s opacity ease-in-out}.categories a:hover{opacity:.5}.categories a.active{opacity:1}.emoji-list{flex-grow:1;overflow-y:auto;height:20em}.emoji-list a{display:inline-block;padding:2px;margin:4px;background-color:#111}.emoji-list a ::ng-deep .emoji{width:32px;height:32px}.emoji-list a:hover{background-color:#333}.search-box{display:flex;align-items:baseline}.search-box mat-form-field{flex-grow:1}@media (max-width: 500px){.selector{flex-direction:row;height:27em}.emoji-list{height:auto}}:host-context(.banta-mobile) .selector{flex-direction:row;height:27em}:host-context(.banta-mobile) .emoji-list{height:auto}\n"] }]
7146
7167
  }], ctorParameters: function () {
7147
- return [{ type: i1.DomSanitizer }, { type: undefined, decorators: [{
7168
+ return [{ type: i1$1.DomSanitizer }, { type: undefined, decorators: [{
7148
7169
  type: Inject,
7149
7170
  args: [BANTA_SDK_OPTIONS]
7150
7171
  }, {
@@ -7219,7 +7240,7 @@ class EmojiSelectorButtonComponent {
7219
7240
  this.overlayRef.attach(this.selectorPanelTemplate);
7220
7241
  }
7221
7242
  }
7222
- EmojiSelectorButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: EmojiSelectorButtonComponent, deps: [{ token: i0.ElementRef }, { token: i1$1.Overlay }], target: i0.ɵɵFactoryTarget.Component });
7243
+ EmojiSelectorButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: EmojiSelectorButtonComponent, deps: [{ token: i0.ElementRef }, { token: i1$2.Overlay }], target: i0.ɵɵFactoryTarget.Component });
7223
7244
  EmojiSelectorButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: EmojiSelectorButtonComponent, selector: "emoji-selector-button", inputs: { overlayX: "overlayX", overlayY: "overlayY", originX: "originX", originY: "originY" }, outputs: { selected: "selected" }, viewQueries: [{ propertyName: "selectorPanelTemplate", first: true, predicate: ["selectorPanelTemplate"], descendants: true }], ngImport: i0, template: `
7224
7245
  <button #button type="button" mat-icon-button (click)="show()">
7225
7246
  <mat-icon>emoji_emotions</mat-icon>
@@ -7244,7 +7265,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
7244
7265
  ></emoji-selector-panel>
7245
7266
  </ng-template>
7246
7267
  `, styles: [":host{display:block;position:relative}button{color:#666}\n"] }]
7247
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1$1.Overlay }]; }, propDecorators: { selectorPanelTemplate: [{
7268
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1$2.Overlay }]; }, propDecorators: { selectorPanelTemplate: [{
7248
7269
  type: ViewChild,
7249
7270
  args: ['selectorPanelTemplate']
7250
7271
  }], selected: [{
@@ -7978,12 +7999,12 @@ class AttachmentButtonComponent {
7978
7999
  });
7979
8000
  }
7980
8001
  }
7981
- AttachmentButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AttachmentButtonComponent, deps: [{ token: i1$2.CDNProvider }], target: i0.ɵɵFactoryTarget.Component });
8002
+ AttachmentButtonComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AttachmentButtonComponent, deps: [{ token: i1$3.CDNProvider }], target: i0.ɵɵFactoryTarget.Component });
7982
8003
  AttachmentButtonComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: AttachmentButtonComponent, selector: "banta-attachment-button", outputs: { addedAttachment: "addedAttachment", attachmentError: "attachmentError" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileUpload"], descendants: true }], ngImport: i0, template: "<button matTooltip=\"Add an image or gif\" #button type=\"button\" mat-icon-button (click)=\"show()\">\r\n\t<mat-icon>image</mat-icon>\r\n</button>\r\n<input style=\"display: none;\" #fileUpload [multiple]=\"false\" (change)=\"fileChange($event)\" type=\"file\" >", styles: ["button{color:#666}\n"], dependencies: [{ kind: "component", type: i2$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i6.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "directive", type: i11.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }] });
7983
8004
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AttachmentButtonComponent, decorators: [{
7984
8005
  type: Component,
7985
8006
  args: [{ selector: 'banta-attachment-button', template: "<button matTooltip=\"Add an image or gif\" #button type=\"button\" mat-icon-button (click)=\"show()\">\r\n\t<mat-icon>image</mat-icon>\r\n</button>\r\n<input style=\"display: none;\" #fileUpload [multiple]=\"false\" (change)=\"fileChange($event)\" type=\"file\" >", styles: ["button{color:#666}\n"] }]
7986
- }], ctorParameters: function () { return [{ type: i1$2.CDNProvider }]; }, propDecorators: { fileInput: [{
8007
+ }], ctorParameters: function () { return [{ type: i1$3.CDNProvider }]; }, propDecorators: { fileInput: [{
7987
8008
  type: ViewChild,
7988
8009
  args: ['fileUpload', { static: false }]
7989
8010
  }], addedAttachment: [{
@@ -8138,7 +8159,10 @@ class CommentFieldComponent {
8138
8159
  if (this._source.connectionStateChanged) {
8139
8160
  this._subs.add(this._source.connectionStateChanged.subscribe(state => {
8140
8161
  if (state === 'lost') {
8141
- this.transientMessage = `Reconnecting...`;
8162
+ if (this._source.errorState === 'server-issue')
8163
+ this.transientMessage = `Error occurred, trying again...`;
8164
+ else
8165
+ this.transientMessage = `Reconnecting...`;
8142
8166
  }
8143
8167
  else if (state === 'restored') {
8144
8168
  this.transientMessage = undefined;
@@ -8747,7 +8771,7 @@ class BantaCommentsComponent {
8747
8771
  }
8748
8772
  updateLoading() {
8749
8773
  var _a, _b;
8750
- if (((_a = this.source) === null || _a === void 0 ? void 0 : _a.state) && ((_b = this.source) === null || _b === void 0 ? void 0 : _b.state) !== 'connecting') {
8774
+ if (((_a = this.source) === null || _a === void 0 ? void 0 : _a.state) && !['connecting', 'lost'].includes((_b = this.source) === null || _b === void 0 ? void 0 : _b.state)) {
8751
8775
  clearInterval(this._loadingTimer);
8752
8776
  this.loadingMessage = `Here we go!`;
8753
8777
  setTimeout(() => {
@@ -10173,6 +10197,8 @@ class ChatSource extends SocketRPC {
10173
10197
  this.subscription = new Subscription();
10174
10198
  this._state = 'connecting';
10175
10199
  this._connectionStateChanged = new Subject();
10200
+ this.wasRestored = false;
10201
+ this.subscribeAttempt = 0;
10176
10202
  this.messageMap = new Map();
10177
10203
  this._messageReceived = new Subject();
10178
10204
  this._messageUpdated = new Subject();
@@ -10197,21 +10223,19 @@ class ChatSource extends SocketRPC {
10197
10223
  });
10198
10224
  return __awaiter(this, void 0, void 0, function* () {
10199
10225
  _super.bind.call(this, socket);
10200
- this.state = 'connected';
10201
- this.markReady();
10202
- yield this.subscribeToTopic();
10203
10226
  this.subscription.add(this.backend.userChanged.subscribe(() => this.authenticate()));
10204
10227
  socket.addEventListener('open', () => __awaiter(this, void 0, void 0, function* () {
10205
- this.state = 'connected';
10228
+ console.log(`[Banta/${this.identifier}] Socket is open`);
10206
10229
  }));
10207
10230
  socket.addEventListener('lost', () => __awaiter(this, void 0, void 0, function* () {
10208
10231
  this.state = 'lost';
10209
10232
  }));
10210
10233
  socket.addEventListener('restore', () => __awaiter(this, void 0, void 0, function* () {
10211
- this.state = 'restored';
10234
+ this.wasRestored = true;
10212
10235
  yield this.authenticate();
10213
10236
  yield this.subscribeToTopic();
10214
10237
  }));
10238
+ yield this.subscribeToTopic();
10215
10239
  return this;
10216
10240
  });
10217
10241
  }
@@ -10231,9 +10255,16 @@ class ChatSource extends SocketRPC {
10231
10255
  }
10232
10256
  getExistingMessages() {
10233
10257
  return __awaiter(this, void 0, void 0, function* () {
10234
- let messages = yield this.peer.getExistingMessages();
10235
- messages = this.mapOrUpdateMessages(messages);
10236
- return messages;
10258
+ try {
10259
+ let messages = yield this.peer.getExistingMessages();
10260
+ messages = this.mapOrUpdateMessages(messages);
10261
+ return messages;
10262
+ }
10263
+ catch (e) {
10264
+ console.error(`[Banta/${this.identifier}] Error occurred while trying to get existing messages:`);
10265
+ console.error(e);
10266
+ return [];
10267
+ }
10237
10268
  });
10238
10269
  }
10239
10270
  ensureConnection(errorMessage) {
@@ -10253,9 +10284,31 @@ class ChatSource extends SocketRPC {
10253
10284
  yield this.peer.editMessage(messageId, text);
10254
10285
  });
10255
10286
  }
10287
+ get errorState() {
10288
+ return this._errorState;
10289
+ }
10256
10290
  subscribeToTopic() {
10257
10291
  return __awaiter(this, void 0, void 0, function* () {
10258
- yield this.peer.subscribe(this.identifier, this.parentIdentifier, this.sortOrder);
10292
+ try {
10293
+ yield this.peer.subscribe(this.identifier, this.parentIdentifier, this.sortOrder);
10294
+ this.subscribeAttempt = 0;
10295
+ this._errorState = undefined;
10296
+ this.state = this.wasRestored ? 'restored' : 'connected';
10297
+ this.markReady();
10298
+ }
10299
+ catch (e) {
10300
+ console.error(`[Banta/${this.identifier}] Error while subscribing to topic`);
10301
+ console.error(e);
10302
+ this.state = 'lost';
10303
+ this._errorState = 'server-issue';
10304
+ this.subscribeAttempt += 1;
10305
+ let delay = Math.min(30 * 1000, (3 * 1000 * this.subscribeAttempt) * (1 + Math.random()));
10306
+ console.error(`[Banta/${this.identifier}] Waiting ${delay}ms before attempting to reconnect...`);
10307
+ setTimeout(() => {
10308
+ console.info(`Attempting reconnection after error in subscribeToTopic...`);
10309
+ this.reconnect();
10310
+ }, delay);
10311
+ }
10259
10312
  });
10260
10313
  }
10261
10314
  authenticate() {
@@ -10398,13 +10451,25 @@ class ChatBackend extends ChatBackendBase {
10398
10451
  .bind(yield this.connectToService());
10399
10452
  });
10400
10453
  }
10454
+ /**
10455
+ * Get the count of the given topic
10456
+ * @param topicId
10457
+ * @returns
10458
+ */
10401
10459
  getSourceCountForTopic(topicId) {
10402
10460
  return __awaiter(this, void 0, void 0, function* () {
10403
- let response = yield fetch(`${this.serviceUrl}/topics/${topicId}`);
10404
- if (response.status >= 400)
10405
- return 0;
10406
- let topic = yield response.json();
10407
- return topic.messageCount || 0;
10461
+ try {
10462
+ let response = yield fetch(`${this.serviceUrl}/topics/${topicId}`);
10463
+ if (response.status >= 400)
10464
+ return 0;
10465
+ let topic = yield response.json();
10466
+ return topic.messageCount || 0;
10467
+ }
10468
+ catch (e) {
10469
+ console.error(`[Banta/${topicId}] Failed to get message count for topic:`);
10470
+ console.error(e);
10471
+ return undefined;
10472
+ }
10408
10473
  });
10409
10474
  }
10410
10475
  refreshMessage(message) {
@@ -10589,9 +10654,7 @@ BantaSdkModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version:
10589
10654
  BantaSdkModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.12", ngImport: i0, type: BantaSdkModule, declarations: [BantaComponent,
10590
10655
  BantaLogoComponent,
10591
10656
  LiveMessageComponent], imports: [CommonModule,
10592
- FormsModule,
10593
- BantaCommonModule,
10594
- CommentsModule,
10657
+ FormsModule, BantaCommonModule, CommentsModule,
10595
10658
  ChatModule,
10596
10659
  EmojiModule,
10597
10660
  MatIconModule,
@@ -10613,7 +10676,7 @@ BantaSdkModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version:
10613
10676
  EmojiModule] });
10614
10677
  BantaSdkModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: BantaSdkModule, imports: [CommonModule,
10615
10678
  FormsModule,
10616
- BantaCommonModule,
10679
+ BantaCommonModule.forRoot(),
10617
10680
  CommentsModule,
10618
10681
  ChatModule,
10619
10682
  EmojiModule,
@@ -10637,7 +10700,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
10637
10700
  imports: [
10638
10701
  CommonModule,
10639
10702
  FormsModule,
10640
- BantaCommonModule,
10703
+ BantaCommonModule.forRoot(),
10641
10704
  CommentsModule,
10642
10705
  ChatModule,
10643
10706
  EmojiModule,