@banta/sdk 4.4.0 → 4.4.3

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 (36) hide show
  1. package/banta-sdk.metadata.json +1 -1
  2. package/bundles/banta-sdk.umd.js +360 -193
  3. package/bundles/banta-sdk.umd.js.map +1 -1
  4. package/bundles/banta-sdk.umd.min.js +1 -1
  5. package/bundles/banta-sdk.umd.min.js.map +1 -1
  6. package/esm2015/lib/attachment-scraper.js +2 -87
  7. package/esm2015/lib/banta-sdk.module.js +23 -1
  8. package/esm2015/lib/chat-backend-base.js +1 -6
  9. package/esm2015/lib/chat-source-base.js +1 -1
  10. package/esm2015/lib/chat-source.js +31 -3
  11. package/esm2015/lib/comments/banta-comments/banta-comments.component.js +6 -7
  12. package/esm2015/lib/comments/comment/comment.component.js +2 -2
  13. package/esm2015/lib/comments/comment-field/comment-field.component.js +37 -6
  14. package/esm2015/lib/common/attachment/attachment.component.js +29 -3
  15. package/esm2015/lib/common/index.js +4 -1
  16. package/esm2015/lib/giphy-attachments.js +20 -0
  17. package/esm2015/lib/index.js +6 -1
  18. package/esm2015/lib/tweet-attachments.js +16 -0
  19. package/esm2015/lib/url-attachments.js +46 -0
  20. package/esm2015/lib/youtube-attachments.js +25 -0
  21. package/fesm2015/banta-sdk.js +263 -148
  22. package/fesm2015/banta-sdk.js.map +1 -1
  23. package/lib/attachment-scraper.d.ts +0 -15
  24. package/lib/banta-sdk.module.d.ts +2 -0
  25. package/lib/chat-backend-base.d.ts +2 -2
  26. package/lib/chat-source-base.d.ts +1 -0
  27. package/lib/chat-source.d.ts +8 -3
  28. package/lib/comments/comment-field/comment-field.component.d.ts +5 -1
  29. package/lib/common/attachment/attachment.component.d.ts +4 -0
  30. package/lib/common/index.d.ts +3 -0
  31. package/lib/giphy-attachments.d.ts +5 -0
  32. package/lib/index.d.ts +5 -0
  33. package/lib/tweet-attachments.d.ts +5 -0
  34. package/lib/url-attachments.d.ts +11 -0
  35. package/lib/youtube-attachments.d.ts +5 -0
  36. package/package.json +1 -1
@@ -207,59 +207,6 @@
207
207
  { type: platformBrowser.DomSanitizer }
208
208
  ]; };
209
209
 
210
- var BantaAttachmentsComponent = /** @class */ (function () {
211
- function BantaAttachmentsComponent() {
212
- this.editing = false;
213
- this.remove = new rxjs.Subject();
214
- }
215
- BantaAttachmentsComponent.prototype.removeAttachment = function (attachment) {
216
- this.remove.next(attachment);
217
- };
218
- BantaAttachmentsComponent.prototype.isImageAttachment = function (attachment) {
219
- if (attachment.type.startsWith('image/'))
220
- return true;
221
- return false;
222
- };
223
- BantaAttachmentsComponent.prototype.isCardAttachment = function (attachment) {
224
- if (['card'].includes(attachment.type))
225
- return true;
226
- return false;
227
- };
228
- BantaAttachmentsComponent.prototype.showLightbox = function (image) {
229
- this.lightbox.open(image.url, this.attachments
230
- .filter(function (x) { return x.type === 'image/png'; })
231
- .map(function (x) { return x.url; }));
232
- };
233
- Object.defineProperty(BantaAttachmentsComponent.prototype, "inlineAttachments", {
234
- get: function () {
235
- return this.attachments.filter(function (x) { return x.type !== 'card' && (x.style === 'inline' || !x.style); });
236
- },
237
- enumerable: false,
238
- configurable: true
239
- });
240
- Object.defineProperty(BantaAttachmentsComponent.prototype, "blockAttachments", {
241
- get: function () {
242
- return this.attachments.filter(function (x) { return x.style === 'block' || x.type === 'card'; });
243
- },
244
- enumerable: false,
245
- configurable: true
246
- });
247
- return BantaAttachmentsComponent;
248
- }());
249
- BantaAttachmentsComponent.decorators = [
250
- { type: core.Component, args: [{
251
- selector: 'banta-attachments',
252
- template: "<ng-container *ngIf=\"attachments?.length > 0\">\r\n <banta-lightbox #lightbox></banta-lightbox>\r\n <div class=\"block-attachments\">\r\n <ng-container *ngFor=\"let attachment of blockAttachments\">\r\n <banta-attachment \r\n [attachment]=\"attachment\"\r\n [editing]=\"editing\"\r\n (removed)=\"removeAttachment(attachment)\"\r\n (activated)=\"showLightbox(attachment)\"\r\n ></banta-attachment>\r\n </ng-container>\r\n </div>\r\n\r\n <div \r\n class=\"inline-attachments\" \r\n [class.single]=\"attachments?.length === 1\" \r\n *ngIf=\"attachments && attachments?.length > 0\"\r\n >\r\n <ng-container *ngFor=\"let attachment of inlineAttachments\">\r\n <banta-attachment \r\n [attachment]=\"attachment\"\r\n [editing]=\"editing\"\r\n (removed)=\"removeAttachment(attachment)\"\r\n (activated)=\"showLightbox(attachment)\"\r\n ></banta-attachment>\r\n </ng-container>\r\n </div>\r\n</ng-container>",
253
- styles: [".block-attachments{display:flex;flex-direction:column}.block-attachments banta-attachment{width:100%}.inline-attachments{flex-direction:row;margin-top:15px;display:flex;gap:20px;flex-wrap:wrap}"]
254
- },] }
255
- ];
256
- BantaAttachmentsComponent.propDecorators = {
257
- attachments: [{ type: core.Input }],
258
- editing: [{ type: core.Input }],
259
- lightbox: [{ type: core.ViewChild, args: ['lightbox',] }],
260
- remove: [{ type: core.Output }]
261
- };
262
-
263
210
  var BantaTrustResourceUrlPipe = /** @class */ (function () {
264
211
  function BantaTrustResourceUrlPipe(sanitizer) {
265
212
  this.sanitizer = sanitizer;
@@ -290,6 +237,15 @@
290
237
  this.removed = new rxjs.Subject();
291
238
  this.activated = new rxjs.Subject();
292
239
  }
240
+ BantaAttachmentComponent.prototype.ngOnInit = function () {
241
+ if (typeof window !== 'undefined') {
242
+ setTimeout(function () {
243
+ if (!window['twttr'])
244
+ return;
245
+ window['twttr'].widgets.load();
246
+ }, 100);
247
+ }
248
+ };
293
249
  BantaAttachmentComponent.prototype.activate = function () {
294
250
  this.activated.next();
295
251
  };
@@ -329,15 +285,40 @@
329
285
  enumerable: false,
330
286
  configurable: true
331
287
  });
288
+ Object.defineProperty(BantaAttachmentComponent.prototype, "hasFrame", {
289
+ get: function () {
290
+ if (!this.attachment)
291
+ return false;
292
+ return this.attachment.type === 'iframe' || (this.attachment.type === 'card'
293
+ && this.attachment.card.player);
294
+ },
295
+ enumerable: false,
296
+ configurable: true
297
+ });
298
+ Object.defineProperty(BantaAttachmentComponent.prototype, "frameUrl", {
299
+ get: function () {
300
+ if (!this.attachment)
301
+ return undefined;
302
+ if (this.attachment.type === 'iframe') {
303
+ return this.attachment.url;
304
+ }
305
+ else if (this.attachment.type === 'card') {
306
+ return this.attachment.card.player;
307
+ }
308
+ },
309
+ enumerable: false,
310
+ configurable: true
311
+ });
332
312
  return BantaAttachmentComponent;
333
313
  }());
334
314
  BantaAttachmentComponent.decorators = [
335
315
  { type: core.Component, args: [{
336
316
  selector: 'banta-attachment',
337
- template: "<button type=\"button\" (click)=\"remove()\" mat-mini-fab color=\"primary\" class=\"remove-button\" *ngIf=\"editing\">\r\n <mat-icon>close</mat-icon>\r\n</button>\r\n\r\n<ng-container *ngIf=\"isError\">\r\n <mat-icon class=\"error\">close</mat-icon>\r\n <em class=\"error\">{{theErrorMessage}}</em>\r\n</ng-container>\r\n<ng-container *ngIf=\"!isError\">\r\n <ng-container *ngIf=\"isLoading\">\r\n <mat-spinner></mat-spinner>\r\n <em>{{loadingMessage}}</em>\r\n </ng-container>\r\n <ng-container *ngIf=\"!isLoading\">\r\n <iframe \r\n *ngIf=\"attachment.type === 'iframe'\" \r\n sandbox=\"allow-scripts allow-popups allow-same-origin allow-presentation\" \r\n [src]=\"attachment.url | trustResourceUrl\"></iframe>\r\n <a *ngIf=\"attachment.type === 'card'\" class=\"card\" [href]=\"attachment.url\" target=\"_blank\">\r\n <img \r\n *ngIf=\"attachment.card.image\"\r\n class=\"thumbnail\" \r\n [src]=\"attachment.card.image\"\r\n />\r\n <div class=\"description\">\r\n <h1>{{attachment.card.title}}</h1>\r\n {{attachment.card.description}}\r\n </div>\r\n </a>\r\n <a class=\"image-attachment\" *ngIf=\"isImageAttachment\" href=\"javascript:;\" (click)=\"activate()\">\r\n <img [src]=\"attachment.url\" alt=\"Image Attachment\">\r\n </a>\r\n </ng-container>\r\n</ng-container>",
338
- styles: [":host{position:relative;display:block}:host.loading{outline:1px solid #333;padding:1em 0;width:300px;text-align:center}:host.loading mat-spinner{display:block;margin:0 auto .5em;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}a.card{display:flex;align-items:flex-start;gap:1em;width:100%;border:1px solid #666;border-radius:4px;padding:1em;box-sizing:border-box;background-color:#191919}a.card img{width:300px;aspect-ratio:16/9;-o-object-fit:cover;object-fit:cover;border-radius:10px}a.card h1{margin:0;font-size:30px}.remove-button{position:absolute;right:10px;top:10px;margin:0;z-index:1}a.image-attachment{width:300px;position:relative;text-align:center}a.image-attachment.with-border{outline:1px solid #333;padding:1em 0}a.image-attachment mat-spinner{display:block;margin:0 auto .5em;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}a.image-attachment mat-icon.error{display:block;font-size:48px;width:48px;height:48px;margin:0 auto .5em}a.image-attachment .error{color:#b76363}a.image-attachment img{width:300px;border-radius:10px;max-width:100%;max-height:20em;-o-object-fit:cover;object-fit:cover}iframe{border:none;width:100%;aspect-ratio:16/9}"]
317
+ template: "<button type=\"button\" (click)=\"remove()\" mat-mini-fab color=\"primary\" class=\"remove-button\" *ngIf=\"editing\">\r\n <mat-icon>close</mat-icon>\r\n</button>\r\n\r\n<ng-container *ngIf=\"isError\">\r\n <mat-icon class=\"error\">close</mat-icon>\r\n <em class=\"error\">{{theErrorMessage}}</em>\r\n</ng-container>\r\n<ng-container *ngIf=\"!isError\">\r\n <ng-container *ngIf=\"isLoading\">\r\n <mat-spinner></mat-spinner>\r\n <em>{{loadingMessage}}</em>\r\n </ng-container>\r\n <ng-container *ngIf=\"!isLoading\">\r\n <iframe *ngIf=\"hasFrame\"\r\n sandbox=\"allow-scripts allow-popups allow-same-origin allow-presentation\" \r\n [src]=\"frameUrl | trustResourceUrl\"></iframe>\r\n <a *ngIf=\"attachment.type === 'card'\" class=\"card\" [href]=\"attachment.url\" target=\"_blank\" [class.has-image]=\"attachment.card.image\">\r\n <img \r\n *ngIf=\"attachment.card.image\"\r\n class=\"thumbnail\" \r\n [src]=\"attachment.card.image\"\r\n />\r\n <div class=\"description\">\r\n <h1>{{attachment.card.title}}</h1>\r\n <div>\r\n {{attachment.card.description}}\r\n </div>\r\n <cite>{{attachment.card.url}}</cite>\r\n </div>\r\n </a>\r\n <a class=\"image-attachment\" *ngIf=\"isImageAttachment\" href=\"javascript:;\" (click)=\"activate()\">\r\n <img [src]=\"attachment.url\" alt=\"Image Attachment\">\r\n </a>\r\n <blockquote *ngIf=\"attachment.type === 'tweet'\" \r\n class=\"twitter-tweet\">\r\n <p lang=\"en\" dir=\"ltr\"></p>\r\n <a href=\"https://twitter.com/seldo/status/1562553608083714050?ref_src=twsrc%5Etfw\"></a>\r\n </blockquote>\r\n </ng-container>\r\n</ng-container>",
318
+ styles: [":host{position:relative;display:block}:host.loading{outline:1px solid #333;padding:1em 0;width:300px;text-align:center}:host.loading mat-spinner{display:block;margin:0 auto .5em;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}a.card{display:flex;align-items:flex-start;gap:1em;width:100%;border:1px solid #666;border-radius:4px;padding:1em;box-sizing:border-box;background-color:#191919;margin:1em 0}a.card img{width:250px;aspect-ratio:16/9;-o-object-fit:cover;object-fit:cover;border-radius:10px}a.card.has-image h1{font-size:22px}a.card h1{min-width:0;margin:0 0 .5em;font-size:26px}a.card cite{min-width:0;opacity:.75;margin-top:1em;display:block;font-size:90%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}a.card .description{min-width:0}.remove-button{position:absolute;right:10px;top:10px;margin:0;z-index:1}a.image-attachment{width:300px;position:relative;text-align:center}a.image-attachment.with-border{outline:1px solid #333;padding:1em 0}a.image-attachment mat-spinner{display:block;margin:0 auto .5em;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}a.image-attachment mat-icon.error{display:block;font-size:48px;width:48px;height:48px;margin:0 auto .5em}a.image-attachment .error{color:#b76363}a.image-attachment img{width:300px;border-radius:10px;max-width:100%;max-height:20em;-o-object-fit:cover;object-fit:cover}iframe{border:none;width:100%;aspect-ratio:16/9}"]
339
319
  },] }
340
320
  ];
321
+ BantaAttachmentComponent.ctorParameters = function () { return []; };
341
322
  BantaAttachmentComponent.propDecorators = {
342
323
  attachment: [{ type: core.Input }],
343
324
  loading: [{ type: core.Input }],
@@ -350,6 +331,59 @@
350
331
  isLoading: [{ type: core.HostBinding, args: ['class.loading',] }]
351
332
  };
352
333
 
334
+ var BantaAttachmentsComponent = /** @class */ (function () {
335
+ function BantaAttachmentsComponent() {
336
+ this.editing = false;
337
+ this.remove = new rxjs.Subject();
338
+ }
339
+ BantaAttachmentsComponent.prototype.removeAttachment = function (attachment) {
340
+ this.remove.next(attachment);
341
+ };
342
+ BantaAttachmentsComponent.prototype.isImageAttachment = function (attachment) {
343
+ if (attachment.type.startsWith('image/'))
344
+ return true;
345
+ return false;
346
+ };
347
+ BantaAttachmentsComponent.prototype.isCardAttachment = function (attachment) {
348
+ if (['card'].includes(attachment.type))
349
+ return true;
350
+ return false;
351
+ };
352
+ BantaAttachmentsComponent.prototype.showLightbox = function (image) {
353
+ this.lightbox.open(image.url, this.attachments
354
+ .filter(function (x) { return x.type === 'image/png'; })
355
+ .map(function (x) { return x.url; }));
356
+ };
357
+ Object.defineProperty(BantaAttachmentsComponent.prototype, "inlineAttachments", {
358
+ get: function () {
359
+ return this.attachments.filter(function (x) { return x.type !== 'card' && (x.style === 'inline' || !x.style); });
360
+ },
361
+ enumerable: false,
362
+ configurable: true
363
+ });
364
+ Object.defineProperty(BantaAttachmentsComponent.prototype, "blockAttachments", {
365
+ get: function () {
366
+ return this.attachments.filter(function (x) { return x.style === 'block' || x.type === 'card'; });
367
+ },
368
+ enumerable: false,
369
+ configurable: true
370
+ });
371
+ return BantaAttachmentsComponent;
372
+ }());
373
+ BantaAttachmentsComponent.decorators = [
374
+ { type: core.Component, args: [{
375
+ selector: 'banta-attachments',
376
+ template: "<ng-container *ngIf=\"attachments?.length > 0\">\r\n <banta-lightbox #lightbox></banta-lightbox>\r\n <div class=\"block-attachments\">\r\n <ng-container *ngFor=\"let attachment of blockAttachments\">\r\n <banta-attachment \r\n [attachment]=\"attachment\"\r\n [editing]=\"editing\"\r\n (removed)=\"removeAttachment(attachment)\"\r\n (activated)=\"showLightbox(attachment)\"\r\n ></banta-attachment>\r\n </ng-container>\r\n </div>\r\n\r\n <div \r\n class=\"inline-attachments\" \r\n [class.single]=\"attachments?.length === 1\" \r\n *ngIf=\"attachments && attachments?.length > 0\"\r\n >\r\n <ng-container *ngFor=\"let attachment of inlineAttachments\">\r\n <banta-attachment \r\n [attachment]=\"attachment\"\r\n [editing]=\"editing\"\r\n (removed)=\"removeAttachment(attachment)\"\r\n (activated)=\"showLightbox(attachment)\"\r\n ></banta-attachment>\r\n </ng-container>\r\n </div>\r\n</ng-container>",
377
+ styles: [".block-attachments{display:flex;flex-direction:column}.block-attachments banta-attachment{width:100%}.inline-attachments{flex-direction:row;margin-top:15px;display:flex;gap:20px;flex-wrap:wrap}"]
378
+ },] }
379
+ ];
380
+ BantaAttachmentsComponent.propDecorators = {
381
+ attachments: [{ type: core.Input }],
382
+ editing: [{ type: core.Input }],
383
+ lightbox: [{ type: core.ViewChild, args: ['lightbox',] }],
384
+ remove: [{ type: core.Output }]
385
+ };
386
+
353
387
  var COMPONENTS = [
354
388
  TimestampComponent,
355
389
  LightboxComponent,
@@ -7425,123 +7459,11 @@
7425
7459
  },] }
7426
7460
  ];
7427
7461
 
7428
- var URL_REGEX = new RegExp('(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?', 'ig');
7429
- var UrlAttachmentScraper = /** @class */ (function () {
7430
- function UrlAttachmentScraper() {
7431
- }
7432
- UrlAttachmentScraper.prototype.findFragments = function (message) {
7433
- var _a;
7434
- // If a message already has a URL attachment, don't add another one.
7435
- if (message.attachments && message.attachments.filter(function (x) { return x.type === 'url'; }).length > 0)
7436
- return null;
7437
- return (Array.from((_a = message.message.match(URL_REGEX)) !== null && _a !== void 0 ? _a : []))
7438
- .reduce(function (a, item) { return (a.includes(item) ? undefined : a.push(item), a); }, [])
7439
- .map(function (url) { return ({
7440
- text: url,
7441
- offset: message.message.indexOf(url),
7442
- type: 'url'
7443
- }); });
7444
- };
7445
- return UrlAttachmentScraper;
7446
- }());
7447
- var GiphyAttachmentResolver = /** @class */ (function () {
7448
- function GiphyAttachmentResolver() {
7449
- }
7450
- GiphyAttachmentResolver.prototype.resolveFragment = function (message, fragment) {
7451
- var _a;
7452
- return __awaiter(this, void 0, void 0, function () {
7453
- var gifId;
7454
- return __generator(this, function (_b) {
7455
- if (fragment.type === 'url' && fragment.text.startsWith('https://giphy.com/gifs')) {
7456
- gifId = (_a = /[^-\/]+$/.exec(fragment.text)) === null || _a === void 0 ? void 0 : _a.toString();
7457
- if (!gifId)
7458
- return [2 /*return*/, null];
7459
- return [2 /*return*/, {
7460
- type: 'iframe',
7461
- url: "https://giphy.com/embed/" + gifId,
7462
- style: 'inline'
7463
- }];
7464
- }
7465
- return [2 /*return*/, null];
7466
- });
7467
- });
7468
- };
7469
- return GiphyAttachmentResolver;
7470
- }());
7471
- var YouTubeAttachmentResolver = /** @class */ (function () {
7472
- function YouTubeAttachmentResolver() {
7473
- }
7474
- YouTubeAttachmentResolver.prototype.resolveFragment = function (message, fragment) {
7475
- return __awaiter(this, void 0, void 0, function () {
7476
- var videoId, match;
7477
- return __generator(this, function (_b) {
7478
- if (fragment.type !== 'url')
7479
- return [2 /*return*/, null];
7480
- if (fragment.text.match(/https?:\/\/(www\.)?youtube.com\/watch\?v=/)) {
7481
- match = /watch\?v=([^&]+)/.exec(fragment.text);
7482
- if (match) {
7483
- videoId = match[1];
7484
- }
7485
- }
7486
- if (videoId) {
7487
- return [2 /*return*/, {
7488
- type: 'iframe',
7489
- url: "https://www.youtube.com/embed/" + videoId,
7490
- style: 'block'
7491
- }];
7492
- }
7493
- return [2 /*return*/, null];
7494
- });
7495
- });
7496
- };
7497
- return YouTubeAttachmentResolver;
7498
- }());
7499
- var UrlAttachmentResolver = /** @class */ (function () {
7500
- function UrlAttachmentResolver(backend) {
7501
- this.backend = backend;
7502
- }
7503
- UrlAttachmentResolver.prototype.resolveFragment = function (message, fragment) {
7504
- return __awaiter(this, void 0, void 0, function () {
7505
- var urlCard;
7506
- return __generator(this, function (_b) {
7507
- switch (_b.label) {
7508
- case 0:
7509
- if (fragment.type !== 'url')
7510
- return [2 /*return*/, null];
7511
- return [4 /*yield*/, this.backend.getCardForUrl(fragment.text)];
7512
- case 1:
7513
- urlCard = _b.sent();
7514
- if (urlCard) {
7515
- return [2 /*return*/, {
7516
- type: 'card',
7517
- url: fragment.text,
7518
- card: urlCard,
7519
- style: 'block'
7520
- }];
7521
- }
7522
- return [2 /*return*/];
7523
- }
7524
- });
7525
- });
7526
- };
7527
- return UrlAttachmentResolver;
7528
- }());
7529
- UrlAttachmentResolver.decorators = [
7530
- { type: core.Injectable }
7531
- ];
7532
- UrlAttachmentResolver.ctorParameters = function () { return [
7533
- { type: ChatBackendBase }
7534
- ]; };
7535
-
7536
7462
  var ChatBackendBase = /** @class */ (function () {
7537
7463
  function ChatBackendBase() {
7538
7464
  this._userChanged = new rxjs.BehaviorSubject(null);
7539
7465
  this._attachmentScrapers = [];
7540
7466
  this._attachmentResolvers = [];
7541
- this.registerAttachmentScraper(new UrlAttachmentScraper());
7542
- this.registerAttachmentResolver(new GiphyAttachmentResolver());
7543
- this.registerAttachmentResolver(new YouTubeAttachmentResolver());
7544
- this.registerAttachmentResolver(new UrlAttachmentResolver(this));
7545
7467
  }
7546
7468
  Object.defineProperty(ChatBackendBase.prototype, "userChanged", {
7547
7469
  get: function () {
@@ -8651,7 +8573,7 @@
8651
8573
  CommentComponent.decorators = [
8652
8574
  { type: core.Component, args: [{
8653
8575
  selector: 'banta-comment',
8654
- template: "\r\n<mat-menu #pointItemMenu=\"matMenu\">\r\n <button mat-menu-item (click)=\"share()\">\r\n <mat-icon>share</mat-icon>\r\n Share\r\n </button>\r\n <button *ngIf=\"!mine\" mat-menu-item (click)=\"report()\">\r\n <mat-icon>warning</mat-icon>\r\n Report\r\n </button>\r\n <button *ngIf=\"mine\" [disabled]=\"!permissions?.canEdit\" mat-menu-item (click)=\"startEdit()\">\r\n <mat-icon>edit</mat-icon>\r\n Edit\r\n </button>\r\n <button *ngIf=\"mine\" [disabled]=\"!permissions?.canDelete\" mat-menu-item (click)=\"delete()\">\r\n <mat-icon>delete</mat-icon>\r\n Delete\r\n </button>\r\n</mat-menu>\r\n\r\n<div class=\"message-content\">\r\n <div class=\"user\">\r\n <div class=\"user-1\">\r\n <a\r\n href=\"javascript:;\"\r\n class=\"avatar\"\r\n (click)=\"selectAvatar(message.user)\"\r\n [style.background-image]=\"avatarForUser(message.user)\"></a>\r\n <div class=\"user-identity\">\r\n <a href=\"javascript:;\" class=\"display-name\" (click)=\"selectUser()\">{{message.user.displayName}}</a>\r\n <a href=\"javascript:;\" class=\"username\" (click)=\"selectUsername(message.user)\">@{{message.user.username}}</a>\r\n </div>\r\n </div>\r\n <div class=\"user-2\">\r\n <span class=\"user-tag\" *ngIf=\"message.user.tag\">{{message.user.tag}}</span>\r\n <banta-timestamp [value]=\"message.sentAt\"></banta-timestamp>\r\n <span class=\"spacer\"></span>\r\n </div>\r\n </div>\r\n <div class=\"content\" *ngIf=\"!editing\">\r\n <span class=\"banta-message-content\" [innerHTML]=\"message.message | markdownToHtml\"></span>\r\n <banta-attachments [attachments]=\"message.attachments\"></banta-attachments>\r\n <ul class=\"message-facts\">\r\n <li *ngIf=\"message.edits?.length > 0\">(Edited)</li>\r\n </ul>\r\n </div>\r\n <div class=\"content\" *ngIf=\"editing\" style=\"padding-bottom: 2em;\">\r\n <div>\r\n <mat-form-field floatLabel=\"always\" appearance=\"outline\" style=\"width: 100%;\">\r\n <mat-label>Edit Message</mat-label>\r\n <textarea matInput [(ngModel)]=\"editedMessage\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n <button mat-raised-button (click)=\"saveEdit()\">Save</button> &nbsp;\r\n <button mat-button (click)=\"endEditing()\">Cancel</button>\r\n </div>\r\n\r\n\r\n <div class=\"actions\">\r\n <div class=\"spacer\"></div>\r\n <div class=\"counted-action\" *ngIf=\"showReplyAction\">\r\n <button mat-button [matTooltip]=\"replyCount > 0 ? 'Replies' : 'Reply'\" matTooltipPosition=\"below\" (click)=\"select()\">\r\n <mat-icon [inline]=\"true\">comment</mat-icon>\r\n <span class=\"count-indicator\">\r\n {{replyCount > 0 ? 'Replies' : 'Reply'}}\r\n {{replyCount > 0 ? '(' + replyCount + ')' : ''}}\r\n </span>\r\n </button>\r\n </div>\r\n <div class=\"counted-action\" [class.active]=\"message.userState?.liked\">\r\n <button \r\n *ngIf=\"message.transientState?.liking\"\r\n mat-icon-button \r\n [disabled]=\"true\" \r\n [matTooltip]=\"upvoting ? 'Please wait...' : message.userState?.liked ? 'Unlike' : 'Like'\" \r\n matTooltipPosition=\"below\" \r\n >\r\n <mat-spinner [diameter]=\"15\" style=\"margin-left: 1em;\"></mat-spinner>\r\n </button>\r\n <button \r\n *ngIf=\"!message.transientState?.liking\"\r\n mat-button \r\n [disabled]=\"!permissions?.canLike\" \r\n [matTooltip]=\"upvoting ? 'Please wait...' : 'Like'\" \r\n matTooltipPosition=\"below\" \r\n (click)=\"message.userState?.liked ? unlike() : like()\" \r\n >\r\n <mat-icon [inline]=\"true\">thumb_up</mat-icon>\r\n <span class=\"count-indicator\" *ngIf=\"message.likes > 0\">\r\n {{message.likes}}\r\n </span>\r\n </button>\r\n </div>\r\n\r\n <button mat-icon-button [matMenuTriggerFor]=\"pointItemMenu\">\r\n <mat-icon [inline]=\"true\">more_vert</mat-icon>\r\n </button>\r\n </div>\r\n</div>\r\n",
8576
+ template: "\r\n<mat-menu #pointItemMenu=\"matMenu\">\r\n <button mat-menu-item (click)=\"share()\">\r\n <mat-icon>share</mat-icon>\r\n Share\r\n </button>\r\n <button *ngIf=\"!mine\" mat-menu-item (click)=\"report()\">\r\n <mat-icon>warning</mat-icon>\r\n Report\r\n </button>\r\n <button *ngIf=\"mine\" [disabled]=\"!permissions?.canEdit\" mat-menu-item (click)=\"startEdit()\">\r\n <mat-icon>edit</mat-icon>\r\n Edit\r\n </button>\r\n <button *ngIf=\"mine\" [disabled]=\"!permissions?.canDelete\" mat-menu-item (click)=\"delete()\">\r\n <mat-icon>delete</mat-icon>\r\n Delete\r\n </button>\r\n</mat-menu>\r\n\r\n<div class=\"message-content\">\r\n <div class=\"user\">\r\n <div class=\"user-1\">\r\n <a\r\n href=\"javascript:;\"\r\n class=\"avatar\"\r\n (click)=\"selectAvatar(message.user)\"\r\n [style.background-image]=\"avatarForUser(message.user)\"></a>\r\n <div class=\"user-identity\">\r\n <a href=\"javascript:;\" class=\"display-name\" (click)=\"selectUser()\">{{message.user.displayName}}</a>\r\n <a href=\"javascript:;\" class=\"username\" (click)=\"selectUsername(message.user)\">@{{message.user.username}}</a>\r\n </div>\r\n </div>\r\n <div class=\"user-2\">\r\n <span class=\"user-tag\" *ngIf=\"message.user.tag\">{{message.user.tag}}</span>\r\n <banta-timestamp [value]=\"message.sentAt\"></banta-timestamp>\r\n <span class=\"spacer\"></span>\r\n </div>\r\n </div>\r\n <div class=\"content\" *ngIf=\"!editing\">\r\n <span class=\"banta-message-content\" [innerHTML]=\"message.message | markdownToHtml\"></span>\r\n <banta-attachments [attachments]=\"message.attachments\"></banta-attachments>\r\n <ul class=\"message-facts\">\r\n <li *ngIf=\"message.edits?.length > 0\">(Edited)</li>\r\n </ul>\r\n </div>\r\n <div class=\"content\" *ngIf=\"editing\" style=\"padding-bottom: 2em;\">\r\n <div>\r\n <mat-form-field floatLabel=\"always\" appearance=\"outline\" style=\"width: 100%;\">\r\n <mat-label>Edit Message</mat-label>\r\n <textarea matInput [(ngModel)]=\"editedMessage\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n <button mat-raised-button (click)=\"saveEdit()\">Save</button> &nbsp;\r\n <button mat-button (click)=\"endEditing()\">Cancel</button>\r\n </div>\r\n\r\n\r\n <div class=\"actions\">\r\n <div class=\"spacer\"></div>\r\n <div class=\"counted-action\" *ngIf=\"showReplyAction\">\r\n <button mat-button [matTooltip]=\"replyCount > 0 ? 'Replies' : 'Reply'\" matTooltipPosition=\"below\" (click)=\"select()\">\r\n <mat-icon [inline]=\"true\">comment</mat-icon>\r\n <span class=\"count-indicator\">\r\n {{replyCount > 0 ? 'Replies' : 'Reply'}}\r\n {{replyCount > 0 ? '(' + replyCount + ')' : ''}}\r\n </span>\r\n </button>\r\n </div>\r\n <div class=\"counted-action\" [class.active]=\"message.userState?.liked\">\r\n <button \r\n *ngIf=\"message.transientState?.liking\"\r\n mat-icon-button \r\n [disabled]=\"true\" \r\n [matTooltip]=\"upvoting ? 'Please wait...' : message.userState?.liked ? 'Unlike' : 'Like'\" \r\n matTooltipPosition=\"below\" \r\n >\r\n <mat-spinner [diameter]=\"15\" style=\"margin-left: 1em;\"></mat-spinner>\r\n </button>\r\n <button \r\n *ngIf=\"!message.transientState?.liking\"\r\n mat-button \r\n [matTooltip]=\"permissions?.canLike ? upvoting ? 'Please wait...' : 'Like' : permissions?.canLikeErrorMessage\" \r\n matTooltipPosition=\"below\" \r\n (click)=\"message.userState?.liked ? unlike() : like()\" \r\n >\r\n <mat-icon [inline]=\"true\">thumb_up</mat-icon>\r\n <span class=\"count-indicator\" *ngIf=\"message.likes > 0\">\r\n {{message.likes}}\r\n </span>\r\n </button>\r\n </div>\r\n\r\n <button mat-icon-button [matMenuTriggerFor]=\"pointItemMenu\">\r\n <mat-icon [inline]=\"true\">more_vert</mat-icon>\r\n </button>\r\n </div>\r\n</div>\r\n",
8655
8577
  styles: ["@-webkit-keyframes comment-appear{0%{transform:translate(100vw)}to{transform:translate(0)}}@keyframes comment-appear{0%{transform:translate(100vw)}to{transform:translate(0)}}:host{display:flex;flex-direction:column;position:relative;padding:.5em;visibility:hidden}:host.new{visibility:visible;-webkit-animation-name:comment-appear;animation-name:comment-appear;-webkit-animation-duration:.4s;animation-duration:.4s;-webkit-animation-fill-mode:both;animation-fill-mode:both}:host.highlighted{background:#00223a;outline:2px solid #003277}:host.visible{visibility:visible}:host:hover{background:#eee}:host .message-content .content{margin-left:60px;margin-right:.5em}:host .message-content .attachments-row{margin-top:15px;display:flex;gap:10px}:host .message-content .attachments-row img{border-radius:10px;width:300px;max-width:100%;max-height:20em;-o-object-fit:cover;object-fit:cover}:host.abbreviated .message-content .content{text-overflow:ellipsis;overflow-y:hidden}:host .actions{display:flex;padding-right:10px;margin-left:60px;align-items:center}:host .actions button,banta-timestamp{color:#666;flex-shrink:0}banta-timestamp{font-size:10pt;margin-left:1em;text-align:right}.user{position:relative;margin:1em 0 0;display:flex;align-items:center;flex-wrap:wrap}.user .user-1,.user .user-2{display:flex;flex-wrap:nowrap;align-items:center;min-width:0}.user .user-2{margin:1em 0}.user .user-identity{display:flex;flex-direction:column;min-width:0}.user .display-name,.user .username{z-index:1;position:relative;padding:0 0 0 1em;font-size:10pt;color:#000;margin:0 auto 0 0;display:block;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;max-width:100%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;flex-shrink:1;flex-grow:0;min-width:0}.user .display-name.username.username.username,.user .username.username.username.username{color:#666}.avatar{height:48px;width:48px;background-position:50%;background-size:cover;background-color:#333;border-radius:100%;flex-shrink:0;flex-grow:0}.counted-action{display:flex;align-items:center}.counted-action.active .count-indicator,.counted-action.active button{color:#00a5ff}.counted-action button .count-indicator{margin-left:.5em}.count-indicator{font-size:9pt;padding:0 0 0 3px;color:#666}:host-context(.mat-dark-theme) .count-indicator{border-color:#333}:host-context(.mat-dark-theme):hover{background:#060606}.user-tag,:host-context(.mat-dark-theme) .user .display-name,:host-context(.mat-dark-theme) .user .username{color:#fff}.user-tag{text-transform:uppercase;font-size:12px;border:1px solid #b27373;background:#7a412b;padding:3px 5px;margin:0 .5em 0 1em;border-radius:3px}.spacer{flex-shrink:1;flex-grow:1}ul.message-facts{margin:0;padding:0;color:#666}ul.message-facts li{list-style-type:none;border-left:1px solid #666;font-size:10pt;padding-left:.5em;margin-left:.5em;margin-top:.5em}ul.message-facts li:first-child{border-left:1px solid transparent;margin-left:0;padding-left:0}@media (max-width:400px){.avatar{height:32px;width:32px}:host .actions{margin-left:0;margin-top:.5em}:host .message-content .content{margin-left:44px;margin-right:.5em}}:host-context(.banta-mobile) .avatar{height:32px;width:32px}:host-context(.banta-mobile) :host .actions{margin-left:0;margin-top:.5em}:host-context(.banta-mobile) :host .message-content .content{margin-left:44px;margin-right:.5em}.card-attachment a{display:flex;align-items:flex-start;gap:1em;width:100%;border:1px solid #666;border-radius:4px;padding:1em;box-sizing:border-box;background-color:#191919}.card-attachment a img{width:300px;aspect-ratio:16/9;-o-object-fit:cover;object-fit:cover;border-radius:10px}.card-attachment a h1{margin:0;font-size:30px}"]
8656
8578
  },] }
8657
8579
  ];
@@ -9488,7 +9410,6 @@
9488
9410
  };
9489
9411
  // Actions
9490
9412
  BantaCommentsComponent.prototype.likeMessage = function (source, message) {
9491
- var _a;
9492
9413
  return __awaiter(this, void 0, void 0, function () {
9493
9414
  var e_4;
9494
9415
  return __generator(this, function (_d) {
@@ -9496,24 +9417,23 @@
9496
9417
  case 0:
9497
9418
  this._upvoted.next(message);
9498
9419
  message.transientState.liking = true;
9499
- if (!((_a = message.userState) === null || _a === void 0 ? void 0 : _a.liked))
9500
- message.likes = (message.likes || 0) + 1;
9501
9420
  _d.label = 1;
9502
9421
  case 1:
9503
- _d.trys.push([1, 3, , 4]);
9422
+ _d.trys.push([1, 3, 4, 6]);
9504
9423
  return [4 /*yield*/, source.likeMessage(message.id)];
9505
9424
  case 2:
9506
9425
  _d.sent();
9507
- return [3 /*break*/, 4];
9426
+ return [3 /*break*/, 6];
9508
9427
  case 3:
9509
9428
  e_4 = _d.sent();
9510
9429
  this.handleBackendExceptionAsAlert(e_4, 'Could not like this message: ');
9511
- return [3 /*break*/, 4];
9430
+ return [3 /*break*/, 6];
9512
9431
  case 4: return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(function () { return resolve(); }, 250); })];
9513
9432
  case 5:
9514
9433
  _d.sent();
9515
9434
  message.transientState.liking = false;
9516
- return [2 /*return*/];
9435
+ return [7 /*endfinally*/];
9436
+ case 6: return [2 /*return*/];
9517
9437
  }
9518
9438
  });
9519
9439
  });
@@ -9734,7 +9654,7 @@
9734
9654
  BantaCommentsComponent.decorators = [
9735
9655
  { type: core.Component, args: [{
9736
9656
  selector: 'banta-comments',
9737
- template: "<ng-container *ngIf=\"loading\">\r\n <div class=\"loading-screen\" [class.visible]=\"showLoadingScreen\">\r\n <h1>Loading Comments</h1>\r\n <div>\r\n <mat-spinner [diameter]=\"300\" [strokeWidth]=\"2\"></mat-spinner>\r\n </div>\r\n\r\n <p class=\"loading-message\" [class.visible]=\"loadingMessageVisible\">{{loadingMessage}}</p>\r\n </div>\r\n</ng-container>\r\n<ng-container *ngIf=\"!loading\">\r\n <div class=\"focused\" [class.visible]=\"selectedMessageVisible\" *ngIf=\"selectedMessage && !useInlineReplies\">\r\n\r\n <div>\r\n <a mat-button href=\"javascript:;\" (click)=\"unselectMessage()\">\r\n <mat-icon>arrow_back</mat-icon>\r\n Latest Comments\r\n </a>\r\n </div>\r\n\r\n <banta-comment\r\n [message]=\"selectedMessage\"\r\n [liking]=\"selectedMessage.transientState.liking\"\r\n [mine]=\"user?.id === selectedMessage.user?.id\"\r\n [permissions]=\"source?.permissions\"\r\n [showReplyAction]=\"false\"\r\n [editing]=\"selectedMessage.transientState.editing\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (editStarted)=\"startEditing(selectedMessage)\"\r\n (editEnded)=\"selectedMessage.transientState.editing = false\"\r\n (edited)=\"saveEdit(selectedMessage, $event)\"\r\n (userSelected)=\"selectMessageUser(selectedMessage)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (liked)=\"likeMessage(source, selectedMessage)\"\r\n (unliked)=\"unlikeMessage(source, selectedMessage)\"\r\n (reported)=\"reportMessage(selectedMessage)\"\r\n (selected)=\"selectMessage(selectedMessage)\"\r\n (shared)=\"shareMessage($event)\"\r\n (deleted)=\"deleteMessage(selectedMessage)\"\r\n ></banta-comment>\r\n\r\n <div class=\"replies\">\r\n\r\n <ng-container *ngIf=\"!selectedMessageThread\">\r\n <div class=\"loading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedMessageThread\">\r\n <banta-comment-view\r\n [source]=\"selectedMessageThread\"\r\n [allowReplies]=\"false\"\r\n [fixedHeight]=\"false\"\r\n [showEmptyState]=\"false\"\r\n [newestLast]=\"true\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (liked)=\"likeMessage(selectedMessageThread, $event)\"\r\n (unliked)=\"unlikeMessage(selectedMessageThread, $event)\"\r\n (messageEdited)=\"editMessage(selectedMessageThread, $event.message, $event.newMessage)\"\r\n (reported)=\"reportMessage($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (shared)=\"shareMessage($event)\"\r\n (deleted)=\"deleteMessage($event)\"\r\n ></banta-comment-view>\r\n\r\n <banta-comment-field\r\n [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n (signInSelected)=\"showSignIn()\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n [source]=\"selectedMessageThread\"\r\n [maxLength]=\"maxCommentLength\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInLabel]=\"signInLabel\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [user]=\"user\"\r\n [label]=\"postReplyLabel\"\r\n [submit]=\"sendReply\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"sendReplyOptionsTemplate\"></ng-container>\r\n </banta-comment-field>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <div class=\"main\" [class.hidden]=\"selectedMessage && !useInlineReplies\">\r\n <banta-comment-field\r\n [source]=\"source\"\r\n [user]=\"user\"\r\n [sendLabel]=\"sendLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [signInLabel]=\"signInLabel\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n [label]=\"postCommentLabel\"\r\n [maxLength]=\"maxCommentLength\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n (signInSelected)=\"showSignIn()\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [submit]=\"sendMessage\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n >\r\n \r\n </banta-comment-field>\r\n\r\n <banta-comment-sort\r\n [(sort)]=\"sortOrder\"></banta-comment-sort>\r\n\r\n <banta-comment-view\r\n [class.faded]=\"selectedMessage && !useInlineReplies\"\r\n [source]=\"source\"\r\n [fixedHeight]=\"fixedHeight\"\r\n [maxMessages]=\"maxMessages\"\r\n [maxVisibleMessages]=\"maxVisibleMessages\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (userSelected)=\"selectMessageUser($event)\"\r\n (sortOrderChanged)=\"sortOrder = $event\"\r\n (selected)=\"selectMessage($event)\"\r\n (liked)=\"likeMessage(source, $event)\"\r\n (unliked)=\"unlikeMessage(source, $event)\"\r\n (messageEdited)=\"editMessage(source, $event.message, $event.newMessage)\"\r\n (reported)=\"reportMessage($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (shared)=\"shareMessage($event)\"\r\n [selectedMessage]=\"selectedMessage\"\r\n (deleted)=\"deleteMessage($event)\"\r\n >\r\n <div class=\"inline-replies\">\r\n <div class=\"focused\" [class.visible]=\"selectedMessageVisible\" *ngIf=\"selectedMessage\">\r\n <div class=\"replies\">\r\n \r\n <ng-container *ngIf=\"!selectedMessageThread\">\r\n <div class=\"loading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n </ng-container>\r\n \r\n <ng-container *ngIf=\"selectedMessageThread\">\r\n <banta-comment-view\r\n [source]=\"selectedMessageThread\"\r\n [allowReplies]=\"false\"\r\n [fixedHeight]=\"false\"\r\n [showEmptyState]=\"false\"\r\n [newestLast]=\"true\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (liked)=\"likeMessage(selectedMessageThread, $event)\"\r\n (unliked)=\"unlikeMessage(selectedMessageThread, $event)\"\r\n (messageEdited)=\"editMessage(selectedMessageThread, $event.message, $event.newMessage)\"\r\n (reported)=\"reportMessage($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (shared)=\"shareMessage($event)\"\r\n (deleted)=\"deleteMessage($event)\"\r\n ></banta-comment-view>\r\n \r\n <banta-comment-field\r\n [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n (signInSelected)=\"showSignIn()\"\r\n [maxLength]=\"maxCommentLength\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n [source]=\"selectedMessageThread\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInLabel]=\"signInLabel\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [user]=\"user\"\r\n [label]=\"postReplyLabel\"\r\n [submit]=\"sendReply\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"sendReplyOptionsTemplate\"></ng-container>\r\n </banta-comment-field>\r\n </ng-container>\r\n </div>\r\n </div> \r\n </div>\r\n </banta-comment-view>\r\n </div>\r\n</ng-container>\r\n",
9657
+ template: "<ng-container *ngIf=\"loading\">\r\n <div class=\"loading-screen\" [class.visible]=\"showLoadingScreen\">\r\n <h1>Loading...</h1>\r\n <div>\r\n <mat-spinner [diameter]=\"300\" [strokeWidth]=\"2\"></mat-spinner>\r\n </div>\r\n\r\n <p class=\"loading-message\" [class.visible]=\"loadingMessageVisible\">{{loadingMessage}}</p>\r\n </div>\r\n</ng-container>\r\n<ng-container *ngIf=\"!loading\">\r\n <div class=\"focused\" [class.visible]=\"selectedMessageVisible\" *ngIf=\"selectedMessage && !useInlineReplies\">\r\n\r\n <div>\r\n <a mat-button href=\"javascript:;\" (click)=\"unselectMessage()\">\r\n <mat-icon>arrow_back</mat-icon>\r\n Latest Comments\r\n </a>\r\n </div>\r\n\r\n <banta-comment\r\n [message]=\"selectedMessage\"\r\n [liking]=\"selectedMessage.transientState.liking\"\r\n [mine]=\"user?.id === selectedMessage.user?.id\"\r\n [permissions]=\"source?.permissions\"\r\n [showReplyAction]=\"false\"\r\n [editing]=\"selectedMessage.transientState.editing\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (editStarted)=\"startEditing(selectedMessage)\"\r\n (editEnded)=\"selectedMessage.transientState.editing = false\"\r\n (edited)=\"saveEdit(selectedMessage, $event)\"\r\n (userSelected)=\"selectMessageUser(selectedMessage)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (liked)=\"likeMessage(source, selectedMessage)\"\r\n (unliked)=\"unlikeMessage(source, selectedMessage)\"\r\n (reported)=\"reportMessage(selectedMessage)\"\r\n (selected)=\"selectMessage(selectedMessage)\"\r\n (shared)=\"shareMessage($event)\"\r\n (deleted)=\"deleteMessage(selectedMessage)\"\r\n ></banta-comment>\r\n\r\n <div class=\"replies\">\r\n\r\n <ng-container *ngIf=\"!selectedMessageThread\">\r\n <div class=\"loading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedMessageThread\">\r\n <banta-comment-view\r\n [source]=\"selectedMessageThread\"\r\n [allowReplies]=\"false\"\r\n [fixedHeight]=\"false\"\r\n [showEmptyState]=\"false\"\r\n [newestLast]=\"true\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (liked)=\"likeMessage(selectedMessageThread, $event)\"\r\n (unliked)=\"unlikeMessage(selectedMessageThread, $event)\"\r\n (messageEdited)=\"editMessage(selectedMessageThread, $event.message, $event.newMessage)\"\r\n (reported)=\"reportMessage($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (shared)=\"shareMessage($event)\"\r\n (deleted)=\"deleteMessage($event)\"\r\n ></banta-comment-view>\r\n\r\n <banta-comment-field\r\n [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n (signInSelected)=\"showSignIn()\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n [source]=\"selectedMessageThread\"\r\n [maxLength]=\"maxCommentLength\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInLabel]=\"signInLabel\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [user]=\"user\"\r\n [label]=\"postReplyLabel\"\r\n [submit]=\"sendReply\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"sendReplyOptionsTemplate\"></ng-container>\r\n </banta-comment-field>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <div class=\"main\" [class.hidden]=\"selectedMessage && !useInlineReplies\">\r\n <banta-comment-field\r\n [source]=\"source\"\r\n [user]=\"user\"\r\n [sendLabel]=\"sendLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [signInLabel]=\"signInLabel\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n [label]=\"postCommentLabel\"\r\n [maxLength]=\"maxCommentLength\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n (signInSelected)=\"showSignIn()\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [submit]=\"sendMessage\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n >\r\n \r\n </banta-comment-field>\r\n\r\n <banta-comment-sort\r\n [(sort)]=\"sortOrder\"></banta-comment-sort>\r\n\r\n <banta-comment-view\r\n [class.faded]=\"selectedMessage && !useInlineReplies\"\r\n [source]=\"source\"\r\n [fixedHeight]=\"fixedHeight\"\r\n [maxMessages]=\"maxMessages\"\r\n [maxVisibleMessages]=\"maxVisibleMessages\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (userSelected)=\"selectMessageUser($event)\"\r\n (sortOrderChanged)=\"sortOrder = $event\"\r\n (selected)=\"selectMessage($event)\"\r\n (liked)=\"likeMessage(source, $event)\"\r\n (unliked)=\"unlikeMessage(source, $event)\"\r\n (messageEdited)=\"editMessage(source, $event.message, $event.newMessage)\"\r\n (reported)=\"reportMessage($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (shared)=\"shareMessage($event)\"\r\n [selectedMessage]=\"selectedMessage\"\r\n (deleted)=\"deleteMessage($event)\"\r\n >\r\n <div class=\"inline-replies\">\r\n <div class=\"focused\" [class.visible]=\"selectedMessageVisible\" *ngIf=\"selectedMessage\">\r\n <div class=\"replies\">\r\n \r\n <ng-container *ngIf=\"!selectedMessageThread\">\r\n <div class=\"loading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n </ng-container>\r\n \r\n <ng-container *ngIf=\"selectedMessageThread\">\r\n <banta-comment-view\r\n [source]=\"selectedMessageThread\"\r\n [allowReplies]=\"false\"\r\n [fixedHeight]=\"false\"\r\n [showEmptyState]=\"false\"\r\n [newestLast]=\"true\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (liked)=\"likeMessage(selectedMessageThread, $event)\"\r\n (unliked)=\"unlikeMessage(selectedMessageThread, $event)\"\r\n (messageEdited)=\"editMessage(selectedMessageThread, $event.message, $event.newMessage)\"\r\n (reported)=\"reportMessage($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (shared)=\"shareMessage($event)\"\r\n (deleted)=\"deleteMessage($event)\"\r\n ></banta-comment-view>\r\n \r\n <banta-comment-field\r\n [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n (signInSelected)=\"showSignIn()\"\r\n [maxLength]=\"maxCommentLength\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n [source]=\"selectedMessageThread\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInLabel]=\"signInLabel\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [user]=\"user\"\r\n [label]=\"postReplyLabel\"\r\n [submit]=\"sendReply\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"sendReplyOptionsTemplate\"></ng-container>\r\n </banta-comment-field>\r\n </ng-container>\r\n </div>\r\n </div> \r\n </div>\r\n </banta-comment-view>\r\n </div>\r\n</ng-container>\r\n",
9738
9658
  styles: [":host{display:flex;flex-direction:column}@-webkit-keyframes select-comment{0%{transform:scale(1.15)}to{transform:scale(1)}}@keyframes select-comment{0%{transform:scale(1.15)}to{transform:scale(1)}}.focused{-webkit-animation-name:select-comment;animation-name:select-comment;-webkit-animation-duration:.4s;animation-duration:.4s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.focused .replies{margin-top:1em;margin-left:2em;border-left:2px solid #333;padding-left:2em}banta-comment-view{opacity:1;transition:opacity .4s ease-in-out}banta-comment-view.faded{opacity:.25}.loading{display:block;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;margin:0 auto;min-height:16em}.main.hidden{display:none}.loading-screen{text-align:center;opacity:0;transition:opacity .25s ease-in-out}.loading-screen.visible{opacity:1}.loading-screen h1{font-weight:100}.loading-screen mat-spinner{margin:5em auto}.loading-screen .loading-message{opacity:0;transition:opacity .25s ease-in-out;width:500px;max-width:100%;margin:0 auto}.loading-screen .loading-message.visible{opacity:1}banta-comment-sort{margin:0 0 0 auto;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;display:block}.inline-replies{margin-left:4em}@media (max-width:500px){.focused .replies{margin-left:0}.inline-replies{margin-left:1em}.focused .replies{padding-left:.5em}banta-comment-sort{margin:0;width:100%}}:host-context(.banta-mobile) .focused .replies{margin-left:0}:host-context(.banta-mobile) .inline-replies{margin-left:1em}:host-context(.banta-mobile) .focused .replies{padding-left:.5em}:host-context(.banta-mobile) banta-comment-sort{margin:0;width:100%}"]
9739
9659
  },] }
9740
9660
  ];
@@ -9861,6 +9781,7 @@
9861
9781
  var CommentFieldComponent = /** @class */ (function () {
9862
9782
  function CommentFieldComponent(chatBackend) {
9863
9783
  this.chatBackend = chatBackend;
9784
+ this._subs = new rxjs.Subscription();
9864
9785
  this.canComment = true;
9865
9786
  this.allowAttachments = false;
9866
9787
  this.signInSelected = new rxjs.Subject();
@@ -9885,6 +9806,40 @@
9885
9806
  this.autoCompleteSelected = 0;
9886
9807
  this.chatMessageAttachments = [];
9887
9808
  }
9809
+ Object.defineProperty(CommentFieldComponent.prototype, "source", {
9810
+ get: function () {
9811
+ return this._source;
9812
+ },
9813
+ set: function (value) {
9814
+ var _this = this;
9815
+ var _a;
9816
+ if (this._source) {
9817
+ (_a = this._subs) === null || _a === void 0 ? void 0 : _a.unsubscribe();
9818
+ this._source = null;
9819
+ }
9820
+ this._source = value;
9821
+ this._subs = new rxjs.Subscription();
9822
+ if (this._source) {
9823
+ setTimeout(function () {
9824
+ if (_this._source.connectionStateChanged) {
9825
+ _this._subs.add(_this._source.connectionStateChanged.subscribe(function (state) {
9826
+ if (state === 'lost') {
9827
+ _this.transientMessage = "Reconnecting...";
9828
+ }
9829
+ else if (state === 'restored') {
9830
+ _this.transientMessage = undefined;
9831
+ }
9832
+ else if (state === 'connecting') {
9833
+ _this.transientMessage = "Connecting...";
9834
+ }
9835
+ }));
9836
+ }
9837
+ });
9838
+ }
9839
+ },
9840
+ enumerable: false,
9841
+ configurable: true
9842
+ });
9888
9843
  Object.defineProperty(CommentFieldComponent.prototype, "text", {
9889
9844
  get: function () {
9890
9845
  return this._text;
@@ -10348,8 +10303,8 @@
10348
10303
  CommentFieldComponent.decorators = [
10349
10304
  { type: core.Component, args: [{
10350
10305
  selector: 'banta-comment-field',
10351
- template: "<form class=\"new-message\" (submit)=\"sendMessage()\">\r\n <div class=\"avatar-container\">\r\n <a href=\"javascript:;\"\r\n class=\"avatar\"\r\n (click)=\"showEditAvatar()\"\r\n [style.background-image]=\"'url(' + userAvatarUrl + ')'\"\r\n ></a>\r\n </div>\r\n <div class=\"text-container\">\r\n <div class=\"field-container\">\r\n <div class=\"field-row\">\r\n <mat-form-field appearance=\"outline\" floatLabel=\"always\">\r\n <mat-label>{{label}}</mat-label>\r\n <textarea\r\n #textarea\r\n name=\"message\"\r\n [placeholder]=\"placeholder\"\r\n matInput\r\n cdkTextareaAutosize\r\n [maxlength]=\"maxLength\"\r\n (keydown)=\"onKeyDown($event)\"\r\n (blur)=\"onBlur()\"\r\n [disabled]=\"sending\"\r\n [(ngModel)]=\"text\"></textarea>\r\n </mat-form-field>\r\n <div class=\"options-line\">\r\n <mat-spinner *ngIf=\"sending\" class=\"icon loading\" diameter=\"18\" strokeWidth=\"2\"></mat-spinner>\r\n <div *ngIf=\"sendError\" class=\"error-message\" [class.expanded]=\"expandError\" [matTooltip]=\"sendError.message\" (click)=\"alertError()\">\r\n <mat-icon *ngIf=\"sendError\">error</mat-icon>\r\n {{sendError.message}}\r\n </div>\r\n <div class=\"spacer\"></div>\r\n <div class=\"custom\">\r\n <ng-content></ng-content>\r\n </div>\r\n <banta-attachment-button \r\n *ngIf=\"allowAttachments\"\r\n (addedAttachment)=\"addedAttachment($event)\"\r\n (attachmentError)=\"attachmentError($event)\"\r\n ></banta-attachment-button>\r\n <emoji-selector-button (selected)=\"insertEmoji($event)\"></emoji-selector-button>\r\n </div>\r\n \r\n </div>\r\n <div #autocompleteContainer class=\"autocomplete-container\">\r\n <div #autocomplete class=\"autocomplete\" [class.visible]=\"autocompleteVisible\">\r\n\r\n <div>\r\n <strong>{{completionPrefix}}</strong>...\r\n </div>\r\n <a\r\n mat-button\r\n *ngFor=\"let option of autocompleteOptions; index as index\"\r\n (click)=\"activateAutoComplete(option)\"\r\n [class.active]=\"autoCompleteSelected === index\"\r\n >\r\n {{option.label}}\r\n </a>\r\n </div>\r\n </div>\r\n\r\n <banta-attachments \r\n [attachments]=\"chatMessageAttachments\"\r\n [editing]=\"true\"\r\n (remove)=\"removeAttachment($event)\"\r\n ></banta-attachments>\r\n </div>\r\n </div>\r\n <div class=\"actions\">\r\n <ng-container *ngIf=\"!user\">\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n type=\"button\"\r\n (click)=\"showSignIn()\"\r\n >{{signInLabel}}</button>\r\n </ng-container>\r\n <ng-container *ngIf=\"user\">\r\n <button\r\n mat-raised-button\r\n class=\"send\"\r\n color=\"primary\"\r\n [disabled]=\"!sendButtonEnabled\"\r\n >\r\n <ng-container *ngIf=\"canComment\">\r\n <mat-icon *ngIf=\"!sending\">chevron_right</mat-icon>\r\n <mat-spinner *ngIf=\"sending\" class=\"icon\" diameter=\"18\" strokeWidth=\"2\"></mat-spinner>\r\n </ng-container>\r\n <span class=\"label\">\r\n <ng-container *ngIf=\"!canComment\">\r\n {{permissionDeniedLabel}}\r\n </ng-container>\r\n <ng-container *ngIf=\"canComment\">\r\n <ng-container *ngIf=\"!sending\">\r\n {{sendLabel}}\r\n </ng-container>\r\n <ng-container *ngIf=\"sending\">\r\n {{sendingLabel}}\r\n </ng-container>\r\n </ng-container>\r\n </span>\r\n </button>\r\n </ng-container>\r\n </div>\r\n</form>",
10352
- styles: ["@-webkit-keyframes comment-field-appear{0%{transform:translateY(128px);opacity:0}to{transform:translate(0);opacity:1}}@keyframes comment-field-appear{0%{transform:translateY(128px);opacity:0}to{transform:translate(0);opacity:1}}:host{margin:0 2em 0 0;display:block;-webkit-animation-name:comment-field-appear;animation-name:comment-field-appear;-webkit-animation-duration:.8s;animation-duration:.8s;-webkit-animation-delay:.4s;animation-delay:.4s;-webkit-animation-fill-mode:both;animation-fill-mode:both;position:relative;z-index:20}.avatar-container{width:calc(48px + 1.75em);display:flex;justify-content:flex-end;flex-shrink:0}.avatar-container .avatar{width:48px;height:48px;background:#000;border-radius:100%;background-size:cover;background-repeat:no-repeat;background-position:50%;margin-top:.75em;margin-right:.75em}form{display:flex;padding:.5em;align-items:center}form .text-container{position:relative;display:flex;flex-grow:1;min-width:0}form .text-container textarea{font-size:14pt;width:100%}form .text-container textarea[disabled]{opacity:.5}form .text-container mat-spinner.loading{position:absolute;left:.5em;bottom:.5em}form .text-container .options-line{display:flex;align-items:center}form .text-container .options-line>*{flex-shrink:0}form .text-container .options-line .error-message{left:.5em;bottom:.5em;color:#683333;overflow-x:hidden;max-width:1.5em;white-space:nowrap;transition:max-width 2s ease-in-out;text-overflow:ellipsis;overflow:hidden;flex-shrink:1}form .text-container .options-line .error-message.expanded,form .text-container .options-line .error-message:hover{max-width:100%}form .text-container .options-line .error-message mat-icon{vertical-align:middle}form input[type=text]{background:#000;color:#fff;border:1px solid #333;width:100%;height:1em}form .actions{margin-left:1em;flex-shrink:0}form button{display:block;margin:0 0 0 auto}form.new-message{display:flex;align-items:flex-start;min-width:0}form.new-message .field-container{flex-grow:1;display:flex;flex-direction:column;min-width:0}form.new-message mat-form-field{width:100%}form.new-message mat-form-field ::ng-deep .mat-form-field-wrapper{padding-bottom:0}form.new-message button{margin:1.25em 0 0}button.send{min-width:9em}textarea{max-height:7em}.autocomplete-container{width:calc(100% - 2em);position:relative;pointer-events:none;top:-2em}.autocomplete{visibility:hidden;pointer-events:none;position:absolute;background:#333;padding:.5em;display:flex;flex-direction:column;z-index:100}.autocomplete.visible{visibility:visible;pointer-events:auto}.autocomplete a{width:100%;text-align:left}.autocomplete a.active{background:#555}@media (max-width:500px){:host{margin:0}.avatar-container{width:auto;flex-shrink:0}.avatar-container .avatar{width:32px;height:32px;margin-top:1.5em}button.send{min-width:auto;margin-top:1.5em}button.send .label{display:none}}:host-context(.banta-mobile) :host{margin:0}:host-context(.banta-mobile) .avatar-container{width:auto;flex-shrink:0}:host-context(.banta-mobile) .avatar-container .avatar{width:32px;height:32px;margin-top:1.5em}:host-context(.banta-mobile) button.send{min-width:auto;margin-top:1.5em}:host-context(.banta-mobile) button.send .label{display:none}.image-attachments-container{display:flex;gap:20px}.image-attachments-container .image-attachment{width:300px;position:relative;text-align:center}.image-attachments-container .image-attachment.with-border{outline:1px solid #333;padding:1em 0}.image-attachments-container .image-attachment mat-spinner{display:block;margin:0 auto .5em;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.image-attachments-container .image-attachment mat-icon.error{display:block;font-size:48px;width:48px;height:48px;margin:0 auto .5em}.image-attachments-container .image-attachment .error{color:#b76363}.image-attachments-container .image-attachment img{width:300px;border-radius:10px}.image-attachments-container .image-attachment .remove-img{position:absolute;right:10px;top:10px;margin:0}.card-attachment,.field-row{position:relative}.card-attachment a{display:flex;align-items:flex-start;gap:1em;width:100%;border:1px solid #666;border-radius:4px;padding:2em;box-sizing:border-box;background-color:#191919}.card-attachment a img{width:300px;aspect-ratio:16/9;-o-object-fit:cover;object-fit:cover;border-radius:10px}.card-attachment a h1{margin:0;font-size:30px}.card-attachment .remove-img{position:absolute;right:10px;top:10px;margin:0}"]
10306
+ template: "<form class=\"new-message\" (submit)=\"sendMessage()\">\r\n <div class=\"avatar-container\">\r\n <a href=\"javascript:;\"\r\n class=\"avatar\"\r\n (click)=\"showEditAvatar()\"\r\n [style.background-image]=\"'url(' + userAvatarUrl + ')'\"\r\n ></a>\r\n </div>\r\n <div class=\"text-container\">\r\n <div class=\"field-container\">\r\n <div class=\"field-row\">\r\n <mat-form-field class=\"message-field\" appearance=\"outline\" floatLabel=\"always\">\r\n <mat-label>{{label}}</mat-label>\r\n <textarea\r\n #textarea\r\n name=\"message\"\r\n [placeholder]=\"placeholder\"\r\n matInput\r\n cdkTextareaAutosize\r\n [maxlength]=\"maxLength\"\r\n (keydown)=\"onKeyDown($event)\"\r\n (blur)=\"onBlur()\"\r\n [disabled]=\"sending\"\r\n [(ngModel)]=\"text\"></textarea>\r\n </mat-form-field>\r\n <div class=\"options-line\">\r\n <mat-spinner *ngIf=\"sending\" class=\"icon loading\" diameter=\"18\" strokeWidth=\"2\"></mat-spinner>\r\n <div *ngIf=\"sendError\" class=\"error-message\" [class.expanded]=\"expandError\" [matTooltip]=\"sendError.message\" (click)=\"alertError()\">\r\n <mat-icon *ngIf=\"sendError\">error</mat-icon>\r\n {{sendError.message}}\r\n </div>\r\n <div *ngIf=\"!sendError && transientMessage\" class=\"transient-message\" [class.expanded]=\"true\" [matTooltip]=\"transientMessage\" (click)=\"alertError()\">\r\n <mat-spinner [inline]=\"true\" [diameter]=\"15\"></mat-spinner>\r\n {{transientMessage}}\r\n </div>\r\n <div class=\"spacer\"></div>\r\n <div class=\"custom\">\r\n <ng-content></ng-content>\r\n </div>\r\n <banta-attachment-button \r\n *ngIf=\"allowAttachments\"\r\n (addedAttachment)=\"addedAttachment($event)\"\r\n (attachmentError)=\"attachmentError($event)\"\r\n ></banta-attachment-button>\r\n <emoji-selector-button (selected)=\"insertEmoji($event)\"></emoji-selector-button>\r\n </div>\r\n \r\n </div>\r\n <div #autocompleteContainer class=\"autocomplete-container\">\r\n <div #autocomplete class=\"autocomplete\" [class.visible]=\"autocompleteVisible\">\r\n\r\n <div>\r\n <strong>{{completionPrefix}}</strong>...\r\n </div>\r\n <a\r\n mat-button\r\n *ngFor=\"let option of autocompleteOptions; index as index\"\r\n (click)=\"activateAutoComplete(option)\"\r\n [class.active]=\"autoCompleteSelected === index\"\r\n >\r\n {{option.label}}\r\n </a>\r\n </div>\r\n </div>\r\n\r\n <banta-attachments \r\n [attachments]=\"chatMessageAttachments\"\r\n [editing]=\"true\"\r\n (remove)=\"removeAttachment($event)\"\r\n ></banta-attachments>\r\n </div>\r\n </div>\r\n <div class=\"actions\">\r\n <ng-container *ngIf=\"!user\">\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n type=\"button\"\r\n (click)=\"showSignIn()\"\r\n >{{signInLabel}}</button>\r\n </ng-container>\r\n <ng-container *ngIf=\"user\">\r\n <button\r\n mat-raised-button\r\n class=\"send\"\r\n color=\"primary\"\r\n [disabled]=\"!sendButtonEnabled\"\r\n >\r\n <ng-container *ngIf=\"canComment\">\r\n <mat-icon *ngIf=\"!sending\">chevron_right</mat-icon>\r\n <mat-spinner *ngIf=\"sending\" class=\"icon\" diameter=\"18\" strokeWidth=\"2\"></mat-spinner>\r\n </ng-container>\r\n <span class=\"label\">\r\n <ng-container *ngIf=\"!canComment\">\r\n {{permissionDeniedLabel}}\r\n </ng-container>\r\n <ng-container *ngIf=\"canComment\">\r\n <ng-container *ngIf=\"!sending\">\r\n {{sendLabel}}\r\n </ng-container>\r\n <ng-container *ngIf=\"sending\">\r\n {{sendingLabel}}\r\n </ng-container>\r\n </ng-container>\r\n </span>\r\n </button>\r\n </ng-container>\r\n </div>\r\n</form>",
10307
+ styles: ["@-webkit-keyframes comment-field-appear{0%{transform:translateY(128px);opacity:0}to{transform:translate(0);opacity:1}}@keyframes comment-field-appear{0%{transform:translateY(128px);opacity:0}to{transform:translate(0);opacity:1}}:host{margin:0 2em 0 0;display:block;-webkit-animation-name:comment-field-appear;animation-name:comment-field-appear;-webkit-animation-duration:.8s;animation-duration:.8s;-webkit-animation-delay:.4s;animation-delay:.4s;-webkit-animation-fill-mode:both;animation-fill-mode:both;position:relative;z-index:20}.avatar-container{width:calc(48px + 1.75em);display:flex;justify-content:flex-end;flex-shrink:0}.avatar-container .avatar{width:48px;height:48px;background:#000;border-radius:100%;background-size:cover;background-repeat:no-repeat;background-position:50%;margin-top:.75em;margin-right:.75em}form{display:flex;padding:.5em;align-items:center}form .text-container{position:relative;display:flex;flex-grow:1;min-width:0}form .text-container textarea{font-size:14pt;width:100%}form .text-container textarea[disabled]{opacity:.5}form .text-container mat-spinner.loading{position:absolute;left:.5em;bottom:.5em}form .text-container .options-line{display:flex;align-items:center}form .text-container .options-line>*{flex-shrink:0}form .text-container .options-line .transient-message{display:flex;flex-direction:row;align-items:center;gap:.5em}form .text-container .options-line .error-message{left:.5em;bottom:.5em;color:#683333;overflow-x:hidden;max-width:1.5em;white-space:nowrap;transition:max-width 2s ease-in-out;text-overflow:ellipsis;overflow:hidden;flex-shrink:1}form .text-container .options-line .error-message.expanded,form .text-container .options-line .error-message:hover{max-width:100%}form .text-container .options-line .error-message mat-icon{vertical-align:middle}form input[type=text]{background:#000;color:#fff;border:1px solid #333;width:100%;height:1em}form .actions{margin-left:1em;flex-shrink:0}form button{display:block;margin:0 0 0 auto}form.new-message{display:flex;align-items:flex-start;min-width:0}form.new-message .field-container{flex-grow:1;display:flex;flex-direction:column;min-width:0}form.new-message mat-form-field{width:100%}form.new-message mat-form-field ::ng-deep .mat-form-field-wrapper{padding-bottom:0}form.new-message button{margin:1.25em 0 0}button.send{min-width:9em}textarea{max-height:7em}.autocomplete-container{width:calc(100% - 2em);position:relative;pointer-events:none;top:-2em}.autocomplete{visibility:hidden;pointer-events:none;position:absolute;background:#333;padding:.5em;display:flex;flex-direction:column;z-index:100}.autocomplete.visible{visibility:visible;pointer-events:auto}.autocomplete a{width:100%;text-align:left}.autocomplete a.active{background:#555}.image-attachments-container{display:flex;gap:20px}.image-attachments-container .image-attachment{width:300px;position:relative;text-align:center}.image-attachments-container .image-attachment.with-border{outline:1px solid #333;padding:1em 0}.image-attachments-container .image-attachment mat-spinner{display:block;margin:0 auto .5em;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.image-attachments-container .image-attachment mat-icon.error{display:block;font-size:48px;width:48px;height:48px;margin:0 auto .5em}.image-attachments-container .image-attachment .error{color:#b76363}.image-attachments-container .image-attachment img{width:300px;border-radius:10px}.image-attachments-container .image-attachment .remove-img{position:absolute;right:10px;top:10px;margin:0}.card-attachment,.field-row{position:relative}.card-attachment a{display:flex;align-items:flex-start;gap:1em;width:100%;border:1px solid #666;border-radius:4px;padding:2em;box-sizing:border-box;background-color:#191919}.card-attachment a img{width:300px;aspect-ratio:16/9;-o-object-fit:cover;object-fit:cover;border-radius:10px}.card-attachment a h1{margin:0;font-size:30px}.card-attachment .remove-img{position:absolute;right:10px;top:10px;margin:0}@media (max-width:500px){:host{margin:0}.avatar-container{width:auto;flex-shrink:0}.avatar-container .avatar{width:32px;height:32px;margin-top:1.5em}:host.can-comment button.send .label,:host:not(.can-comment) .text-container,:host:not(.can-comment) mat-form-field.message-field{display:none}button.send{min-width:auto;margin-top:1.5em}}:host-context(.banta-mobile) :host{margin:0}:host-context(.banta-mobile) .avatar-container{width:auto;flex-shrink:0}:host-context(.banta-mobile) .avatar-container .avatar{width:32px;height:32px;margin-top:1.5em}:host-context(.banta-mobile) :host.can-comment button.send .label,:host-context(.banta-mobile) :host:not(.can-comment) .text-container,:host-context(.banta-mobile) :host:not(.can-comment) mat-form-field.message-field{display:none}:host-context(.banta-mobile) button.send{min-width:auto;margin-top:1.5em}"]
10353
10308
  },] }
10354
10309
  ];
10355
10310
  CommentFieldComponent.ctorParameters = function () { return [
@@ -10358,10 +10313,11 @@
10358
10313
  CommentFieldComponent.propDecorators = {
10359
10314
  source: [{ type: core.Input }],
10360
10315
  user: [{ type: core.Input }],
10361
- canComment: [{ type: core.Input }],
10316
+ canComment: [{ type: core.HostBinding, args: ['class.can-comment',] }, { type: core.Input }],
10362
10317
  allowAttachments: [{ type: core.Input }],
10363
10318
  signInSelected: [{ type: core.Output }],
10364
10319
  editAvatarSelected: [{ type: core.Output }],
10320
+ transientMessage: [{ type: core.Input }],
10365
10321
  sendLabel: [{ type: core.Input }],
10366
10322
  sendingLabel: [{ type: core.Input }],
10367
10323
  label: [{ type: core.Input }],
@@ -10557,7 +10513,8 @@
10557
10513
  _this.parentIdentifier = parentIdentifier;
10558
10514
  _this.sortOrder = sortOrder;
10559
10515
  _this.subscription = new rxjs.Subscription();
10560
- _this.state = 'connecting';
10516
+ _this._state = 'connecting';
10517
+ _this._connectionStateChanged = new rxjs.Subject();
10561
10518
  _this.messageMap = new Map();
10562
10519
  _this._messageReceived = new rxjs.Subject();
10563
10520
  _this._messageUpdated = new rxjs.Subject();
@@ -10566,6 +10523,25 @@
10566
10523
  _this.ready = new Promise(function (resolve) { return _this.markReady = resolve; });
10567
10524
  return _this;
10568
10525
  }
10526
+ Object.defineProperty(ChatSource.prototype, "state", {
10527
+ get: function () {
10528
+ return this._state;
10529
+ },
10530
+ set: function (value) {
10531
+ var _this = this;
10532
+ this._state = value;
10533
+ setTimeout(function () { return _this._connectionStateChanged.next(_this._state); });
10534
+ },
10535
+ enumerable: false,
10536
+ configurable: true
10537
+ });
10538
+ Object.defineProperty(ChatSource.prototype, "connectionStateChanged", {
10539
+ get: function () {
10540
+ return this._connectionStateChanged.asObservable();
10541
+ },
10542
+ enumerable: false,
10543
+ configurable: true
10544
+ });
10569
10545
  ChatSource.prototype.bind = function (socket) {
10570
10546
  var _super = Object.create(null, {
10571
10547
  bind: { get: function () { return _super_1.prototype.bind; } }
@@ -10636,14 +10612,36 @@
10636
10612
  });
10637
10613
  });
10638
10614
  };
10639
- ChatSource.prototype.editMessage = function (messageId, text) {
10615
+ ChatSource.prototype.ensureConnection = function (errorMessage) {
10640
10616
  return __awaiter(this, void 0, void 0, function () {
10617
+ var reason;
10641
10618
  return __generator(this, function (_b) {
10642
- this.peer.editMessage(messageId, text);
10619
+ reason = "Connection to chat services is not currently available.";
10620
+ if (this.state !== 'connected' && this.state !== 'restored') {
10621
+ if (errorMessage)
10622
+ throw new Error(errorMessage + ": " + reason);
10623
+ else
10624
+ throw new Error("" + reason);
10625
+ }
10643
10626
  return [2 /*return*/];
10644
10627
  });
10645
10628
  });
10646
10629
  };
10630
+ ChatSource.prototype.editMessage = function (messageId, text) {
10631
+ return __awaiter(this, void 0, void 0, function () {
10632
+ return __generator(this, function (_b) {
10633
+ switch (_b.label) {
10634
+ case 0: return [4 /*yield*/, this.ensureConnection()];
10635
+ case 1:
10636
+ _b.sent();
10637
+ return [4 /*yield*/, this.peer.editMessage(messageId, text)];
10638
+ case 2:
10639
+ _b.sent();
10640
+ return [2 /*return*/];
10641
+ }
10642
+ });
10643
+ });
10644
+ };
10647
10645
  ChatSource.prototype.subscribeToTopic = function () {
10648
10646
  return __awaiter(this, void 0, void 0, function () {
10649
10647
  return __generator(this, function (_b) {
@@ -10721,8 +10719,11 @@
10721
10719
  return __awaiter(this, void 0, void 0, function () {
10722
10720
  return __generator(this, function (_b) {
10723
10721
  switch (_b.label) {
10724
- case 0: return [4 /*yield*/, this.peer.sendMessage(message)];
10725
- case 1: return [2 /*return*/, _b.sent()];
10722
+ case 0: return [4 /*yield*/, this.ensureConnection()];
10723
+ case 1:
10724
+ _b.sent();
10725
+ return [4 /*yield*/, this.peer.sendMessage(message)];
10726
+ case 2: return [2 /*return*/, _b.sent()];
10726
10727
  }
10727
10728
  });
10728
10729
  });
@@ -10746,8 +10747,11 @@
10746
10747
  case 0:
10747
10748
  if (this.messageMap.has(id))
10748
10749
  return [2 /*return*/, this.messageMap.get(id)];
10749
- return [4 /*yield*/, this.peer.getMessage(id)];
10750
+ return [4 /*yield*/, this.ensureConnection("Could not get message")];
10750
10751
  case 1:
10752
+ _b.sent();
10753
+ return [4 /*yield*/, this.peer.getMessage(id)];
10754
+ case 2:
10751
10755
  message = _b.sent();
10752
10756
  this.messageMap.set(id, message);
10753
10757
  return [2 /*return*/, message];
@@ -10769,8 +10773,11 @@
10769
10773
  return __awaiter(this, void 0, void 0, function () {
10770
10774
  return __generator(this, function (_b) {
10771
10775
  switch (_b.label) {
10772
- case 0: return [4 /*yield*/, this.peer.likeMessage(messageId)];
10773
- case 1: return [2 /*return*/, _b.sent()];
10776
+ case 0: return [4 /*yield*/, this.ensureConnection()];
10777
+ case 1:
10778
+ _b.sent();
10779
+ return [4 /*yield*/, this.peer.likeMessage(messageId)];
10780
+ case 2: return [2 /*return*/, _b.sent()];
10774
10781
  }
10775
10782
  });
10776
10783
  });
@@ -10779,8 +10786,11 @@
10779
10786
  return __awaiter(this, void 0, void 0, function () {
10780
10787
  return __generator(this, function (_b) {
10781
10788
  switch (_b.label) {
10782
- case 0: return [4 /*yield*/, this.peer.unlikeMessage(messageId)];
10783
- case 1: return [2 /*return*/, _b.sent()];
10789
+ case 0: return [4 /*yield*/, this.ensureConnection()];
10790
+ case 1:
10791
+ _b.sent();
10792
+ return [4 /*yield*/, this.peer.unlikeMessage(messageId)];
10793
+ case 2: return [2 /*return*/, _b.sent()];
10784
10794
  }
10785
10795
  });
10786
10796
  });
@@ -10789,8 +10799,11 @@
10789
10799
  return __awaiter(this, void 0, void 0, function () {
10790
10800
  return __generator(this, function (_b) {
10791
10801
  switch (_b.label) {
10792
- case 0: return [4 /*yield*/, this.peer.deleteMessage(messageId)];
10793
- case 1: return [2 /*return*/, _b.sent()];
10802
+ case 0: return [4 /*yield*/, this.ensureConnection()];
10803
+ case 1:
10804
+ _b.sent();
10805
+ return [4 /*yield*/, this.peer.deleteMessage(messageId)];
10806
+ case 2: return [2 /*return*/, _b.sent()];
10794
10807
  }
10795
10808
  });
10796
10809
  });
@@ -10951,8 +10964,151 @@
10951
10964
  { type: undefined, decorators: [{ type: core.Inject, args: [BANTA_SDK_OPTIONS,] }] }
10952
10965
  ]; };
10953
10966
 
10967
+ var URL_REGEX = new RegExp('(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?', 'ig');
10968
+ var UrlAttachmentScraper = /** @class */ (function () {
10969
+ function UrlAttachmentScraper() {
10970
+ }
10971
+ UrlAttachmentScraper.prototype.findFragments = function (message) {
10972
+ var _a;
10973
+ // If a message already has a URL attachment, don't add another one.
10974
+ if (message.attachments && message.attachments.filter(function (x) { return x.type === 'url'; }).length > 0)
10975
+ return null;
10976
+ return (Array.from((_a = message.message.match(URL_REGEX)) !== null && _a !== void 0 ? _a : []))
10977
+ .reduce(function (a, item) { return (a.includes(item) ? undefined : a.push(item), a); }, [])
10978
+ .map(function (url) { return ({
10979
+ text: url,
10980
+ offset: message.message.indexOf(url),
10981
+ type: 'url'
10982
+ }); });
10983
+ };
10984
+ return UrlAttachmentScraper;
10985
+ }());
10986
+ var UrlAttachmentResolver = /** @class */ (function () {
10987
+ function UrlAttachmentResolver(backend) {
10988
+ this.backend = backend;
10989
+ }
10990
+ UrlAttachmentResolver.prototype.resolveFragment = function (message, fragment) {
10991
+ return __awaiter(this, void 0, void 0, function () {
10992
+ var urlCard;
10993
+ return __generator(this, function (_b) {
10994
+ switch (_b.label) {
10995
+ case 0:
10996
+ if (fragment.type !== 'url')
10997
+ return [2 /*return*/, null];
10998
+ return [4 /*yield*/, this.backend.getCardForUrl(fragment.text)];
10999
+ case 1:
11000
+ urlCard = _b.sent();
11001
+ if (urlCard) {
11002
+ return [2 /*return*/, {
11003
+ type: 'card',
11004
+ url: fragment.text,
11005
+ card: urlCard,
11006
+ style: 'block'
11007
+ }];
11008
+ }
11009
+ return [2 /*return*/];
11010
+ }
11011
+ });
11012
+ });
11013
+ };
11014
+ return UrlAttachmentResolver;
11015
+ }());
11016
+ UrlAttachmentResolver.decorators = [
11017
+ { type: core.Injectable }
11018
+ ];
11019
+ UrlAttachmentResolver.ctorParameters = function () { return [
11020
+ { type: ChatBackendBase }
11021
+ ]; };
11022
+
11023
+ var YouTubeAttachmentResolver = /** @class */ (function () {
11024
+ function YouTubeAttachmentResolver() {
11025
+ }
11026
+ YouTubeAttachmentResolver.prototype.resolveFragment = function (message, fragment) {
11027
+ return __awaiter(this, void 0, void 0, function () {
11028
+ var videoId, match;
11029
+ return __generator(this, function (_a) {
11030
+ if (fragment.type !== 'url')
11031
+ return [2 /*return*/, null];
11032
+ if (fragment.text.match(/https?:\/\/(www\.)?youtube.com\/watch\?v=/)) {
11033
+ match = /watch\?v=([^&]+)/.exec(fragment.text);
11034
+ if (match) {
11035
+ videoId = match[1];
11036
+ }
11037
+ }
11038
+ if (videoId) {
11039
+ return [2 /*return*/, {
11040
+ type: 'iframe',
11041
+ url: "https://www.youtube.com/embed/" + videoId,
11042
+ style: 'block'
11043
+ }];
11044
+ }
11045
+ return [2 /*return*/, null];
11046
+ });
11047
+ });
11048
+ };
11049
+ return YouTubeAttachmentResolver;
11050
+ }());
11051
+
11052
+ var GiphyAttachmentResolver = /** @class */ (function () {
11053
+ function GiphyAttachmentResolver() {
11054
+ }
11055
+ GiphyAttachmentResolver.prototype.resolveFragment = function (message, fragment) {
11056
+ var _a;
11057
+ return __awaiter(this, void 0, void 0, function () {
11058
+ var gifId;
11059
+ return __generator(this, function (_b) {
11060
+ if (fragment.type === 'url' && fragment.text.startsWith('https://giphy.com/gifs')) {
11061
+ gifId = (_a = /[^-\/]+$/.exec(fragment.text)) === null || _a === void 0 ? void 0 : _a.toString();
11062
+ if (!gifId)
11063
+ return [2 /*return*/, null];
11064
+ return [2 /*return*/, {
11065
+ type: 'iframe',
11066
+ url: "https://giphy.com/embed/" + gifId,
11067
+ style: 'inline'
11068
+ }];
11069
+ }
11070
+ return [2 /*return*/, null];
11071
+ });
11072
+ });
11073
+ };
11074
+ return GiphyAttachmentResolver;
11075
+ }());
11076
+
11077
+ var TweetAttachmentResolver = /** @class */ (function () {
11078
+ function TweetAttachmentResolver() {
11079
+ }
11080
+ TweetAttachmentResolver.prototype.resolveFragment = function (message, fragment) {
11081
+ return __awaiter(this, void 0, void 0, function () {
11082
+ return __generator(this, function (_a) {
11083
+ if (fragment.type === 'url' && fragment.text.startsWith('https://twitter.com/')) {
11084
+ return [2 /*return*/, {
11085
+ type: 'tweet',
11086
+ url: fragment.text,
11087
+ style: 'block'
11088
+ }];
11089
+ }
11090
+ return [2 /*return*/, null];
11091
+ });
11092
+ });
11093
+ };
11094
+ return TweetAttachmentResolver;
11095
+ }());
11096
+
10954
11097
  var BantaSdkModule = /** @class */ (function () {
10955
- function BantaSdkModule() {
11098
+ function BantaSdkModule(chatBackend) {
11099
+ if (typeof window !== 'undefined') {
11100
+ if (!document.querySelector('script[src="https://platform.twitter.com/widgets.js"]')) {
11101
+ var script = document.createElement('script');
11102
+ script.src = 'https://platform.twitter.com/widgets.js';
11103
+ script.async = true;
11104
+ document.body.appendChild(script);
11105
+ }
11106
+ }
11107
+ chatBackend.registerAttachmentScraper(new UrlAttachmentScraper());
11108
+ chatBackend.registerAttachmentResolver(new GiphyAttachmentResolver());
11109
+ chatBackend.registerAttachmentResolver(new YouTubeAttachmentResolver());
11110
+ chatBackend.registerAttachmentResolver(new TweetAttachmentResolver());
11111
+ chatBackend.registerAttachmentResolver(new UrlAttachmentResolver(chatBackend));
10956
11112
  }
10957
11113
  BantaSdkModule.configure = function (options) {
10958
11114
  return {
@@ -11002,7 +11158,10 @@
11002
11158
  CommentsModule
11003
11159
  ]
11004
11160
  },] }
11005
- ];
11161
+ ];
11162
+ BantaSdkModule.ctorParameters = function () { return [
11163
+ { type: ChatBackendBase }
11164
+ ]; };
11006
11165
 
11007
11166
  /*
11008
11167
  * Public API Surface of sdk
@@ -11014,6 +11173,8 @@
11014
11173
 
11015
11174
  exports.AttachmentButtonComponent = AttachmentButtonComponent;
11016
11175
  exports.BANTA_SDK_OPTIONS = BANTA_SDK_OPTIONS;
11176
+ exports.BantaAttachmentComponent = BantaAttachmentComponent;
11177
+ exports.BantaAttachmentsComponent = BantaAttachmentsComponent;
11017
11178
  exports.BantaChatComponent = BantaChatComponent;
11018
11179
  exports.BantaCommentsComponent = BantaCommentsComponent;
11019
11180
  exports.BantaCommonModule = BantaCommonModule;
@@ -11022,6 +11183,7 @@
11022
11183
  exports.BantaMarkdownToHtmlPipe = BantaMarkdownToHtmlPipe;
11023
11184
  exports.BantaReplySendOptionsDirective = BantaReplySendOptionsDirective;
11024
11185
  exports.BantaSdkModule = BantaSdkModule;
11186
+ exports.BantaTrustResourceUrlPipe = BantaTrustResourceUrlPipe;
11025
11187
  exports.ChatBackend = ChatBackend;
11026
11188
  exports.ChatBackendBase = ChatBackendBase;
11027
11189
  exports.ChatMessageComponent = ChatMessageComponent;
@@ -11037,11 +11199,16 @@
11037
11199
  exports.EmojiModule = EmojiModule;
11038
11200
  exports.EmojiSelectorButtonComponent = EmojiSelectorButtonComponent;
11039
11201
  exports.EmojiSelectorPanelComponent = EmojiSelectorPanelComponent;
11202
+ exports.GiphyAttachmentResolver = GiphyAttachmentResolver;
11040
11203
  exports.LightboxComponent = LightboxComponent;
11041
11204
  exports.LiveChatMessageComponent = LiveChatMessageComponent;
11042
11205
  exports.LiveCommentComponent = LiveCommentComponent;
11043
11206
  exports.LiveMessageComponent = LiveMessageComponent;
11044
11207
  exports.TimestampComponent = TimestampComponent;
11208
+ exports.TweetAttachmentResolver = TweetAttachmentResolver;
11209
+ exports.UrlAttachmentResolver = UrlAttachmentResolver;
11210
+ exports.UrlAttachmentScraper = UrlAttachmentScraper;
11211
+ exports.YouTubeAttachmentResolver = YouTubeAttachmentResolver;
11045
11212
  exports.lazyConnection = lazyConnection;
11046
11213
 
11047
11214
  Object.defineProperty(exports, '__esModule', { value: true });