@banta/sdk 5.9.0 → 6.0.0

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.
@@ -15,7 +15,7 @@ import createDOMPurify from 'dompurify';
15
15
  import twemoji$1 from 'twemoji';
16
16
  import * as marked from 'marked';
17
17
  import * as i3 from '@angular/cdk/bidi';
18
- import * as i8 from '@angular/material/progress-spinner';
18
+ import * as i9 from '@angular/material/progress-spinner';
19
19
  import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
20
20
  import * as i6 from '@angular/material/button';
21
21
  import { MatButtonModule } from '@angular/material/button';
@@ -33,8 +33,14 @@ import * as i2$3 from '@angular/material/dialog';
33
33
  import { MatDialogModule } from '@angular/material/dialog';
34
34
  import * as i7 from '@angular/material/menu';
35
35
  import { MatMenuModule } from '@angular/material/menu';
36
- import * as i11 from '@angular/material/tooltip';
36
+ import * as i8 from '@angular/material/divider';
37
+ import { MatDividerModule } from '@angular/material/divider';
38
+ import * as i12 from '@angular/material/tooltip';
37
39
  import { MatTooltipModule } from '@angular/material/tooltip';
40
+ import * as i13 from '@angular/material/datepicker';
41
+ import { MatDatepickerModule } from '@angular/material/datepicker';
42
+ import * as i14 from '@angular/material/radio';
43
+ import { MatRadioModule } from '@angular/material/radio';
38
44
  import * as i2$2 from '@angular/router';
39
45
  import * as i3$2 from '@angular/material/snack-bar';
40
46
  import { MatSnackBarModule } from '@angular/material/snack-bar';
@@ -509,7 +515,7 @@ class BantaAttachmentComponent {
509
515
  }
510
516
  }
511
517
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: BantaAttachmentComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
512
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: BantaAttachmentComponent, selector: "banta-attachment", inputs: { attachment: "attachment", loading: "loading", editing: "editing", loadingMessage: "loadingMessage", error: "error", errorMessage: "errorMessage" }, outputs: { removed: "removed", activated: "activated", loaded: "loaded" }, host: { properties: { "class.loading": "this.isLoading" } }, ngImport: i0, 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 && attachment\">\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-attachment\" [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 class=\"summary\">\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 && attachment.url\" 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]=\"attachment.url\"></a>\r\n </blockquote>\r\n </ng-container>\r\n</ng-container>", 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:fit-content}a.card-attachment{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-attachment img{width:250px;aspect-ratio:16/9;object-fit:cover;border-radius:10px}a.card-attachment.has-image h1{font-size:22px}a.card-attachment h1{min-width:0;margin:0 0 .5em;font-size:26px}a.card-attachment cite{min-width:0;opacity:.75;margin-top:1em;display:block;font-size:80%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}a.card-attachment .description{min-width:0;width:100%}a.card-attachment .summary{overflow-x:hidden;text-overflow:ellipsis}.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: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;object-fit:cover}iframe{border:none;width:100%;aspect-ratio:16/9}@media (max-width: 700px){a.card-attachment{flex-direction:column}a.card-attachment img{width:100%}}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i3.Dir, selector: "[dir]", inputs: ["dir"], outputs: ["dirChange"], exportAs: ["dir"] }, { kind: "component", type: i8.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i6.MatMiniFabButton, selector: "button[mat-mini-fab]", exportAs: ["matButton"] }, { kind: "pipe", type: BantaTrustResourceUrlPipe, name: "trustResourceUrl" }] }); }
518
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: BantaAttachmentComponent, selector: "banta-attachment", inputs: { attachment: "attachment", loading: "loading", editing: "editing", loadingMessage: "loadingMessage", error: "error", errorMessage: "errorMessage" }, outputs: { removed: "removed", activated: "activated", loaded: "loaded" }, host: { properties: { "class.loading": "this.isLoading" } }, ngImport: i0, 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 && attachment\">\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-attachment\" [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 class=\"summary\">\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 && attachment.url\" 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]=\"attachment.url\"></a>\r\n </blockquote>\r\n </ng-container>\r\n</ng-container>", 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:fit-content}a.card-attachment{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-attachment img{width:250px;aspect-ratio:16/9;object-fit:cover;border-radius:10px}a.card-attachment.has-image h1{font-size:22px}a.card-attachment h1{min-width:0;margin:0 0 .5em;font-size:26px}a.card-attachment cite{min-width:0;opacity:.75;margin-top:1em;display:block;font-size:80%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}a.card-attachment .description{min-width:0;width:100%}a.card-attachment .summary{overflow-x:hidden;text-overflow:ellipsis}.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: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;object-fit:cover}iframe{border:none;width:100%;aspect-ratio:16/9}@media (max-width: 700px){a.card-attachment{flex-direction:column}a.card-attachment img{width:100%}}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i3.Dir, selector: "[dir]", inputs: ["dir"], outputs: ["dirChange"], exportAs: ["dir"] }, { kind: "component", type: i9.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i6.MatMiniFabButton, selector: "button[mat-mini-fab]", exportAs: ["matButton"] }, { kind: "pipe", type: BantaTrustResourceUrlPipe, name: "trustResourceUrl" }] }); }
513
519
  }
514
520
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: BantaAttachmentComponent, decorators: [{
515
521
  type: Component,
@@ -7435,6 +7441,8 @@ class CommentComponent {
7435
7441
  //#endregion
7436
7442
  //#region Properties
7437
7443
  this.isLoaded = false;
7444
+ this.pinFormVisible = false;
7445
+ this.today = new Date();
7438
7446
  this.showReplyAction = true;
7439
7447
  this.maxLength = 1500;
7440
7448
  this.mine = false;
@@ -7455,6 +7463,8 @@ class CommentComponent {
7455
7463
  this._editEnded = new Subject();
7456
7464
  this._edited = new Subject();
7457
7465
  this._loaded = new Subject();
7466
+ this._pinned = new Subject();
7467
+ this._unpinned = new Subject();
7458
7468
  this.liked = this._liked.asObservable();
7459
7469
  this.unliked = this._unliked.asObservable();
7460
7470
  this.selected = this._selected.asObservable();
@@ -7468,6 +7478,8 @@ class CommentComponent {
7468
7478
  this.avatarSelected = this._avatarSelected.asObservable();
7469
7479
  this.reported = this._reported.asObservable();
7470
7480
  this.loaded = this._loaded.asObservable();
7481
+ this.pinned = this._pinned.asObservable();
7482
+ this.unpinned = this._unpinned.asObservable();
7471
7483
  this.isNew = false;
7472
7484
  this.visible = false;
7473
7485
  }
@@ -7490,6 +7502,17 @@ class CommentComponent {
7490
7502
  get isHighlighted() { return this.message?.transientState?.highlighted ?? false; }
7491
7503
  get replyCount() { return this.message.submessages?.length || this.message.submessageCount || 0; }
7492
7504
  get element() { return this.elementRef.nativeElement; }
7505
+ get isPinned() {
7506
+ return this.message.pinned && (!this.message.pinnedUntil || this.message.pinnedUntil > Date.now());
7507
+ }
7508
+ get pinFormValid() {
7509
+ if (!this.pinMode)
7510
+ return false;
7511
+ if (this.pinMode === 'until') {
7512
+ return !!this.pinUntilDate && !!this.pinUntilTime;
7513
+ }
7514
+ return true;
7515
+ }
7493
7516
  avatarForUser(user) { return `url(${user?.avatarUrl ?? this.genericAvatarUrl})`; }
7494
7517
  //#endregion
7495
7518
  //#region Public Component API
@@ -7518,17 +7541,39 @@ class CommentComponent {
7518
7541
  like() { this._liked.next(); }
7519
7542
  unlike() { this._unliked.next(); }
7520
7543
  share() { this._shared.next(this.message); }
7544
+ unpin() { this._unpinned.next(this.message); }
7521
7545
  select() { this._selected.next(); }
7522
7546
  selectUser() { this._userSelected.next(); }
7523
7547
  startEdit() { this._editStarted.next(); this.editedMessage = this.message.message; }
7524
7548
  selectUsername(user) { this._usernameSelected.next(user); this.selectUser(); }
7525
7549
  selectAvatar(user) { this._avatarSelected.next(user); this.selectUser(); }
7550
+ showPinForm() {
7551
+ this.pinFormVisible = true;
7552
+ this.pinUntilTime = '08:00';
7553
+ }
7554
+ submitPin() {
7555
+ let pinUntil;
7556
+ if (this.pinMode === 'until') {
7557
+ let date = new Date(this.pinUntilDate);
7558
+ let [hour, minute] = this.pinUntilTime.split(':');
7559
+ date.setHours(Number(hour));
7560
+ date.setMinutes(Number(minute));
7561
+ pinUntil = date.getTime();
7562
+ }
7563
+ this.pinFormVisible = false;
7564
+ this._pinned.next({
7565
+ message: this.message,
7566
+ options: {
7567
+ until: pinUntil
7568
+ }
7569
+ });
7570
+ }
7526
7571
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: CommentComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
7527
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: CommentComponent, selector: "banta-comment", inputs: { message: "message", customMenuItems: "customMenuItems", showReplyAction: "showReplyAction", maxLength: "maxLength", permissions: "permissions", mine: "mine", editing: "editing", genericAvatarUrl: "genericAvatarUrl", readonly: "readonly" }, outputs: { liked: "liked", unliked: "unliked", selected: "selected", edited: "edited", deleted: "deleted", editStarted: "editStarted", editEnded: "editEnded", shared: "shared", userSelected: "userSelected", usernameSelected: "usernameSelected", avatarSelected: "avatarSelected", reported: "reported", loaded: "loaded" }, host: { properties: { "attr.data-comment-id": "this.commentId", "class.new": "this.isNew", "class.highlighted": "this.isHighlighted", "class.visible": "this.visible" } }, ngImport: i0, 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 || readonly\" 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 || readonly\" mat-menu-item (click)=\"delete()\">\r\n <mat-icon>delete</mat-icon>\r\n Delete\r\n </button>\r\n\r\n <button *ngFor=\"let menuItem of customMenuItems\" mat-menu-item (click)=\"menuItem.action(message)\">\r\n <mat-icon>{{menuItem.icon}}</mat-icon>\r\n {{menuItem.label}}\r\n </button>\r\n\r\n</mat-menu>\r\n\r\n<div class=\"banta-message-content-container\">\r\n <div class=\"banta-user\">\r\n <div class=\"banta-user-1\">\r\n <a\r\n href=\"javascript:;\"\r\n class=\"banta-avatar\"\r\n (click)=\"selectAvatar(message.user)\"\r\n [style.background-image]=\"avatarForUser(message.user)\"></a>\r\n <div class=\"banta-user-identity\">\r\n <a href=\"javascript:;\" class=\"banta-display-name\" (click)=\"selectUser()\">{{message.user.displayName}}</a>\r\n <a href=\"javascript:;\" class=\"banta-username\" (click)=\"selectUsername(message.user)\">&#64;{{message.user.username}}</a>\r\n </div>\r\n </div>\r\n <div class=\"banta-user-2\">\r\n <span class=\"banta-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=\"banta-content\" *ngIf=\"!editing\">\r\n <span class=\"banta-message-content\" [innerHTML]=\"message.message | mentionLinker: message.mentionLinks | bantaMarkdownToHtml\"></span>\r\n <banta-attachments \r\n [attachments]=\"message.attachments\"\r\n (loaded)=\"markAttachmentsLoaded()\"\r\n ></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=\"banta-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\" [maxlength]=\"maxLength\"></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=\"banta-actions\">\r\n <div class=\"spacer\"></div>\r\n <div class=\"banta-counted-action\" *ngIf=\"showReplyAction\">\r\n <button mat-button [matTooltip]=\"replyCount > 0 ? 'Replies' : 'Reply'\" matTooltipPosition=\"below\" (click)=\"select()\">\r\n <mat-icon>comment</mat-icon>\r\n <span class=\"banta-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=\"banta-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]=\"readonly\"\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>thumb_up</mat-icon>\r\n <span class=\"banta-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>more_vert</mat-icon>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: ["@keyframes comment-appear{0%{transform:translate(6em)}to{transform:translate(0)}}:host{display:flex;flex-direction:column;position:relative;padding:.5em;visibility:hidden}:host.new{visibility:visible;animation-name:comment-appear;animation-duration:.25s;animation-fill-mode:both}:host.highlighted{background:#00223a;outline:2px solid #003277}:host.visible{visibility:visible}:host:hover{background:#eee}:host .banta-message-content-container .banta-content{margin-left:60px;margin-right:.5em}:host .banta-message-content-container .attachments-row{margin-top:15px;display:flex;gap:10px}:host .banta-message-content-container .attachments-row img{border-radius:10px;width:300px;max-width:100%;max-height:20em;object-fit:cover}:host.abbreviated .banta-message-content-container .banta-content{text-overflow:ellipsis;overflow-y:hidden}:host .banta-actions{display:flex;padding-right:10px;margin-left:60px;align-items:center}:host .banta-actions button{color:#666;flex-shrink:0}banta-timestamp{color:#666;font-size:10pt;flex-shrink:0;margin-left:1em;text-align:right}.banta-user{position:relative;margin:1em 0 0;display:flex;align-items:center;flex-wrap:wrap}.banta-user .banta-user-1,.banta-user .banta-user-2{display:flex;flex-wrap:nowrap;align-items:center;min-width:0}.banta-user .banta-user-2{margin:1em 0}.banta-user .banta-user-identity{display:flex;flex-direction:column;min-width:0}.banta-user .banta-display-name,.banta-user .banta-username{z-index:1;position:relative;padding:0 0 0 1em;font-size:10pt;color:#000;margin:0 auto 0 0;display:block;width:fit-content;max-width:100%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;flex-shrink:1;flex-grow:0;min-width:0}.banta-user .banta-display-name.banta-username.banta-username.banta-username,.banta-user .banta-username.banta-username.banta-username.banta-username{color:#666}.banta-avatar{height:48px;width:48px;background-position:center;background-size:cover;background-color:#333;border-radius:100%;flex-shrink:0;flex-grow:0}.banta-counted-action{display:flex;align-items:center}.banta-counted-action.active button,.banta-counted-action.active .banta-count-indicator{color:#00a5ff}.banta-counted-action button .banta-count-indicator{margin-left:.5em}.banta-count-indicator{font-size:9pt;padding:0 0 0 3px;color:#666}:host-context(.mat-dark-theme) .banta-count-indicator{border-color:#333}:host-context(.mat-dark-theme):hover{background:#060606}:host-context(.mat-dark-theme) .banta-user .banta-display-name,:host-context(.mat-dark-theme) .banta-user .banta-username{color:#fff}.banta-user-tag{text-transform:uppercase;font-size:12px;border:1px solid #b27373;background:#7a412b;color:#fff;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}ul.message-facts li{margin-top:.5em}ul.message-facts li:first-child{border-left:1px solid transparent;margin-left:0;padding-left:0}@media (max-width: 400px){.banta-avatar{height:32px;width:32px}:host .banta-actions{margin-left:0;margin-top:.5em}:host .banta-message-content-container .banta-content{margin-left:44px;margin-right:.5em}}:host-context(.banta-mobile) .banta-avatar{height:32px;width:32px}:host-context(.banta-mobile) :host .banta-actions{margin-left:0;margin-top:.5em}:host-context(.banta-mobile) :host .banta-message-content-container .banta-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;object-fit:cover;border-radius:10px}.card-attachment a h1{margin:0;font-size:30px}::ng-deep .banta-message-content img.emoji{height:1.5em;vertical-align:middle}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$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: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i3$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6$1.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"] }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: TimestampComponent, selector: "banta-timestamp", inputs: ["value"] }, { kind: "component", type: BantaAttachmentsComponent, selector: "banta-attachments", inputs: ["attachments", "editing"], outputs: ["remove", "loaded"] }, { kind: "directive", type: i11.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: BantaMarkdownToHtmlPipe, name: "bantaMarkdownToHtml" }, { kind: "pipe", type: BantaMentionLinkerPipe, name: "mentionLinker" }] }); }
7572
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.9", type: CommentComponent, selector: "banta-comment", inputs: { message: "message", customMenuItems: "customMenuItems", showReplyAction: "showReplyAction", maxLength: "maxLength", permissions: "permissions", mine: "mine", editing: "editing", genericAvatarUrl: "genericAvatarUrl", readonly: "readonly" }, outputs: { liked: "liked", unliked: "unliked", selected: "selected", edited: "edited", deleted: "deleted", editStarted: "editStarted", editEnded: "editEnded", shared: "shared", userSelected: "userSelected", usernameSelected: "usernameSelected", avatarSelected: "avatarSelected", reported: "reported", loaded: "loaded", pinned: "pinned", unpinned: "unpinned" }, host: { properties: { "attr.data-comment-id": "this.commentId", "class.new": "this.isNew", "class.highlighted": "this.isHighlighted", "class.visible": "this.visible", "class.pinned": "this.isPinned" } }, ngImport: i0, template: "\r\n<mat-menu #pointItemMenu=\"matMenu\">\r\n @if (permissions.canPin) {\r\n @if (isPinned) {\r\n <button mat-menu-item (click)=\"unpin()\">\r\n <mat-icon>push_pin</mat-icon>\r\n Unpin\r\n </button>\r\n } @else {\r\n <button mat-menu-item (click)=\"showPinForm()\">\r\n <mat-icon>push_pin</mat-icon>\r\n Pin\r\n </button>\r\n }\r\n <mat-divider />\r\n }\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 || readonly\" 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 || readonly\" mat-menu-item (click)=\"delete()\">\r\n <mat-icon>delete</mat-icon>\r\n Delete\r\n </button>\r\n\r\n <button *ngFor=\"let menuItem of customMenuItems\" mat-menu-item (click)=\"menuItem.action(message)\">\r\n <mat-icon>{{menuItem.icon}}</mat-icon>\r\n {{menuItem.label}}\r\n </button>\r\n\r\n</mat-menu>\r\n\r\n<div class=\"banta-message-content-container\">\r\n <div class=\"banta-user\">\r\n <div class=\"banta-user-1\">\r\n <a\r\n href=\"javascript:;\"\r\n class=\"banta-avatar\"\r\n (click)=\"selectAvatar(message.user)\"\r\n [style.background-image]=\"avatarForUser(message.user)\"></a>\r\n <div class=\"banta-user-identity\">\r\n <a href=\"javascript:;\" class=\"banta-display-name\" (click)=\"selectUser()\">{{message.user.displayName}}</a>\r\n <a href=\"javascript:;\" class=\"banta-username\" (click)=\"selectUsername(message.user)\">&#64;{{message.user.username}}</a>\r\n </div>\r\n </div>\r\n <div class=\"banta-user-2\">\r\n <span class=\"banta-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 class=\"spacer\"></div>\r\n </div>\r\n <div class=\"banta-content\" *ngIf=\"!editing\">\r\n <span class=\"banta-message-content\" [innerHTML]=\"message.message | mentionLinker: message.mentionLinks | bantaMarkdownToHtml\"></span>\r\n <banta-attachments \r\n [attachments]=\"message.attachments\"\r\n (loaded)=\"markAttachmentsLoaded()\"\r\n ></banta-attachments>\r\n <ul class=\"message-facts\">\r\n <li *ngIf=\"message.edits?.length > 0\">(Edited)</li>\r\n </ul>\r\n\r\n @if (pinFormVisible) {\r\n <div class=\"banta-pin-form\">\r\n <div class=\"banta-pin-form-header\">\r\n <div class=\"banta-pin-form-header-title\">\r\n Pin message?\r\n </div>\r\n <div class=\"spacer\"></div>\r\n <!-- <div class=\"banta-pin-form-auth-explanation\">\r\n <mat-icon>lock</mat-icon> Only available to authorized users.\r\n </div> -->\r\n <button mat-icon-button (click)=\"pinFormVisible = false\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <p>\r\n Pinning this message will cause it to appear at the top of the discussion for all users.\r\n </p>\r\n\r\n\r\n <mat-radio-group [(ngModel)]=\"pinMode\">\r\n <div>\r\n <mat-radio-button value=\"forever\">Pin indefinitely</mat-radio-button>\r\n </div>\r\n <div>\r\n <mat-radio-button value=\"until\">Pin until a specific time:</mat-radio-button>\r\n </div>\r\n <div class=\"banta-pin-form-until\" [class.banta-pin-form-until-disabled]=\"pinMode !== 'until'\">\r\n <mat-form-field appearance=\"outline\" floatLabel=\"always\">\r\n <mat-label>Date</mat-label>\r\n <input \r\n matInput \r\n [min]=\"today\"\r\n [matDatepicker]=\"datepicker\" \r\n [(ngModel)]=\"pinUntilDate\"\r\n [disabled]=\"pinMode !== 'until'\" \r\n />\r\n <mat-datepicker #datepicker/>\r\n <mat-datepicker-toggle [for]=\"datepicker\" matSuffix/>\r\n </mat-form-field>\r\n \r\n <mat-form-field appearance=\"outline\" floatLabel=\"always\">\r\n <mat-label>Time</mat-label>\r\n <input matInput\r\n type=\"time\"\r\n [(ngModel)]=\"pinUntilTime\"\r\n [ngModelOptions]=\"{updateOn: 'blur'}\"\r\n [disabled]=\"pinMode !== 'until'\" \r\n />\r\n <mat-timepicker #timepicker/>\r\n <mat-timepicker-toggle [for]=\"timepicker\" matSuffix/>\r\n </mat-form-field>\r\n </div>\r\n </mat-radio-group>\r\n\r\n <div class=\"banta-pin-form-actions\">\r\n <button mat-button (click)=\"pinFormVisible = false\">\r\n Cancel\r\n </button>\r\n <button mat-raised-button color=\"primary\" (click)=\"submitPin()\" [disabled]=\"!pinFormValid\">\r\n Pin\r\n </button>\r\n </div>\r\n\r\n </div>\r\n }\r\n </div>\r\n <div class=\"banta-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\" [maxlength]=\"maxLength\"></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=\"banta-actions\">\r\n @if (isPinned) {\r\n <div class=\"pin-indicator\">\r\n <mat-icon>push_pin</mat-icon> Pinned\r\n @if (message.pinnedUntil) {\r\n until <time [datetime]=\"message.pinnedUntil | date: 'full'\">{{ message.pinnedUntil | date: 'short' }}</time>\r\n }\r\n </div>\r\n }\r\n <div class=\"spacer\"></div>\r\n <div class=\"banta-counted-action\" *ngIf=\"showReplyAction\">\r\n <button mat-button [matTooltip]=\"replyCount > 0 ? 'Replies' : 'Reply'\" matTooltipPosition=\"below\" (click)=\"select()\">\r\n <mat-icon>comment</mat-icon>\r\n <span class=\"banta-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=\"banta-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]=\"readonly\"\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>thumb_up</mat-icon>\r\n <span class=\"banta-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>more_vert</mat-icon>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: ["@keyframes comment-appear{0%{transform:translate(6em)}to{transform:translate(0)}}:host{display:flex;flex-direction:column;position:relative;padding:.5em;visibility:hidden}:host.new{visibility:visible;animation-name:comment-appear;animation-duration:.25s;animation-fill-mode:both}:host.pinned{background-color:#1c1c1c;border:1px solid #057eb1;border-radius:5px}:host.highlighted{background:#00223a;outline:2px solid #003277}:host.visible{visibility:visible}:host:hover{background:#eee}:host .banta-message-content-container .banta-content{margin-left:60px;margin-right:.5em}:host .banta-message-content-container .attachments-row{margin-top:15px;display:flex;gap:10px}:host .banta-message-content-container .attachments-row img{border-radius:10px;width:300px;max-width:100%;max-height:20em;object-fit:cover}:host.abbreviated .banta-message-content-container .banta-content{text-overflow:ellipsis;overflow-y:hidden}:host .banta-actions{display:flex;padding-right:10px;margin-left:60px;align-items:center}:host .banta-actions button{color:#666;flex-shrink:0}banta-timestamp{color:#666;font-size:10pt;flex-shrink:0;margin-left:1em;text-align:right}.banta-user{position:relative;margin:1em 0 0;display:flex;align-items:center;flex-wrap:wrap}.banta-user .banta-user-1,.banta-user .banta-user-2{display:flex;flex-wrap:nowrap;align-items:center;min-width:0}.banta-user .banta-user-2{margin:1em 0}.banta-user .banta-user-identity{display:flex;flex-direction:column;min-width:0}.banta-user .banta-display-name,.banta-user .banta-username{z-index:1;position:relative;padding:0 0 0 1em;font-size:10pt;color:#000;margin:0 auto 0 0;display:block;width:fit-content;max-width:100%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;flex-shrink:1;flex-grow:0;min-width:0}.banta-user .banta-display-name.banta-username.banta-username.banta-username,.banta-user .banta-username.banta-username.banta-username.banta-username{color:#666}.banta-avatar{height:48px;width:48px;background-position:center;background-size:cover;background-color:#333;border-radius:100%;flex-shrink:0;flex-grow:0}.banta-counted-action{display:flex;align-items:center}.banta-counted-action.active button,.banta-counted-action.active .banta-count-indicator{color:#00a5ff}.banta-counted-action button .banta-count-indicator{margin-left:.5em}.banta-count-indicator{font-size:9pt;padding:0 0 0 3px;color:#666}:host-context(.mat-dark-theme) .banta-count-indicator{border-color:#333}:host-context(.mat-dark-theme):hover{background:#060606}:host-context(.mat-dark-theme) .banta-user .banta-display-name,:host-context(.mat-dark-theme) .banta-user .banta-username{color:#fff}.banta-user-tag{text-transform:uppercase;font-size:12px;border:1px solid #b27373;background:#7a412b;color:#fff;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;display:flex;align-items:center}ul.message-facts li{list-style-type:none;border-left:1px solid #666;font-size:10pt;padding-left:.5em;margin-left:.5em;display:flex;align-items:center}ul.message-facts li:first-child{border-left:1px solid transparent;margin-left:0;padding-left:0}@media (max-width: 400px){.banta-avatar{height:32px;width:32px}:host .banta-actions{margin-left:0;margin-top:.5em}:host .banta-message-content-container .banta-content{margin-left:44px;margin-right:.5em}}:host-context(.banta-mobile) .banta-avatar{height:32px;width:32px}:host-context(.banta-mobile) :host .banta-actions{margin-left:0;margin-top:.5em}:host-context(.banta-mobile) :host .banta-message-content-container .banta-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;object-fit:cover;border-radius:10px}.card-attachment a h1{margin:0;font-size:30px}::ng-deep .banta-message-content img.emoji{height:1.5em;vertical-align:middle}.banta-pin-form{border:1px solid #333;border-radius:4px;padding:1em}.banta-pin-form .banta-pin-form-header{display:flex;flex-direction:row;align-items:center}.banta-pin-form .banta-pin-form-header .banta-pin-form-header-title{font-size:150%;margin-bottom:.5em}.banta-pin-form .banta-pin-form-auth-explanation{opacity:.25;font-size:80%;margin-bottom:.5em;display:flex;align-items:center;gap:.5em}.banta-pin-form .banta-pin-form-until{display:flex;align-items:baseline;gap:1em;margin:1em 0 1em 2em}.banta-pin-form .banta-pin-form-until.banta-pin-form-until-disabled{pointer-events:none;opacity:.5}.banta-pin-form .banta-pin-form-actions{display:flex;align-items:baseline;justify-content:flex-end;gap:1em}.pin-indicator{font-size:80%;display:flex;align-items:center;margin-right:2em;opacity:.5;gap:.5em}.pin-indicator mat-icon{width:16px;height:16px;font-size:16px}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$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: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i3$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i5.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i6$1.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"] }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatDivider, selector: "mat-divider", inputs: ["vertical", "inset"] }, { kind: "component", type: i9.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: TimestampComponent, selector: "banta-timestamp", inputs: ["value"] }, { kind: "component", type: BantaAttachmentsComponent, selector: "banta-attachments", inputs: ["attachments", "editing"], outputs: ["remove", "loaded"] }, { kind: "directive", type: i12.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: i13.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i13.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i13.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "directive", type: i14.MatRadioGroup, selector: "mat-radio-group", inputs: ["color", "name", "labelPosition", "value", "selected", "disabled", "required"], outputs: ["change"], exportAs: ["matRadioGroup"] }, { kind: "component", type: i14.MatRadioButton, selector: "mat-radio-button", inputs: ["id", "name", "aria-label", "aria-labelledby", "aria-describedby", "disableRipple", "tabIndex", "checked", "value", "labelPosition", "disabled", "required", "color"], outputs: ["change"], exportAs: ["matRadioButton"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }, { kind: "pipe", type: BantaMarkdownToHtmlPipe, name: "bantaMarkdownToHtml" }, { kind: "pipe", type: BantaMentionLinkerPipe, name: "mentionLinker" }] }); }
7528
7573
  }
7529
7574
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: CommentComponent, decorators: [{
7530
7575
  type: Component,
7531
- args: [{ selector: 'banta-comment', 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 || readonly\" 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 || readonly\" mat-menu-item (click)=\"delete()\">\r\n <mat-icon>delete</mat-icon>\r\n Delete\r\n </button>\r\n\r\n <button *ngFor=\"let menuItem of customMenuItems\" mat-menu-item (click)=\"menuItem.action(message)\">\r\n <mat-icon>{{menuItem.icon}}</mat-icon>\r\n {{menuItem.label}}\r\n </button>\r\n\r\n</mat-menu>\r\n\r\n<div class=\"banta-message-content-container\">\r\n <div class=\"banta-user\">\r\n <div class=\"banta-user-1\">\r\n <a\r\n href=\"javascript:;\"\r\n class=\"banta-avatar\"\r\n (click)=\"selectAvatar(message.user)\"\r\n [style.background-image]=\"avatarForUser(message.user)\"></a>\r\n <div class=\"banta-user-identity\">\r\n <a href=\"javascript:;\" class=\"banta-display-name\" (click)=\"selectUser()\">{{message.user.displayName}}</a>\r\n <a href=\"javascript:;\" class=\"banta-username\" (click)=\"selectUsername(message.user)\">&#64;{{message.user.username}}</a>\r\n </div>\r\n </div>\r\n <div class=\"banta-user-2\">\r\n <span class=\"banta-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=\"banta-content\" *ngIf=\"!editing\">\r\n <span class=\"banta-message-content\" [innerHTML]=\"message.message | mentionLinker: message.mentionLinks | bantaMarkdownToHtml\"></span>\r\n <banta-attachments \r\n [attachments]=\"message.attachments\"\r\n (loaded)=\"markAttachmentsLoaded()\"\r\n ></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=\"banta-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\" [maxlength]=\"maxLength\"></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=\"banta-actions\">\r\n <div class=\"spacer\"></div>\r\n <div class=\"banta-counted-action\" *ngIf=\"showReplyAction\">\r\n <button mat-button [matTooltip]=\"replyCount > 0 ? 'Replies' : 'Reply'\" matTooltipPosition=\"below\" (click)=\"select()\">\r\n <mat-icon>comment</mat-icon>\r\n <span class=\"banta-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=\"banta-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]=\"readonly\"\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>thumb_up</mat-icon>\r\n <span class=\"banta-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>more_vert</mat-icon>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: ["@keyframes comment-appear{0%{transform:translate(6em)}to{transform:translate(0)}}:host{display:flex;flex-direction:column;position:relative;padding:.5em;visibility:hidden}:host.new{visibility:visible;animation-name:comment-appear;animation-duration:.25s;animation-fill-mode:both}:host.highlighted{background:#00223a;outline:2px solid #003277}:host.visible{visibility:visible}:host:hover{background:#eee}:host .banta-message-content-container .banta-content{margin-left:60px;margin-right:.5em}:host .banta-message-content-container .attachments-row{margin-top:15px;display:flex;gap:10px}:host .banta-message-content-container .attachments-row img{border-radius:10px;width:300px;max-width:100%;max-height:20em;object-fit:cover}:host.abbreviated .banta-message-content-container .banta-content{text-overflow:ellipsis;overflow-y:hidden}:host .banta-actions{display:flex;padding-right:10px;margin-left:60px;align-items:center}:host .banta-actions button{color:#666;flex-shrink:0}banta-timestamp{color:#666;font-size:10pt;flex-shrink:0;margin-left:1em;text-align:right}.banta-user{position:relative;margin:1em 0 0;display:flex;align-items:center;flex-wrap:wrap}.banta-user .banta-user-1,.banta-user .banta-user-2{display:flex;flex-wrap:nowrap;align-items:center;min-width:0}.banta-user .banta-user-2{margin:1em 0}.banta-user .banta-user-identity{display:flex;flex-direction:column;min-width:0}.banta-user .banta-display-name,.banta-user .banta-username{z-index:1;position:relative;padding:0 0 0 1em;font-size:10pt;color:#000;margin:0 auto 0 0;display:block;width:fit-content;max-width:100%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;flex-shrink:1;flex-grow:0;min-width:0}.banta-user .banta-display-name.banta-username.banta-username.banta-username,.banta-user .banta-username.banta-username.banta-username.banta-username{color:#666}.banta-avatar{height:48px;width:48px;background-position:center;background-size:cover;background-color:#333;border-radius:100%;flex-shrink:0;flex-grow:0}.banta-counted-action{display:flex;align-items:center}.banta-counted-action.active button,.banta-counted-action.active .banta-count-indicator{color:#00a5ff}.banta-counted-action button .banta-count-indicator{margin-left:.5em}.banta-count-indicator{font-size:9pt;padding:0 0 0 3px;color:#666}:host-context(.mat-dark-theme) .banta-count-indicator{border-color:#333}:host-context(.mat-dark-theme):hover{background:#060606}:host-context(.mat-dark-theme) .banta-user .banta-display-name,:host-context(.mat-dark-theme) .banta-user .banta-username{color:#fff}.banta-user-tag{text-transform:uppercase;font-size:12px;border:1px solid #b27373;background:#7a412b;color:#fff;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}ul.message-facts li{margin-top:.5em}ul.message-facts li:first-child{border-left:1px solid transparent;margin-left:0;padding-left:0}@media (max-width: 400px){.banta-avatar{height:32px;width:32px}:host .banta-actions{margin-left:0;margin-top:.5em}:host .banta-message-content-container .banta-content{margin-left:44px;margin-right:.5em}}:host-context(.banta-mobile) .banta-avatar{height:32px;width:32px}:host-context(.banta-mobile) :host .banta-actions{margin-left:0;margin-top:.5em}:host-context(.banta-mobile) :host .banta-message-content-container .banta-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;object-fit:cover;border-radius:10px}.card-attachment a h1{margin:0;font-size:30px}::ng-deep .banta-message-content img.emoji{height:1.5em;vertical-align:middle}\n"] }]
7576
+ args: [{ selector: 'banta-comment', template: "\r\n<mat-menu #pointItemMenu=\"matMenu\">\r\n @if (permissions.canPin) {\r\n @if (isPinned) {\r\n <button mat-menu-item (click)=\"unpin()\">\r\n <mat-icon>push_pin</mat-icon>\r\n Unpin\r\n </button>\r\n } @else {\r\n <button mat-menu-item (click)=\"showPinForm()\">\r\n <mat-icon>push_pin</mat-icon>\r\n Pin\r\n </button>\r\n }\r\n <mat-divider />\r\n }\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 || readonly\" 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 || readonly\" mat-menu-item (click)=\"delete()\">\r\n <mat-icon>delete</mat-icon>\r\n Delete\r\n </button>\r\n\r\n <button *ngFor=\"let menuItem of customMenuItems\" mat-menu-item (click)=\"menuItem.action(message)\">\r\n <mat-icon>{{menuItem.icon}}</mat-icon>\r\n {{menuItem.label}}\r\n </button>\r\n\r\n</mat-menu>\r\n\r\n<div class=\"banta-message-content-container\">\r\n <div class=\"banta-user\">\r\n <div class=\"banta-user-1\">\r\n <a\r\n href=\"javascript:;\"\r\n class=\"banta-avatar\"\r\n (click)=\"selectAvatar(message.user)\"\r\n [style.background-image]=\"avatarForUser(message.user)\"></a>\r\n <div class=\"banta-user-identity\">\r\n <a href=\"javascript:;\" class=\"banta-display-name\" (click)=\"selectUser()\">{{message.user.displayName}}</a>\r\n <a href=\"javascript:;\" class=\"banta-username\" (click)=\"selectUsername(message.user)\">&#64;{{message.user.username}}</a>\r\n </div>\r\n </div>\r\n <div class=\"banta-user-2\">\r\n <span class=\"banta-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 class=\"spacer\"></div>\r\n </div>\r\n <div class=\"banta-content\" *ngIf=\"!editing\">\r\n <span class=\"banta-message-content\" [innerHTML]=\"message.message | mentionLinker: message.mentionLinks | bantaMarkdownToHtml\"></span>\r\n <banta-attachments \r\n [attachments]=\"message.attachments\"\r\n (loaded)=\"markAttachmentsLoaded()\"\r\n ></banta-attachments>\r\n <ul class=\"message-facts\">\r\n <li *ngIf=\"message.edits?.length > 0\">(Edited)</li>\r\n </ul>\r\n\r\n @if (pinFormVisible) {\r\n <div class=\"banta-pin-form\">\r\n <div class=\"banta-pin-form-header\">\r\n <div class=\"banta-pin-form-header-title\">\r\n Pin message?\r\n </div>\r\n <div class=\"spacer\"></div>\r\n <!-- <div class=\"banta-pin-form-auth-explanation\">\r\n <mat-icon>lock</mat-icon> Only available to authorized users.\r\n </div> -->\r\n <button mat-icon-button (click)=\"pinFormVisible = false\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <p>\r\n Pinning this message will cause it to appear at the top of the discussion for all users.\r\n </p>\r\n\r\n\r\n <mat-radio-group [(ngModel)]=\"pinMode\">\r\n <div>\r\n <mat-radio-button value=\"forever\">Pin indefinitely</mat-radio-button>\r\n </div>\r\n <div>\r\n <mat-radio-button value=\"until\">Pin until a specific time:</mat-radio-button>\r\n </div>\r\n <div class=\"banta-pin-form-until\" [class.banta-pin-form-until-disabled]=\"pinMode !== 'until'\">\r\n <mat-form-field appearance=\"outline\" floatLabel=\"always\">\r\n <mat-label>Date</mat-label>\r\n <input \r\n matInput \r\n [min]=\"today\"\r\n [matDatepicker]=\"datepicker\" \r\n [(ngModel)]=\"pinUntilDate\"\r\n [disabled]=\"pinMode !== 'until'\" \r\n />\r\n <mat-datepicker #datepicker/>\r\n <mat-datepicker-toggle [for]=\"datepicker\" matSuffix/>\r\n </mat-form-field>\r\n \r\n <mat-form-field appearance=\"outline\" floatLabel=\"always\">\r\n <mat-label>Time</mat-label>\r\n <input matInput\r\n type=\"time\"\r\n [(ngModel)]=\"pinUntilTime\"\r\n [ngModelOptions]=\"{updateOn: 'blur'}\"\r\n [disabled]=\"pinMode !== 'until'\" \r\n />\r\n <mat-timepicker #timepicker/>\r\n <mat-timepicker-toggle [for]=\"timepicker\" matSuffix/>\r\n </mat-form-field>\r\n </div>\r\n </mat-radio-group>\r\n\r\n <div class=\"banta-pin-form-actions\">\r\n <button mat-button (click)=\"pinFormVisible = false\">\r\n Cancel\r\n </button>\r\n <button mat-raised-button color=\"primary\" (click)=\"submitPin()\" [disabled]=\"!pinFormValid\">\r\n Pin\r\n </button>\r\n </div>\r\n\r\n </div>\r\n }\r\n </div>\r\n <div class=\"banta-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\" [maxlength]=\"maxLength\"></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=\"banta-actions\">\r\n @if (isPinned) {\r\n <div class=\"pin-indicator\">\r\n <mat-icon>push_pin</mat-icon> Pinned\r\n @if (message.pinnedUntil) {\r\n until <time [datetime]=\"message.pinnedUntil | date: 'full'\">{{ message.pinnedUntil | date: 'short' }}</time>\r\n }\r\n </div>\r\n }\r\n <div class=\"spacer\"></div>\r\n <div class=\"banta-counted-action\" *ngIf=\"showReplyAction\">\r\n <button mat-button [matTooltip]=\"replyCount > 0 ? 'Replies' : 'Reply'\" matTooltipPosition=\"below\" (click)=\"select()\">\r\n <mat-icon>comment</mat-icon>\r\n <span class=\"banta-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=\"banta-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]=\"readonly\"\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>thumb_up</mat-icon>\r\n <span class=\"banta-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>more_vert</mat-icon>\r\n </button>\r\n </div>\r\n</div>\r\n", styles: ["@keyframes comment-appear{0%{transform:translate(6em)}to{transform:translate(0)}}:host{display:flex;flex-direction:column;position:relative;padding:.5em;visibility:hidden}:host.new{visibility:visible;animation-name:comment-appear;animation-duration:.25s;animation-fill-mode:both}:host.pinned{background-color:#1c1c1c;border:1px solid #057eb1;border-radius:5px}:host.highlighted{background:#00223a;outline:2px solid #003277}:host.visible{visibility:visible}:host:hover{background:#eee}:host .banta-message-content-container .banta-content{margin-left:60px;margin-right:.5em}:host .banta-message-content-container .attachments-row{margin-top:15px;display:flex;gap:10px}:host .banta-message-content-container .attachments-row img{border-radius:10px;width:300px;max-width:100%;max-height:20em;object-fit:cover}:host.abbreviated .banta-message-content-container .banta-content{text-overflow:ellipsis;overflow-y:hidden}:host .banta-actions{display:flex;padding-right:10px;margin-left:60px;align-items:center}:host .banta-actions button{color:#666;flex-shrink:0}banta-timestamp{color:#666;font-size:10pt;flex-shrink:0;margin-left:1em;text-align:right}.banta-user{position:relative;margin:1em 0 0;display:flex;align-items:center;flex-wrap:wrap}.banta-user .banta-user-1,.banta-user .banta-user-2{display:flex;flex-wrap:nowrap;align-items:center;min-width:0}.banta-user .banta-user-2{margin:1em 0}.banta-user .banta-user-identity{display:flex;flex-direction:column;min-width:0}.banta-user .banta-display-name,.banta-user .banta-username{z-index:1;position:relative;padding:0 0 0 1em;font-size:10pt;color:#000;margin:0 auto 0 0;display:block;width:fit-content;max-width:100%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;flex-shrink:1;flex-grow:0;min-width:0}.banta-user .banta-display-name.banta-username.banta-username.banta-username,.banta-user .banta-username.banta-username.banta-username.banta-username{color:#666}.banta-avatar{height:48px;width:48px;background-position:center;background-size:cover;background-color:#333;border-radius:100%;flex-shrink:0;flex-grow:0}.banta-counted-action{display:flex;align-items:center}.banta-counted-action.active button,.banta-counted-action.active .banta-count-indicator{color:#00a5ff}.banta-counted-action button .banta-count-indicator{margin-left:.5em}.banta-count-indicator{font-size:9pt;padding:0 0 0 3px;color:#666}:host-context(.mat-dark-theme) .banta-count-indicator{border-color:#333}:host-context(.mat-dark-theme):hover{background:#060606}:host-context(.mat-dark-theme) .banta-user .banta-display-name,:host-context(.mat-dark-theme) .banta-user .banta-username{color:#fff}.banta-user-tag{text-transform:uppercase;font-size:12px;border:1px solid #b27373;background:#7a412b;color:#fff;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;display:flex;align-items:center}ul.message-facts li{list-style-type:none;border-left:1px solid #666;font-size:10pt;padding-left:.5em;margin-left:.5em;display:flex;align-items:center}ul.message-facts li:first-child{border-left:1px solid transparent;margin-left:0;padding-left:0}@media (max-width: 400px){.banta-avatar{height:32px;width:32px}:host .banta-actions{margin-left:0;margin-top:.5em}:host .banta-message-content-container .banta-content{margin-left:44px;margin-right:.5em}}:host-context(.banta-mobile) .banta-avatar{height:32px;width:32px}:host-context(.banta-mobile) :host .banta-actions{margin-left:0;margin-top:.5em}:host-context(.banta-mobile) :host .banta-message-content-container .banta-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;object-fit:cover;border-radius:10px}.card-attachment a h1{margin:0;font-size:30px}::ng-deep .banta-message-content img.emoji{height:1.5em;vertical-align:middle}.banta-pin-form{border:1px solid #333;border-radius:4px;padding:1em}.banta-pin-form .banta-pin-form-header{display:flex;flex-direction:row;align-items:center}.banta-pin-form .banta-pin-form-header .banta-pin-form-header-title{font-size:150%;margin-bottom:.5em}.banta-pin-form .banta-pin-form-auth-explanation{opacity:.25;font-size:80%;margin-bottom:.5em;display:flex;align-items:center;gap:.5em}.banta-pin-form .banta-pin-form-until{display:flex;align-items:baseline;gap:1em;margin:1em 0 1em 2em}.banta-pin-form .banta-pin-form-until.banta-pin-form-until-disabled{pointer-events:none;opacity:.5}.banta-pin-form .banta-pin-form-actions{display:flex;align-items:baseline;justify-content:flex-end;gap:1em}.pin-indicator{font-size:80%;display:flex;align-items:center;margin-right:2em;opacity:.5;gap:.5em}.pin-indicator mat-icon{width:16px;height:16px;font-size:16px}\n"] }]
7532
7577
  }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { message: [{
7533
7578
  type: Input
7534
7579
  }], customMenuItems: [{
@@ -7573,6 +7618,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImpor
7573
7618
  type: Output
7574
7619
  }], loaded: [{
7575
7620
  type: Output
7621
+ }], pinned: [{
7622
+ type: Output
7623
+ }], unpinned: [{
7624
+ type: Output
7576
7625
  }], commentId: [{
7577
7626
  type: HostBinding,
7578
7627
  args: ['attr.data-comment-id']
@@ -7585,6 +7634,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImpor
7585
7634
  }], visible: [{
7586
7635
  type: HostBinding,
7587
7636
  args: ['class.visible']
7637
+ }], isPinned: [{
7638
+ type: HostBinding,
7639
+ args: ['class.pinned']
7588
7640
  }] } });
7589
7641
 
7590
7642
  const DEFAULT_MAX_MESSAGES = 2000;
@@ -7597,6 +7649,7 @@ class CommentViewComponent {
7597
7649
  //#region Fields
7598
7650
  this._sourceSubs = new Subscription();
7599
7651
  this.menuMessage = null;
7652
+ this.pinnedMessages = [];
7600
7653
  this.messages = [];
7601
7654
  this.customSortEnabled = false;
7602
7655
  this.sourceLoaded = new Promise(r => this.markSourceLoaded = r);
@@ -7626,6 +7679,7 @@ class CommentViewComponent {
7626
7679
  * *above* the visible set of messages.
7627
7680
  */
7628
7681
  this.olderMessages = [];
7682
+ this.collapsePins = false;
7629
7683
  this.newestLast = false;
7630
7684
  this.holdNewMessages = false;
7631
7685
  this.showEmptyState = true;
@@ -7638,6 +7692,8 @@ class CommentViewComponent {
7638
7692
  this._selected = new Subject();
7639
7693
  this._liked = new Subject();
7640
7694
  this._unliked = new Subject();
7695
+ this._pinned = new Subject();
7696
+ this._unpinned = new Subject();
7641
7697
  this._reported = new Subject();
7642
7698
  this._userSelected = new Subject();
7643
7699
  this._usernameSelected = new Subject();
@@ -7651,6 +7707,8 @@ class CommentViewComponent {
7651
7707
  this.reported = this._reported.asObservable();
7652
7708
  this.liked = this._liked.asObservable();
7653
7709
  this.unliked = this._unliked.asObservable();
7710
+ this.pinned = this._pinned.asObservable();
7711
+ this.unpinned = this._unpinned.asObservable();
7654
7712
  this.usernameSelected = this._usernameSelected.asObservable();
7655
7713
  this.avatarSelected = this._avatarSelected.asObservable();
7656
7714
  this.shared = this._shared.asObservable();
@@ -7774,6 +7832,12 @@ class CommentViewComponent {
7774
7832
  unlikeMessage(message) {
7775
7833
  this._unliked.next(message);
7776
7834
  }
7835
+ pinMessage(message, options) {
7836
+ this._pinned.next({ message, options });
7837
+ }
7838
+ unpinMessage(message) {
7839
+ this._unpinned.next(message);
7840
+ }
7777
7841
  reportMessage(message) {
7778
7842
  this._reported.next(message);
7779
7843
  }
@@ -7818,12 +7882,17 @@ class CommentViewComponent {
7818
7882
  this._sourceSubs = new Subscription();
7819
7883
  this._sourceSubs.add(this._source.messageReceived.subscribe(msg => this.messageReceived(msg)));
7820
7884
  this._sourceSubs.add(this._source.messageSent.subscribe(msg => this.messageSent(msg)));
7885
+ this._sourceSubs.add(this._source.messageUpdated.subscribe(msg => this.messageUpdated(msg)));
7821
7886
  this._sourceSubs.add(this.backend.userChanged.subscribe(user => this.currentUser = user));
7822
7887
  this.getInitialMessages();
7823
7888
  }
7824
7889
  }
7825
7890
  async getInitialMessages() {
7826
- let messages = (await this._source.getExistingMessages());
7891
+ // Get the pinned messages
7892
+ let pinnedMessages = await this._source.getPinnedMessages();
7893
+ pinnedMessages.forEach(m => m.transientState ??= {});
7894
+ this.pinnedMessages = pinnedMessages;
7895
+ let messages = await this._source.getExistingMessages();
7827
7896
  messages.forEach(m => m.transientState ??= {});
7828
7897
  this.messages = this.newestLast ? messages.slice().reverse() : messages;
7829
7898
  if (this.messages.length > this.maxVisibleMessages) {
@@ -8204,6 +8273,28 @@ class CommentViewComponent {
8204
8273
  return;
8205
8274
  this.scrollToLatest();
8206
8275
  }
8276
+ isPinned(message) {
8277
+ return message.pinned && (!message.pinnedUntil || message.pinnedUntil > Date.now());
8278
+ }
8279
+ messageUpdated(message) {
8280
+ let pinned = this.isPinned(message);
8281
+ let inPins = this.pinnedMessages.some(x => x.id === message.id);
8282
+ if (pinned && !inPins) {
8283
+ this.pinnedMessages.unshift(message);
8284
+ let index = this.messages.indexOf(message);
8285
+ if (index >= 0) {
8286
+ this.messages.splice(index, 1);
8287
+ }
8288
+ }
8289
+ else if (!pinned && inPins) {
8290
+ this.messages.push(message);
8291
+ let index = this.pinnedMessages.indexOf(message);
8292
+ if (index >= 0) {
8293
+ this.pinnedMessages.splice(index, 1);
8294
+ }
8295
+ this.sortMessages();
8296
+ }
8297
+ }
8207
8298
  scrollToLatest() {
8208
8299
  if (!this.messageContainer) {
8209
8300
  return;
@@ -8238,17 +8329,19 @@ class CommentViewComponent {
8238
8329
  return false;
8239
8330
  }
8240
8331
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: CommentViewComponent, deps: [{ token: ChatBackendBase }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
8241
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.9", type: CommentViewComponent, selector: "banta-comment-view", inputs: { source: "source", maxMessages: "maxMessages", maxVisibleMessages: "maxVisibleMessages", newestLast: "newestLast", holdNewMessages: "holdNewMessages", showEmptyState: "showEmptyState", allowReplies: "allowReplies", enableHoldOnClick: "enableHoldOnClick", enableHoldOnScroll: "enableHoldOnScroll", customMenuItems: "customMenuItems", fixedHeight: "fixedHeight", selectedMessage: "selectedMessage", genericAvatarUrl: "genericAvatarUrl" }, outputs: { userSelected: "userSelected", reported: "reported", liked: "liked", unliked: "unliked", usernameSelected: "usernameSelected", avatarSelected: "avatarSelected", shared: "shared", deleted: "deleted", selected: "selected", messageEdited: "messageEdited", sortOrderChanged: "sortOrderChanged", filterModeChanged: "filterModeChanged" }, host: { properties: { "class.fixed-height": "this.fixedHeight" } }, viewQueries: [{ propertyName: "messageContainer", first: true, predicate: ["messageContainer"], descendants: true }, { propertyName: "commentsQuery", predicate: CommentComponent, descendants: true }], ngImport: i0, template: "<div class=\"banta-message-container\" #messageContainer>\r\n <ng-content select=\"[data-before]\"></ng-content>\r\n\r\n <div class=\"banta-top-sticky\">\r\n @if (!newestLast) {\r\n <button \r\n mat-button \r\n class=\"banta-nav\" \r\n [class.visible]=\"shouldShowNewMessageIndicator\" \r\n href=\"javascript:;\" \r\n (click)=\"showNewest($event)\"\r\n >\r\n <mat-icon>file_upload</mat-icon>\r\n Newest\r\n @if (heldMessages.length > 0) {\r\n <span class=\"count\">{{ heldMessages.length | number }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n\r\n <button mat-button class=\"pager\" (click)=\"showPrevious()\" [class.visible]=\"shouldShowPrevious\" [disabled]=\"isLoadingMore\">\r\n <mat-icon>expand_less</mat-icon>\r\n {{ previousLabel }}\r\n </button>\r\n\r\n @for (message of messages; track message.id) {\r\n @if (!message.hidden) {\r\n <banta-comment\r\n class=\"abbreviated\"\r\n \r\n [customMenuItems]=\"customMenuItems\"\r\n [message]=\"message\"\r\n [mine]=\"currentUser?.id === message.user?.id\"\r\n [permissions]=\"source?.permissions\"\r\n [showReplyAction]=\"allowReplies\"\r\n [editing]=\"message.transientState.editing\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n [readonly]=\"source?.readonly\"\r\n (click)=\"messageClicked = true\"\r\n (editStarted)=\"startEditing(message)\"\r\n (deleted)=\"deleteMessage(message)\"\r\n (editEnded)=\"message.transientState.editing = false\"\r\n (edited)=\"saveEdit(message, $event)\"\r\n (userSelected)=\"selectMessageUser(message)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (liked)=\"likeMessage(message)\"\r\n (unliked)=\"unlikeMessage(message)\"\r\n (reported)=\"reportMessage(message)\"\r\n (selected)=\"selectMessage(message)\"\r\n (shared)=\"sharedMessage($event)\"\r\n />\r\n <div class=\"banta-inline-replies-container\" *ngIf=\"selectedMessage === message\">\r\n <ng-content select=\".inline-replies\"></ng-content>\r\n </div>\r\n }\r\n } @empty {\r\n <div class=\"banta-empty-state\" *ngIf=\"showEmptyState\">\r\n Be the first to comment!\r\n </div>\r\n }\r\n\r\n <button mat-button class=\"pager\" (click)=\"showNext()\" [class.visible]=\"shouldShowNext\" [disabled]=\"isLoadingMore\">\r\n <mat-icon>expand_more</mat-icon>\r\n {{ nextLabel }}\r\n </button>\r\n\r\n <div class=\"banta-nav-point banta-bottom-sticky\">\r\n @if (newestLast) {\r\n <button \r\n [matBadge]=\"10\" matBadgeOverlap=\"false\"\r\n matBadgePosition=\"after\" matBadgeSize=\"large\" \r\n mat-button \r\n class=\"banta-nav\" \r\n [class.visible]=\"shouldShowNewMessageIndicator\" \r\n href=\"javascript:;\" \r\n (click)=\"showNewest($event)\"\r\n >\r\n <mat-icon>file_download</mat-icon>\r\n Newest\r\n @if (heldMessages.length > 0) {\r\n <span class=\"count\">{{ heldMessages.length | number }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n\r\n <div class=\"banta-loading-more\" *ngIf=\"isLoadingMore\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n\r\n @if (showDebug) {\r\n <div style=\"color: #666\">\r\n ({{ previousMessages.length }} .. {{ messages.length }} .. {{ nextMessages.length }})\r\n\r\n dir={{newestLast ? '-1' : '1'}}\r\n v={{maxVisibleMessages}}, M={{maxMessages}}\r\n </div>\r\n }\r\n\r\n <ng-content select=\":not([data-before]):not(.inline-replies)\"></ng-content>\r\n</div>\r\n", styles: [":host{flex-grow:1;display:flex;flex-direction:column;opacity:1;transition:.2s opacity ease-in}.banta-message-container{flex-grow:1;color:#111;background:#fff;padding:.5em 1em 3em .5em;opacity:1;transition:.5s opacity ease-in-out;position:relative}.banta-message-container.no-scroll{height:auto;overflow-y:visible}.banta-message-container.faded{opacity:.25}.banta-message-container .overlay{position:absolute;inset:0;z-index:10}:host.fixed-height .banta-message-container{overflow-y:auto}:host-context(.mat-dark-theme) .banta-message-container{color:#fff;background:#111}.banta-empty-state{text-align:center;margin:3em;color:#666}:host-context(.mat-dark-theme) .empty-state{color:#666}button.banta-nav{position:absolute;right:.5em;z-index:10;text-align:center;opacity:0;transition:.4s opacity ease-in-out;pointer-events:none;border-radius:2em;background-color:#ddd}:host-context(.mat-dark-theme) button.banta-nav{background-color:#222;color:#fff}button.banta-nav span.count{background-color:#a93535;color:#fff;padding:4px 10px;border-radius:.5em;margin-left:.25em;font-size:90%}button.banta-nav.visible{opacity:1;pointer-events:initial}button.pager{appearance:none;border:none;width:100%;opacity:0;pointer-events:none;transition:.4s opacity ease-in-out}button.pager.visible{opacity:1;pointer-events:initial}.banta-top-sticky{position:sticky;top:.5em;z-index:10}.banta-bottom-sticky{position:sticky;bottom:3em;z-index:10}.banta-loading-more{padding:2em;text-align:center;margin:0 auto;width:fit-content}@media (max-width: 400px){.banta-message-container{padding:0 0 3em}}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.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-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i8.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: CommentComponent, selector: "banta-comment", inputs: ["message", "customMenuItems", "showReplyAction", "maxLength", "permissions", "mine", "editing", "genericAvatarUrl", "readonly"], outputs: ["liked", "unliked", "selected", "edited", "deleted", "editStarted", "editEnded", "shared", "userSelected", "usernameSelected", "avatarSelected", "reported", "loaded"] }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }] }); }
8332
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.9", type: CommentViewComponent, selector: "banta-comment-view", inputs: { source: "source", maxMessages: "maxMessages", maxVisibleMessages: "maxVisibleMessages", collapsePins: "collapsePins", newestLast: "newestLast", holdNewMessages: "holdNewMessages", showEmptyState: "showEmptyState", allowReplies: "allowReplies", enableHoldOnClick: "enableHoldOnClick", enableHoldOnScroll: "enableHoldOnScroll", customMenuItems: "customMenuItems", fixedHeight: "fixedHeight", selectedMessage: "selectedMessage", genericAvatarUrl: "genericAvatarUrl" }, outputs: { userSelected: "userSelected", reported: "reported", liked: "liked", unliked: "unliked", pinned: "pinned", unpinned: "unpinned", usernameSelected: "usernameSelected", avatarSelected: "avatarSelected", shared: "shared", deleted: "deleted", selected: "selected", messageEdited: "messageEdited", sortOrderChanged: "sortOrderChanged", filterModeChanged: "filterModeChanged" }, host: { properties: { "class.fixed-height": "this.fixedHeight" } }, viewQueries: [{ propertyName: "messageContainer", first: true, predicate: ["messageContainer"], descendants: true }, { propertyName: "commentsQuery", predicate: CommentComponent, descendants: true }], ngImport: i0, template: "<div class=\"banta-message-container\" #messageContainer>\r\n <ng-content select=\"[data-before]\"></ng-content>\r\n\r\n @if (!collapsePins) {\r\n @for (message of pinnedMessages; track message.id) {\r\n @if (!message.hidden) {\r\n <banta-comment\r\n class=\"abbreviated\"\r\n \r\n [customMenuItems]=\"customMenuItems\"\r\n [message]=\"message\"\r\n [mine]=\"currentUser?.id === message.user?.id\"\r\n [permissions]=\"source?.permissions\"\r\n [showReplyAction]=\"allowReplies\"\r\n [editing]=\"message.transientState.editing\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n [readonly]=\"source?.readonly\"\r\n (click)=\"messageClicked = true\"\r\n (editStarted)=\"startEditing(message)\"\r\n (deleted)=\"deleteMessage(message)\"\r\n (editEnded)=\"message.transientState.editing = false\"\r\n (edited)=\"saveEdit(message, $event)\"\r\n (userSelected)=\"selectMessageUser(message)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (liked)=\"likeMessage(message)\"\r\n (pinned)=\"pinMessage(message, $event.options)\"\r\n (unpinned)=\"unpinMessage(message)\"\r\n (unliked)=\"unlikeMessage(message)\"\r\n (reported)=\"reportMessage(message)\"\r\n (selected)=\"selectMessage(message)\"\r\n (shared)=\"sharedMessage($event)\"\r\n />\r\n <div class=\"banta-inline-replies-container\" *ngIf=\"selectedMessage === message\">\r\n <ng-content select=\".inline-replies\"></ng-content>\r\n </div>\r\n }\r\n }\r\n }\r\n\r\n <div class=\"banta-top-sticky\">\r\n @if (!newestLast) {\r\n <button \r\n mat-button \r\n class=\"banta-nav\" \r\n [class.visible]=\"shouldShowNewMessageIndicator\" \r\n href=\"javascript:;\" \r\n (click)=\"showNewest($event)\"\r\n >\r\n <mat-icon>file_upload</mat-icon>\r\n Newest\r\n @if (heldMessages.length > 0) {\r\n <span class=\"count\">{{ heldMessages.length | number }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n\r\n <button mat-button class=\"pager\" (click)=\"showPrevious()\" [class.visible]=\"shouldShowPrevious\" [disabled]=\"isLoadingMore\">\r\n <mat-icon>expand_less</mat-icon>\r\n {{ previousLabel }}\r\n </button>\r\n\r\n @for (message of messages; track message.id) {\r\n @if (!message.hidden) {\r\n <banta-comment\r\n class=\"abbreviated\"\r\n \r\n [customMenuItems]=\"customMenuItems\"\r\n [message]=\"message\"\r\n [mine]=\"currentUser?.id === message.user?.id\"\r\n [permissions]=\"source?.permissions\"\r\n [showReplyAction]=\"allowReplies\"\r\n [editing]=\"message.transientState.editing\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n [readonly]=\"source?.readonly\"\r\n (click)=\"messageClicked = true\"\r\n (editStarted)=\"startEditing(message)\"\r\n (deleted)=\"deleteMessage(message)\"\r\n (editEnded)=\"message.transientState.editing = false\"\r\n (edited)=\"saveEdit(message, $event)\"\r\n (userSelected)=\"selectMessageUser(message)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (liked)=\"likeMessage(message)\"\r\n (pinned)=\"pinMessage(message, $event.options)\"\r\n (unpinned)=\"unpinMessage(message)\"\r\n (unliked)=\"unlikeMessage(message)\"\r\n (reported)=\"reportMessage(message)\"\r\n (selected)=\"selectMessage(message)\"\r\n (shared)=\"sharedMessage($event)\"\r\n />\r\n <div class=\"banta-inline-replies-container\" *ngIf=\"selectedMessage === message\">\r\n <ng-content select=\".inline-replies\"></ng-content>\r\n </div>\r\n }\r\n } @empty {\r\n <div class=\"banta-empty-state\" *ngIf=\"showEmptyState\">\r\n Be the first to comment!\r\n </div>\r\n }\r\n\r\n <button mat-button class=\"pager\" (click)=\"showNext()\" [class.visible]=\"shouldShowNext\" [disabled]=\"isLoadingMore\">\r\n <mat-icon>expand_more</mat-icon>\r\n {{ nextLabel }}\r\n </button>\r\n\r\n <div class=\"banta-nav-point banta-bottom-sticky\">\r\n @if (newestLast) {\r\n <button \r\n [matBadge]=\"10\" matBadgeOverlap=\"false\"\r\n matBadgePosition=\"after\" matBadgeSize=\"large\" \r\n mat-button \r\n class=\"banta-nav\" \r\n [class.visible]=\"shouldShowNewMessageIndicator\" \r\n href=\"javascript:;\" \r\n (click)=\"showNewest($event)\"\r\n >\r\n <mat-icon>file_download</mat-icon>\r\n Newest\r\n @if (heldMessages.length > 0) {\r\n <span class=\"count\">{{ heldMessages.length | number }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n\r\n <div class=\"banta-loading-more\" *ngIf=\"isLoadingMore\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n\r\n @if (showDebug) {\r\n <div style=\"color: #666\">\r\n ({{ previousMessages.length }} .. {{ messages.length }} .. {{ nextMessages.length }})\r\n\r\n dir={{newestLast ? '-1' : '1'}}\r\n v={{maxVisibleMessages}}, M={{maxMessages}}\r\n </div>\r\n }\r\n\r\n <ng-content select=\":not([data-before]):not(.inline-replies)\"></ng-content>\r\n</div>\r\n", styles: [":host{flex-grow:1;display:flex;flex-direction:column;opacity:1;transition:.2s opacity ease-in}.banta-message-container{flex-grow:1;color:#111;background:#fff;padding:.5em 1em 3em .5em;opacity:1;transition:.5s opacity ease-in-out;position:relative}.banta-message-container.no-scroll{height:auto;overflow-y:visible}.banta-message-container.faded{opacity:.25}.banta-message-container .overlay{position:absolute;inset:0;z-index:10}:host.fixed-height .banta-message-container{overflow-y:auto}:host-context(.mat-dark-theme) .banta-message-container{color:#fff;background:#111}.banta-empty-state{text-align:center;margin:3em;color:#666}:host-context(.mat-dark-theme) .empty-state{color:#666}button.banta-nav{position:absolute;right:.5em;z-index:10;text-align:center;opacity:0;transition:.4s opacity ease-in-out;pointer-events:none;border-radius:2em;background-color:#ddd}:host-context(.mat-dark-theme) button.banta-nav{background-color:#222;color:#fff}button.banta-nav span.count{background-color:#a93535;color:#fff;padding:4px 10px;border-radius:.5em;margin-left:.25em;font-size:90%}button.banta-nav.visible{opacity:1;pointer-events:initial}button.pager{appearance:none;border:none;width:100%;opacity:0;pointer-events:none;transition:.4s opacity ease-in-out}button.pager.visible{opacity:1;pointer-events:initial}.banta-top-sticky{position:sticky;top:.5em;z-index:10}.banta-bottom-sticky{position:sticky;bottom:3em;z-index:10}.banta-loading-more{padding:2em;text-align:center;margin:0 auto;width:fit-content}@media (max-width: 400px){.banta-message-container{padding:0 0 3em}}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.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-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i9.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: CommentComponent, selector: "banta-comment", inputs: ["message", "customMenuItems", "showReplyAction", "maxLength", "permissions", "mine", "editing", "genericAvatarUrl", "readonly"], outputs: ["liked", "unliked", "selected", "edited", "deleted", "editStarted", "editEnded", "shared", "userSelected", "usernameSelected", "avatarSelected", "reported", "loaded", "pinned", "unpinned"] }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }] }); }
8242
8333
  }
8243
8334
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: CommentViewComponent, decorators: [{
8244
8335
  type: Component,
8245
- args: [{ selector: 'banta-comment-view', template: "<div class=\"banta-message-container\" #messageContainer>\r\n <ng-content select=\"[data-before]\"></ng-content>\r\n\r\n <div class=\"banta-top-sticky\">\r\n @if (!newestLast) {\r\n <button \r\n mat-button \r\n class=\"banta-nav\" \r\n [class.visible]=\"shouldShowNewMessageIndicator\" \r\n href=\"javascript:;\" \r\n (click)=\"showNewest($event)\"\r\n >\r\n <mat-icon>file_upload</mat-icon>\r\n Newest\r\n @if (heldMessages.length > 0) {\r\n <span class=\"count\">{{ heldMessages.length | number }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n\r\n <button mat-button class=\"pager\" (click)=\"showPrevious()\" [class.visible]=\"shouldShowPrevious\" [disabled]=\"isLoadingMore\">\r\n <mat-icon>expand_less</mat-icon>\r\n {{ previousLabel }}\r\n </button>\r\n\r\n @for (message of messages; track message.id) {\r\n @if (!message.hidden) {\r\n <banta-comment\r\n class=\"abbreviated\"\r\n \r\n [customMenuItems]=\"customMenuItems\"\r\n [message]=\"message\"\r\n [mine]=\"currentUser?.id === message.user?.id\"\r\n [permissions]=\"source?.permissions\"\r\n [showReplyAction]=\"allowReplies\"\r\n [editing]=\"message.transientState.editing\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n [readonly]=\"source?.readonly\"\r\n (click)=\"messageClicked = true\"\r\n (editStarted)=\"startEditing(message)\"\r\n (deleted)=\"deleteMessage(message)\"\r\n (editEnded)=\"message.transientState.editing = false\"\r\n (edited)=\"saveEdit(message, $event)\"\r\n (userSelected)=\"selectMessageUser(message)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (liked)=\"likeMessage(message)\"\r\n (unliked)=\"unlikeMessage(message)\"\r\n (reported)=\"reportMessage(message)\"\r\n (selected)=\"selectMessage(message)\"\r\n (shared)=\"sharedMessage($event)\"\r\n />\r\n <div class=\"banta-inline-replies-container\" *ngIf=\"selectedMessage === message\">\r\n <ng-content select=\".inline-replies\"></ng-content>\r\n </div>\r\n }\r\n } @empty {\r\n <div class=\"banta-empty-state\" *ngIf=\"showEmptyState\">\r\n Be the first to comment!\r\n </div>\r\n }\r\n\r\n <button mat-button class=\"pager\" (click)=\"showNext()\" [class.visible]=\"shouldShowNext\" [disabled]=\"isLoadingMore\">\r\n <mat-icon>expand_more</mat-icon>\r\n {{ nextLabel }}\r\n </button>\r\n\r\n <div class=\"banta-nav-point banta-bottom-sticky\">\r\n @if (newestLast) {\r\n <button \r\n [matBadge]=\"10\" matBadgeOverlap=\"false\"\r\n matBadgePosition=\"after\" matBadgeSize=\"large\" \r\n mat-button \r\n class=\"banta-nav\" \r\n [class.visible]=\"shouldShowNewMessageIndicator\" \r\n href=\"javascript:;\" \r\n (click)=\"showNewest($event)\"\r\n >\r\n <mat-icon>file_download</mat-icon>\r\n Newest\r\n @if (heldMessages.length > 0) {\r\n <span class=\"count\">{{ heldMessages.length | number }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n\r\n <div class=\"banta-loading-more\" *ngIf=\"isLoadingMore\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n\r\n @if (showDebug) {\r\n <div style=\"color: #666\">\r\n ({{ previousMessages.length }} .. {{ messages.length }} .. {{ nextMessages.length }})\r\n\r\n dir={{newestLast ? '-1' : '1'}}\r\n v={{maxVisibleMessages}}, M={{maxMessages}}\r\n </div>\r\n }\r\n\r\n <ng-content select=\":not([data-before]):not(.inline-replies)\"></ng-content>\r\n</div>\r\n", styles: [":host{flex-grow:1;display:flex;flex-direction:column;opacity:1;transition:.2s opacity ease-in}.banta-message-container{flex-grow:1;color:#111;background:#fff;padding:.5em 1em 3em .5em;opacity:1;transition:.5s opacity ease-in-out;position:relative}.banta-message-container.no-scroll{height:auto;overflow-y:visible}.banta-message-container.faded{opacity:.25}.banta-message-container .overlay{position:absolute;inset:0;z-index:10}:host.fixed-height .banta-message-container{overflow-y:auto}:host-context(.mat-dark-theme) .banta-message-container{color:#fff;background:#111}.banta-empty-state{text-align:center;margin:3em;color:#666}:host-context(.mat-dark-theme) .empty-state{color:#666}button.banta-nav{position:absolute;right:.5em;z-index:10;text-align:center;opacity:0;transition:.4s opacity ease-in-out;pointer-events:none;border-radius:2em;background-color:#ddd}:host-context(.mat-dark-theme) button.banta-nav{background-color:#222;color:#fff}button.banta-nav span.count{background-color:#a93535;color:#fff;padding:4px 10px;border-radius:.5em;margin-left:.25em;font-size:90%}button.banta-nav.visible{opacity:1;pointer-events:initial}button.pager{appearance:none;border:none;width:100%;opacity:0;pointer-events:none;transition:.4s opacity ease-in-out}button.pager.visible{opacity:1;pointer-events:initial}.banta-top-sticky{position:sticky;top:.5em;z-index:10}.banta-bottom-sticky{position:sticky;bottom:3em;z-index:10}.banta-loading-more{padding:2em;text-align:center;margin:0 auto;width:fit-content}@media (max-width: 400px){.banta-message-container{padding:0 0 3em}}\n"] }]
8336
+ args: [{ selector: 'banta-comment-view', template: "<div class=\"banta-message-container\" #messageContainer>\r\n <ng-content select=\"[data-before]\"></ng-content>\r\n\r\n @if (!collapsePins) {\r\n @for (message of pinnedMessages; track message.id) {\r\n @if (!message.hidden) {\r\n <banta-comment\r\n class=\"abbreviated\"\r\n \r\n [customMenuItems]=\"customMenuItems\"\r\n [message]=\"message\"\r\n [mine]=\"currentUser?.id === message.user?.id\"\r\n [permissions]=\"source?.permissions\"\r\n [showReplyAction]=\"allowReplies\"\r\n [editing]=\"message.transientState.editing\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n [readonly]=\"source?.readonly\"\r\n (click)=\"messageClicked = true\"\r\n (editStarted)=\"startEditing(message)\"\r\n (deleted)=\"deleteMessage(message)\"\r\n (editEnded)=\"message.transientState.editing = false\"\r\n (edited)=\"saveEdit(message, $event)\"\r\n (userSelected)=\"selectMessageUser(message)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (liked)=\"likeMessage(message)\"\r\n (pinned)=\"pinMessage(message, $event.options)\"\r\n (unpinned)=\"unpinMessage(message)\"\r\n (unliked)=\"unlikeMessage(message)\"\r\n (reported)=\"reportMessage(message)\"\r\n (selected)=\"selectMessage(message)\"\r\n (shared)=\"sharedMessage($event)\"\r\n />\r\n <div class=\"banta-inline-replies-container\" *ngIf=\"selectedMessage === message\">\r\n <ng-content select=\".inline-replies\"></ng-content>\r\n </div>\r\n }\r\n }\r\n }\r\n\r\n <div class=\"banta-top-sticky\">\r\n @if (!newestLast) {\r\n <button \r\n mat-button \r\n class=\"banta-nav\" \r\n [class.visible]=\"shouldShowNewMessageIndicator\" \r\n href=\"javascript:;\" \r\n (click)=\"showNewest($event)\"\r\n >\r\n <mat-icon>file_upload</mat-icon>\r\n Newest\r\n @if (heldMessages.length > 0) {\r\n <span class=\"count\">{{ heldMessages.length | number }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n\r\n <button mat-button class=\"pager\" (click)=\"showPrevious()\" [class.visible]=\"shouldShowPrevious\" [disabled]=\"isLoadingMore\">\r\n <mat-icon>expand_less</mat-icon>\r\n {{ previousLabel }}\r\n </button>\r\n\r\n @for (message of messages; track message.id) {\r\n @if (!message.hidden) {\r\n <banta-comment\r\n class=\"abbreviated\"\r\n \r\n [customMenuItems]=\"customMenuItems\"\r\n [message]=\"message\"\r\n [mine]=\"currentUser?.id === message.user?.id\"\r\n [permissions]=\"source?.permissions\"\r\n [showReplyAction]=\"allowReplies\"\r\n [editing]=\"message.transientState.editing\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n [readonly]=\"source?.readonly\"\r\n (click)=\"messageClicked = true\"\r\n (editStarted)=\"startEditing(message)\"\r\n (deleted)=\"deleteMessage(message)\"\r\n (editEnded)=\"message.transientState.editing = false\"\r\n (edited)=\"saveEdit(message, $event)\"\r\n (userSelected)=\"selectMessageUser(message)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (liked)=\"likeMessage(message)\"\r\n (pinned)=\"pinMessage(message, $event.options)\"\r\n (unpinned)=\"unpinMessage(message)\"\r\n (unliked)=\"unlikeMessage(message)\"\r\n (reported)=\"reportMessage(message)\"\r\n (selected)=\"selectMessage(message)\"\r\n (shared)=\"sharedMessage($event)\"\r\n />\r\n <div class=\"banta-inline-replies-container\" *ngIf=\"selectedMessage === message\">\r\n <ng-content select=\".inline-replies\"></ng-content>\r\n </div>\r\n }\r\n } @empty {\r\n <div class=\"banta-empty-state\" *ngIf=\"showEmptyState\">\r\n Be the first to comment!\r\n </div>\r\n }\r\n\r\n <button mat-button class=\"pager\" (click)=\"showNext()\" [class.visible]=\"shouldShowNext\" [disabled]=\"isLoadingMore\">\r\n <mat-icon>expand_more</mat-icon>\r\n {{ nextLabel }}\r\n </button>\r\n\r\n <div class=\"banta-nav-point banta-bottom-sticky\">\r\n @if (newestLast) {\r\n <button \r\n [matBadge]=\"10\" matBadgeOverlap=\"false\"\r\n matBadgePosition=\"after\" matBadgeSize=\"large\" \r\n mat-button \r\n class=\"banta-nav\" \r\n [class.visible]=\"shouldShowNewMessageIndicator\" \r\n href=\"javascript:;\" \r\n (click)=\"showNewest($event)\"\r\n >\r\n <mat-icon>file_download</mat-icon>\r\n Newest\r\n @if (heldMessages.length > 0) {\r\n <span class=\"count\">{{ heldMessages.length | number }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n\r\n <div class=\"banta-loading-more\" *ngIf=\"isLoadingMore\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n\r\n @if (showDebug) {\r\n <div style=\"color: #666\">\r\n ({{ previousMessages.length }} .. {{ messages.length }} .. {{ nextMessages.length }})\r\n\r\n dir={{newestLast ? '-1' : '1'}}\r\n v={{maxVisibleMessages}}, M={{maxMessages}}\r\n </div>\r\n }\r\n\r\n <ng-content select=\":not([data-before]):not(.inline-replies)\"></ng-content>\r\n</div>\r\n", styles: [":host{flex-grow:1;display:flex;flex-direction:column;opacity:1;transition:.2s opacity ease-in}.banta-message-container{flex-grow:1;color:#111;background:#fff;padding:.5em 1em 3em .5em;opacity:1;transition:.5s opacity ease-in-out;position:relative}.banta-message-container.no-scroll{height:auto;overflow-y:visible}.banta-message-container.faded{opacity:.25}.banta-message-container .overlay{position:absolute;inset:0;z-index:10}:host.fixed-height .banta-message-container{overflow-y:auto}:host-context(.mat-dark-theme) .banta-message-container{color:#fff;background:#111}.banta-empty-state{text-align:center;margin:3em;color:#666}:host-context(.mat-dark-theme) .empty-state{color:#666}button.banta-nav{position:absolute;right:.5em;z-index:10;text-align:center;opacity:0;transition:.4s opacity ease-in-out;pointer-events:none;border-radius:2em;background-color:#ddd}:host-context(.mat-dark-theme) button.banta-nav{background-color:#222;color:#fff}button.banta-nav span.count{background-color:#a93535;color:#fff;padding:4px 10px;border-radius:.5em;margin-left:.25em;font-size:90%}button.banta-nav.visible{opacity:1;pointer-events:initial}button.pager{appearance:none;border:none;width:100%;opacity:0;pointer-events:none;transition:.4s opacity ease-in-out}button.pager.visible{opacity:1;pointer-events:initial}.banta-top-sticky{position:sticky;top:.5em;z-index:10}.banta-bottom-sticky{position:sticky;bottom:3em;z-index:10}.banta-loading-more{padding:2em;text-align:center;margin:0 auto;width:fit-content}@media (max-width: 400px){.banta-message-container{padding:0 0 3em}}\n"] }]
8246
8337
  }], ctorParameters: () => [{ type: ChatBackendBase }, { type: i0.ElementRef }], propDecorators: { source: [{
8247
8338
  type: Input
8248
8339
  }], maxMessages: [{
8249
8340
  type: Input
8250
8341
  }], maxVisibleMessages: [{
8251
8342
  type: Input
8343
+ }], collapsePins: [{
8344
+ type: Input
8252
8345
  }], newestLast: [{
8253
8346
  type: Input
8254
8347
  }], holdNewMessages: [{
@@ -8280,6 +8373,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImpor
8280
8373
  type: Output
8281
8374
  }], unliked: [{
8282
8375
  type: Output
8376
+ }], pinned: [{
8377
+ type: Output
8378
+ }], unpinned: [{
8379
+ type: Output
8283
8380
  }], usernameSelected: [{
8284
8381
  type: Output
8285
8382
  }], avatarSelected: [{
@@ -8367,7 +8464,7 @@ class AttachmentButtonComponent {
8367
8464
  }
8368
8465
  }
8369
8466
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: AttachmentButtonComponent, deps: [{ token: i1$3.CDNProvider }], target: i0.ɵɵFactoryTarget.Component }); }
8370
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: AttachmentButtonComponent, selector: "banta-attachment-button", inputs: { disabled: "disabled" }, 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()\" [disabled]=\"disabled\">\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.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: i11.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] }); }
8467
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: AttachmentButtonComponent, selector: "banta-attachment-button", inputs: { disabled: "disabled" }, 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()\" [disabled]=\"disabled\">\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.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: i12.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }] }); }
8371
8468
  }
8372
8469
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: AttachmentButtonComponent, decorators: [{
8373
8470
  type: Component,
@@ -8796,7 +8893,7 @@ class CommentFieldComponent {
8796
8893
  alert(this.sendError.message);
8797
8894
  }
8798
8895
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: CommentFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
8799
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.9", type: CommentFieldComponent, selector: "banta-comment-field", inputs: { source: "source", user: "user", canComment: "canComment", signInState: "signInState", allowAttachments: "allowAttachments", transientMessage: "transientMessage", sendLabel: "sendLabel", signingInLabel: "signingInLabel", sendingLabel: "sendingLabel", label: "label", permissionDeniedLabel: "permissionDeniedLabel", signInLabel: "signInLabel", maxLength: "maxLength", placeholder: "placeholder", shouldInterceptMessageSend: "shouldInterceptMessageSend", hashtags: "hashtags", participants: "participants", genericAvatarUrl: "genericAvatarUrl", url: "url", submit: "submit", readonly: "readonly", allowServerInfoRequest: "allowServerInfoRequest" }, outputs: { signInSelected: "signInSelected", editAvatarSelected: "editAvatarSelected", focusChange: "focusChange", textChanged: "textChanged", serverInfoRequested: "serverInfoRequested", reconnectRequested: "reconnectRequested", permissionDeniedError: "permissionDeniedError" }, host: { properties: { "class.can-comment": "this.canComment" } }, viewQueries: [{ propertyName: "autocompleteEl", first: true, predicate: ["autocomplete"], descendants: true }, { propertyName: "autocompleteContainerEl", first: true, predicate: ["autocompleteContainer"], descendants: true }, { propertyName: "textareaEl", first: true, predicate: ["textarea"], descendants: true }], ngImport: i0, template: "<form class=\"new-message\" (submit)=\"sendMessage()\">\r\n <div class=\"banta-avatar-container\">\r\n <a href=\"javascript:;\"\r\n class=\"banta-avatar\"\r\n (click)=\"showEditAvatar()\"\r\n [style.background-image]=\"'url(' + userAvatarUrl + ')'\"\r\n ></a>\r\n </div>\r\n <div class=\"banta-text-container\">\r\n <div class=\"banta-field-container\">\r\n <div class=\"banta-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 attachmentScraper\r\n [(attachments)]=\"chatMessageAttachments\"\r\n [placeholder]=\"placeholder\"\r\n matInput\r\n cdkTextareaAutosize\r\n [maxlength]=\"maxLength\"\r\n (keydown)=\"onKeyDown($event)\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"onBlur()\"\r\n [disabled]=\"sending || readonly\"\r\n [(ngModel)]=\"text\"\r\n autocomplete=\"off\"\r\n ></textarea>\r\n </mat-form-field>\r\n <div class=\"banta-options-line\">\r\n <ng-container *ngIf=\"indicatorState === 'transient'\">\r\n <div 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 </ng-container>\r\n <ng-container *ngIf=\"indicatorState === 'sending'\">\r\n <div class=\"banta-transient-message\" [class.expanded]=\"true\" (click)=\"alertError()\">\r\n <mat-spinner [inline]=\"true\" [diameter]=\"15\"></mat-spinner>\r\n {{sendingLabel}}...\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"indicatorState === 'error'\">\r\n <div class=\"banta-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 </ng-container>\r\n\r\n\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 [disabled]=\"readonly\"\r\n (addedAttachment)=\"addedAttachment($event)\"\r\n (attachmentError)=\"attachmentError($event)\"\r\n ></banta-attachment-button>\r\n <emoji-selector-button [disabled]=\"readonly\" (selected)=\"insertEmoji($event)\"></emoji-selector-button>\r\n <mat-menu #overflowMenu>\r\n <button mat-menu-item (click)=\"reconnectRequested.next()\">\r\n <mat-icon>refresh</mat-icon>\r\n Reconnect\r\n </button>\r\n @if (allowServerInfoRequest) {\r\n <button mat-menu-item (click)=\"serverInfoRequested.next()\">\r\n <mat-icon>code</mat-icon>\r\n Server Information\r\n </button>\r\n }\r\n </mat-menu>\r\n <button mat-icon-button [mat-menu-trigger-for]=\"overflowMenu\">\r\n <mat-icon>more_vert</mat-icon>\r\n </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=\"banta-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 *ngIf=\"buttonState === 'send'\"\r\n mat-raised-button\r\n class=\"send\"\r\n color=\"primary\"\r\n [disabled]=\"!sendButtonEnabled\"\r\n >\r\n <mat-icon>chevron_right</mat-icon>\r\n <span class=\"label\">{{sendLabel}}</span>\r\n </button>\r\n <button\r\n *ngIf=\"buttonState === 'sending' || buttonState === 'signing-in'\"\r\n mat-raised-button\r\n class=\"send\"\r\n color=\"primary\"\r\n [disabled]=\"!sendButtonEnabled\"\r\n >\r\n <mat-spinner class=\"icon\" diameter=\"18\" strokeWidth=\"2\"></mat-spinner>\r\n <span class=\"label\">\r\n <ng-container *ngIf=\"buttonState === 'sending'\">\r\n {{sendingLabel}}\r\n </ng-container>\r\n <ng-container *ngIf=\"buttonState === 'signing-in'\">\r\n {{signingInLabel}}\r\n </ng-container>\r\n </span>\r\n </button>\r\n <button\r\n *ngIf=\"buttonState === 'permission-denied'\"\r\n mat-raised-button\r\n class=\"send\"\r\n color=\"primary\"\r\n [disabled]=\"!sendButtonEnabled\"\r\n >\r\n {{permissionDeniedLabel}}\r\n </button>\r\n </ng-container>\r\n </div>\r\n</form>", styles: ["@keyframes comment-field-appear{0%{transform:translateY(128px);opacity:0}to{transform:translate(0);opacity:1}}:host{margin:0 2em 0 0;display:block;animation-name:comment-field-appear;animation-duration:.8s;animation-delay:.4s;animation-fill-mode:both;position:relative;z-index:20}.banta-avatar-container{width:calc(48px + 1.75em);display:flex;justify-content:flex-end;flex-shrink:0}.banta-avatar-container .banta-avatar{width:48px;height:48px;background:#000;border-radius:100%;background-size:cover;background-repeat:no-repeat;background-position:center;margin-top:.75em;margin-right:.75em}form{display:flex;padding:.5em;align-items:center}form .banta-text-container{position:relative;display:flex;flex-grow:1;min-width:0}form .banta-text-container textarea{font-size:14pt;width:100%}form .banta-text-container textarea[disabled]{opacity:.5}form .banta-text-container mat-spinner.loading{position:absolute;left:.5em;bottom:.5em}form .banta-text-container .banta-options-line{display:flex;align-items:center}form .banta-text-container .banta-options-line>*{flex-shrink:0}form .banta-text-container .banta-options-line .banta-transient-message{display:flex;flex-direction:row;align-items:center;gap:.5em}form .banta-text-container .banta-options-line .banta-error-message{left:.5em;bottom:.5em;color:#683333;overflow-x:hidden;max-width:1.5em;white-space:nowrap;transition:2s max-width ease-in-out;text-overflow:ellipsis;overflow:hidden;flex-shrink:1}form .banta-text-container .banta-options-line .banta-error-message.expanded,form .banta-text-container .banta-options-line .banta-error-message:hover{max-width:100%}form .banta-text-container .banta-options-line .banta-error-message mat-icon{vertical-align:middle}form input[type=text]{background:#000;color:#fff;border:1px solid #333;width:100%;height:1em}form .banta-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 .banta-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 .banta-actions 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:initial}.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: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}.banta-field-row,.card-attachment{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;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}.banta-avatar-container{display:none;width:auto;flex-shrink:0}.banta-avatar-container .avatar{width:32px;height:32px;margin-top:1.5em}:host:not(.can-comment) mat-form-field.message-field{display:none}:host:not(.can-comment) .banta-text-container{display:none}:host.can-comment button.send .label{display:none}button.send{min-width:auto;margin-top:1.5em}}:host-context(.banta-mobile) :host{margin:0}:host-context(.banta-mobile) .banta-avatar-container{display:none;width:auto;flex-shrink:0}:host-context(.banta-mobile) .banta-avatar-container .avatar{width:32px;height:32px;margin-top:1.5em}:host-context(.banta-mobile) :host:not(.can-comment) mat-form-field.message-field{display:none}:host-context(.banta-mobile) :host:not(.can-comment) .banta-text-container{display:none}:host-context(.banta-mobile) :host.can-comment button.send .label{display:none}:host-context(.banta-mobile) button.send{min-width:auto;margin-top:1.5em}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "directive", type: i3$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3$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: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3$1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i3$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6$1.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"] }, { kind: "component", type: i6.MatAnchor, selector: "a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: BantaAttachmentsComponent, selector: "banta-attachments", inputs: ["attachments", "editing"], outputs: ["remove", "loaded"] }, { kind: "component", type: EmojiSelectorButtonComponent, selector: "emoji-selector-button", inputs: ["disabled", "overlayX", "overlayY", "originX", "originY"], outputs: ["selected"] }, { kind: "directive", type: i11.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: AttachmentButtonComponent, selector: "banta-attachment-button", inputs: ["disabled"], outputs: ["addedAttachment", "attachmentError"] }, { kind: "directive", type: AttachmentScraperDirective, selector: "[attachmentScraper]", inputs: ["attachments"], outputs: ["attachmentsChange"] }] }); }
8896
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.9", type: CommentFieldComponent, selector: "banta-comment-field", inputs: { source: "source", user: "user", canComment: "canComment", signInState: "signInState", allowAttachments: "allowAttachments", transientMessage: "transientMessage", sendLabel: "sendLabel", signingInLabel: "signingInLabel", sendingLabel: "sendingLabel", label: "label", permissionDeniedLabel: "permissionDeniedLabel", signInLabel: "signInLabel", maxLength: "maxLength", placeholder: "placeholder", shouldInterceptMessageSend: "shouldInterceptMessageSend", hashtags: "hashtags", participants: "participants", genericAvatarUrl: "genericAvatarUrl", url: "url", submit: "submit", readonly: "readonly", allowServerInfoRequest: "allowServerInfoRequest" }, outputs: { signInSelected: "signInSelected", editAvatarSelected: "editAvatarSelected", focusChange: "focusChange", textChanged: "textChanged", serverInfoRequested: "serverInfoRequested", reconnectRequested: "reconnectRequested", permissionDeniedError: "permissionDeniedError" }, host: { properties: { "class.can-comment": "this.canComment" } }, viewQueries: [{ propertyName: "autocompleteEl", first: true, predicate: ["autocomplete"], descendants: true }, { propertyName: "autocompleteContainerEl", first: true, predicate: ["autocompleteContainer"], descendants: true }, { propertyName: "textareaEl", first: true, predicate: ["textarea"], descendants: true }], ngImport: i0, template: "<form class=\"new-message\" (submit)=\"sendMessage()\">\r\n <div class=\"banta-avatar-container\">\r\n <a href=\"javascript:;\"\r\n class=\"banta-avatar\"\r\n (click)=\"showEditAvatar()\"\r\n [style.background-image]=\"'url(' + userAvatarUrl + ')'\"\r\n ></a>\r\n </div>\r\n <div class=\"banta-text-container\">\r\n <div class=\"banta-field-container\">\r\n <div class=\"banta-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 attachmentScraper\r\n [(attachments)]=\"chatMessageAttachments\"\r\n [placeholder]=\"placeholder\"\r\n matInput\r\n cdkTextareaAutosize\r\n [maxlength]=\"maxLength\"\r\n (keydown)=\"onKeyDown($event)\"\r\n (focus)=\"onFocus()\"\r\n (blur)=\"onBlur()\"\r\n [disabled]=\"sending || readonly\"\r\n [(ngModel)]=\"text\"\r\n autocomplete=\"off\"\r\n ></textarea>\r\n </mat-form-field>\r\n <div class=\"banta-options-line\">\r\n <ng-container *ngIf=\"indicatorState === 'transient'\">\r\n <div 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 </ng-container>\r\n <ng-container *ngIf=\"indicatorState === 'sending'\">\r\n <div class=\"banta-transient-message\" [class.expanded]=\"true\" (click)=\"alertError()\">\r\n <mat-spinner [inline]=\"true\" [diameter]=\"15\"></mat-spinner>\r\n {{sendingLabel}}...\r\n </div>\r\n </ng-container>\r\n <ng-container *ngIf=\"indicatorState === 'error'\">\r\n <div class=\"banta-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 </ng-container>\r\n\r\n\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 [disabled]=\"readonly\"\r\n (addedAttachment)=\"addedAttachment($event)\"\r\n (attachmentError)=\"attachmentError($event)\"\r\n ></banta-attachment-button>\r\n <emoji-selector-button [disabled]=\"readonly\" (selected)=\"insertEmoji($event)\"></emoji-selector-button>\r\n <mat-menu #overflowMenu>\r\n <button mat-menu-item (click)=\"reconnectRequested.next()\">\r\n <mat-icon>refresh</mat-icon>\r\n Reconnect\r\n </button>\r\n @if (allowServerInfoRequest) {\r\n <button mat-menu-item (click)=\"serverInfoRequested.next()\">\r\n <mat-icon>code</mat-icon>\r\n Server Information\r\n </button>\r\n }\r\n </mat-menu>\r\n <button mat-icon-button [mat-menu-trigger-for]=\"overflowMenu\">\r\n <mat-icon>more_vert</mat-icon>\r\n </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=\"banta-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 *ngIf=\"buttonState === 'send'\"\r\n mat-raised-button\r\n class=\"send\"\r\n color=\"primary\"\r\n [disabled]=\"!sendButtonEnabled\"\r\n >\r\n <mat-icon>chevron_right</mat-icon>\r\n <span class=\"label\">{{sendLabel}}</span>\r\n </button>\r\n <button\r\n *ngIf=\"buttonState === 'sending' || buttonState === 'signing-in'\"\r\n mat-raised-button\r\n class=\"send\"\r\n color=\"primary\"\r\n [disabled]=\"!sendButtonEnabled\"\r\n >\r\n <mat-spinner class=\"icon\" diameter=\"18\" strokeWidth=\"2\"></mat-spinner>\r\n <span class=\"label\">\r\n <ng-container *ngIf=\"buttonState === 'sending'\">\r\n {{sendingLabel}}\r\n </ng-container>\r\n <ng-container *ngIf=\"buttonState === 'signing-in'\">\r\n {{signingInLabel}}\r\n </ng-container>\r\n </span>\r\n </button>\r\n <button\r\n *ngIf=\"buttonState === 'permission-denied'\"\r\n mat-raised-button\r\n class=\"send\"\r\n color=\"primary\"\r\n [disabled]=\"!sendButtonEnabled\"\r\n >\r\n {{permissionDeniedLabel}}\r\n </button>\r\n </ng-container>\r\n </div>\r\n</form>", styles: ["@keyframes comment-field-appear{0%{transform:translateY(128px);opacity:0}to{transform:translate(0);opacity:1}}:host{margin:0 2em 0 0;display:block;animation-name:comment-field-appear;animation-duration:.8s;animation-delay:.4s;animation-fill-mode:both;position:relative;z-index:20}.banta-avatar-container{width:calc(48px + 1.75em);display:flex;justify-content:flex-end;flex-shrink:0}.banta-avatar-container .banta-avatar{width:48px;height:48px;background:#000;border-radius:100%;background-size:cover;background-repeat:no-repeat;background-position:center;margin-top:.75em;margin-right:.75em}form{display:flex;padding:.5em;align-items:center}form .banta-text-container{position:relative;display:flex;flex-grow:1;min-width:0}form .banta-text-container textarea{font-size:14pt;width:100%}form .banta-text-container textarea[disabled]{opacity:.5}form .banta-text-container mat-spinner.loading{position:absolute;left:.5em;bottom:.5em}form .banta-text-container .banta-options-line{display:flex;align-items:center}form .banta-text-container .banta-options-line>*{flex-shrink:0}form .banta-text-container .banta-options-line .banta-transient-message{display:flex;flex-direction:row;align-items:center;gap:.5em}form .banta-text-container .banta-options-line .banta-error-message{left:.5em;bottom:.5em;color:#683333;overflow-x:hidden;max-width:1.5em;white-space:nowrap;transition:2s max-width ease-in-out;text-overflow:ellipsis;overflow:hidden;flex-shrink:1}form .banta-text-container .banta-options-line .banta-error-message.expanded,form .banta-text-container .banta-options-line .banta-error-message:hover{max-width:100%}form .banta-text-container .banta-options-line .banta-error-message mat-icon{vertical-align:middle}form input[type=text]{background:#000;color:#fff;border:1px solid #333;width:100%;height:1em}form .banta-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 .banta-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 .banta-actions 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:initial}.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: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}.banta-field-row,.card-attachment{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;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}.banta-avatar-container{display:none;width:auto;flex-shrink:0}.banta-avatar-container .avatar{width:32px;height:32px;margin-top:1.5em}:host:not(.can-comment) mat-form-field.message-field{display:none}:host:not(.can-comment) .banta-text-container{display:none}:host.can-comment button.send .label{display:none}button.send{min-width:auto;margin-top:1.5em}}:host-context(.banta-mobile) :host{margin:0}:host-context(.banta-mobile) .banta-avatar-container{display:none;width:auto;flex-shrink:0}:host-context(.banta-mobile) .banta-avatar-container .avatar{width:32px;height:32px;margin-top:1.5em}:host-context(.banta-mobile) :host:not(.can-comment) mat-form-field.message-field{display:none}:host-context(.banta-mobile) :host:not(.can-comment) .banta-text-container{display:none}:host-context(.banta-mobile) :host.can-comment button.send .label{display:none}:host-context(.banta-mobile) button.send{min-width:auto;margin-top:1.5em}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2$1.CdkTextareaAutosize, selector: "textarea[cdkTextareaAutosize]", inputs: ["cdkAutosizeMinRows", "cdkAutosizeMaxRows", "cdkTextareaAutosize", "placeholder"], exportAs: ["cdkTextareaAutosize"] }, { kind: "directive", type: i3$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3$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: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3$1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i3$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i5.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i5.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6$1.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"] }, { kind: "component", type: i6.MatAnchor, selector: "a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i9.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: BantaAttachmentsComponent, selector: "banta-attachments", inputs: ["attachments", "editing"], outputs: ["remove", "loaded"] }, { kind: "component", type: EmojiSelectorButtonComponent, selector: "emoji-selector-button", inputs: ["disabled", "overlayX", "overlayY", "originX", "originY"], outputs: ["selected"] }, { kind: "directive", type: i12.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: AttachmentButtonComponent, selector: "banta-attachment-button", inputs: ["disabled"], outputs: ["addedAttachment", "attachmentError"] }, { kind: "directive", type: AttachmentScraperDirective, selector: "[attachmentScraper]", inputs: ["attachments"], outputs: ["attachmentsChange"] }] }); }
8800
8897
  }
8801
8898
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: CommentFieldComponent, decorators: [{
8802
8899
  type: Component,
@@ -9428,6 +9525,16 @@ class BantaCommentsComponent {
9428
9525
  message.transientState.liking = false;
9429
9526
  }
9430
9527
  }
9528
+ async pinMessage(source, message, options) {
9529
+ await source.pinMessage(message.id, options);
9530
+ //this.reloadSource();
9531
+ this.matSnackBar.open(`The message has been pinned.`, undefined, { duration: 5000 });
9532
+ }
9533
+ async unpinMessage(source, message) {
9534
+ await source.unpinMessage(message.id);
9535
+ //this.reloadSource();
9536
+ this.matSnackBar.open(`The message has been unpinned.`, undefined, { duration: 5000 });
9537
+ }
9431
9538
  async unlikeMessage(source, message) {
9432
9539
  if (!this.user) {
9433
9540
  await this.showSignIn();
@@ -9563,11 +9670,11 @@ class BantaCommentsComponent {
9563
9670
  }
9564
9671
  }
9565
9672
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: BantaCommentsComponent, deps: [{ token: ChatBackendBase }, { token: i0.ElementRef }, { token: i2$2.ActivatedRoute }, { token: i3$2.MatSnackBar }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
9566
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.9", type: BantaCommentsComponent, selector: "banta-comments", inputs: { customMenuItems: "customMenuItems", url: "url", maxCommentLength: "maxCommentLength", loadingMessages: "loadingMessages", useInlineReplies: "useInlineReplies", signInLabel: "signInLabel", sendLabel: "sendLabel", signingInLabel: "signingInLabel", replyLabel: "replyLabel", sendingLabel: "sendingLabel", permissionDeniedLabel: "permissionDeniedLabel", postCommentLabel: "postCommentLabel", postReplyLabel: "postReplyLabel", allowAttachments: "allowAttachments", allowServerInfoRequest: "allowServerInfoRequest", fixedHeight: "fixedHeight", maxMessages: "maxMessages", maxVisibleMessages: "maxVisibleMessages", genericAvatarUrl: "genericAvatarUrl", shouldInterceptMessageSend: "shouldInterceptMessageSend", participants: "participants", source: "source", hashtags: "hashtags", topicID: "topicID", sortOrder: "sortOrder", filterMode: "filterMode", initialMessageCount: "initialMessageCount", metadata: "metadata" }, outputs: { signInSelected: "signInSelected", editAvatarSelected: "editAvatarSelected", permissionDeniedError: "permissionDeniedError", upvoted: "upvoted", reported: "reported", selected: "selected", userSelected: "userSelected", usernameSelected: "usernameSelected", avatarSelected: "avatarSelected", shared: "shared", reconnectRequested: "reconnectRequested" }, host: { properties: { "class.banta-mobile": "this.isMobileSized" } }, queries: [{ propertyName: "sendReplyOptionsTemplate", first: true, predicate: BantaReplySendOptionsDirective, descendants: true, read: TemplateRef }], viewQueries: [{ propertyName: "commentView", first: true, predicate: ["commentView"], descendants: true }, { propertyName: "threadViewQuery", predicate: CommentViewComponent, descendants: true }], ngImport: i0, template: "<ng-container *ngIf=\"loading\">\r\n <div class=\"loading-screen\" [class.visible]=\"showLoadingScreen\">\r\n <h1>{{loadingTitle}}</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 [maxLength]=\"maxCommentLength\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n [readonly]=\"source?.readonly\"\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)=\"toggleSelectedMessage(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 class=\"replies\"\r\n #threadView\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 [customMenuItems]=\"customMenuItems\"\r\n ></banta-comment-view>\r\n\r\n <banta-comment-field\r\n [url]=\"url\"\r\n [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [signingInLabel]=\"signingInLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n [readonly]=\"source?.readonly\"\r\n (signInSelected)=\"showSignIn()\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n [source]=\"selectedMessageThread\"\r\n [maxLength]=\"maxCommentLength\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInState]=\"source?.signInState\"\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 [url]=\"url\"\r\n [source]=\"source\"\r\n [user]=\"user\"\r\n [sendLabel]=\"sendLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [signingInLabel]=\"signingInLabel\"\r\n [signInLabel]=\"signInLabel\"\r\n [signInState]=\"source?.signInState\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n [label]=\"postCommentLabel\"\r\n [maxLength]=\"maxCommentLength\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [submit]=\"sendMessage\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n [readonly]=\"source?.readonly\"\r\n [allowServerInfoRequest]=\"allowServerInfoRequest\"\r\n (serverInfoRequested)=\"showServerInfo()\"\r\n (reconnectRequested)=\"reconnect()\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n (signInSelected)=\"showSignIn()\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n >\r\n \r\n </banta-comment-field>\r\n\r\n @if (serverInfoVisible) {\r\n <div class=\"server-info\">\r\n <div class=\"server-info-header\">\r\n Server Info\r\n <div class=\"spacer\"></div>\r\n <button mat-icon-button matTooltip=\"Reload\" (click)=\"showServerInfo()\">\r\n <mat-icon>refresh</mat-icon>\r\n </button>\r\n <button mat-icon-button matTooltip=\"Hide\" (click)=\"serverInfoVisible = false\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n @if (serverInfoLoading) {\r\n <mat-spinner />\r\n } @else {\r\n <pre>{{ serverInfo | json }}</pre>\r\n }\r\n </div>\r\n }\r\n <mat-menu #filterMenu=\"matMenu\">\r\n <button mat-menu-item *ngFor=\"let filter of filterModes\" (click)=\"filterMode = filter\">\r\n {{filterModeLabels[filter]}}\r\n </button>\r\n </mat-menu>\r\n <mat-menu #sortMenu=\"matMenu\">\r\n <button mat-menu-item *ngFor=\"let sort of sortOrders\" (click)=\"sortOrder = sort\">\r\n {{sortOrderLabels[sort]}}\r\n </button>\r\n </mat-menu>\r\n\r\n <div class=\"settings\">\r\n <button mat-button [matMenuTriggerFor]=\"filterMenu\">\r\n <mat-icon>filter_list</mat-icon>\r\n {{filterModeLabels[filterMode]}}\r\n </button>\r\n <button mat-button [matMenuTriggerFor]=\"sortMenu\">\r\n <mat-icon>sort</mat-icon>\r\n {{sortOrderLabels[sortOrder]}}\r\n </button>\r\n </div>\r\n\r\n <div class=\"loading-comment\" *ngIf=\"loadingSharedComment\">\r\n <h1>Loading the comment you linked to...</h1>\r\n <mat-spinner [diameter]=\"300\" [strokeWidth]=\"2\"></mat-spinner>\r\n <p>\r\n If there are a lot of comments, this might take awhile!\r\n </p>\r\n </div>\r\n <div class=\"loading-comment\" *ngIf=\"!loadingSharedComment && lastSharedCommentID\">\r\n <ng-container *ngIf=\"sharedCommentMissing\">\r\n\r\n <a class=\"close\" mat-icon-button matTooltip=\"Close this notice\" href=\"javascript:;\" (click)=\"lastSharedCommentID = null\">\r\n <mat-icon>close</mat-icon>\r\n </a>\r\n\r\n <h1>\r\n <mat-icon>error</mat-icon>\r\n Uh oh!\r\n </h1>\r\n\r\n <p>The comment you linked to can't be found! It may have been removed.</p>\r\n </ng-container>\r\n <ng-container *ngIf=\"!sharedCommentMissing\">\r\n <a class=\"close\" mat-icon-button matTooltip=\"Close this notice\" href=\"javascript:;\" (click)=\"lastSharedCommentID = null\">\r\n <mat-icon>close</mat-icon>\r\n </a>\r\n <button mat-button (click)=\"navigateToSharedComment(lastSharedCommentID)\">\r\n <mat-icon>move_down</mat-icon> Jump to shared comment\r\n </button>\r\n </ng-container>\r\n </div>\r\n\r\n <banta-comment-view\r\n #commentView\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 [customMenuItems]=\"customMenuItems\"\r\n [holdNewMessages]=\"selectedMessageVisible\"\r\n (userSelected)=\"selectMessageUser($event)\"\r\n (sortOrderChanged)=\"sortOrder = $event\"\r\n (filterModeChanged)=\"filterMode = $event\"\r\n (selected)=\"toggleSelectedMessage($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 [enableHoldOnClick]=\"false\"\r\n [holdNewMessages]=\"replyFieldFocused\"\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 [url]=\"url\"\r\n [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [signingInLabel]=\"signingInLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n (signInSelected)=\"showSignIn()\"\r\n [maxLength]=\"maxCommentLength\"\r\n [source]=\"selectedMessageThread\"\r\n [signInState]=\"source?.signInState\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInLabel]=\"signInLabel\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n [readonly]=\"source?.readonly\"\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 (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n (focusChange)=\"replyFieldFocused = $event\"\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 <div class=\"reconnecting\" *ngIf=\"connectionState === 'lost'\">\r\n <strong>Connection to Live Comments lost.</strong> Reconnecting...\r\n </div>\r\n</ng-container>\r\n", styles: [":host{display:flex;flex-direction:column}@keyframes select-comment{0%{transform:scale(1.15)}to{transform:scale(1)}}.focused{animation-name:select-comment;animation-duration:.4s;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:.4s opacity ease-in-out}banta-comment-view.faded{opacity:.25}.loading{display:block;width:fit-content;margin:0 auto;min-height:16em}.main.hidden{display:none}.loading-screen{text-align:center;opacity:0;transition:.25s ease-in-out opacity}.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:.25s ease-in-out opacity;width:500px;max-width:100%;margin:0 auto}.loading-screen .loading-message.visible{opacity:1}banta-comment-sort{margin:0 0 0 auto;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%}.loading-comment{z-index:100;border:1px solid #333;background:#000;color:#fff;padding:1em;border-radius:4px;text-align:center;position:relative}.loading-comment a.close{position:absolute;top:1em;right:1em}.loading-comment h1{font-weight:100;text-align:center}.loading-comment mat-spinner{margin:0 auto}.reconnecting{position:sticky;bottom:1em;background:#380a39;color:#926893;padding:1em;z-index:10;border-radius:4px;text-align:center}.settings{display:flex}.server-info{border:1px solid #0089ff;padding:0 .5em;border-radius:4px;margin:.5em 0}.server-info .server-info-header{display:flex;align-items:center}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2.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-flat-button], a[mat-stroked-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatIconAnchor, selector: "a[mat-icon-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i8.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "directive", type: i11.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: CommentComponent, selector: "banta-comment", inputs: ["message", "customMenuItems", "showReplyAction", "maxLength", "permissions", "mine", "editing", "genericAvatarUrl", "readonly"], outputs: ["liked", "unliked", "selected", "edited", "deleted", "editStarted", "editEnded", "shared", "userSelected", "usernameSelected", "avatarSelected", "reported", "loaded"] }, { kind: "component", type: CommentViewComponent, selector: "banta-comment-view", inputs: ["source", "maxMessages", "maxVisibleMessages", "newestLast", "holdNewMessages", "showEmptyState", "allowReplies", "enableHoldOnClick", "enableHoldOnScroll", "customMenuItems", "fixedHeight", "selectedMessage", "genericAvatarUrl"], outputs: ["userSelected", "reported", "liked", "unliked", "usernameSelected", "avatarSelected", "shared", "deleted", "selected", "messageEdited", "sortOrderChanged", "filterModeChanged"] }, { kind: "component", type: CommentFieldComponent, selector: "banta-comment-field", inputs: ["source", "user", "canComment", "signInState", "allowAttachments", "transientMessage", "sendLabel", "signingInLabel", "sendingLabel", "label", "permissionDeniedLabel", "signInLabel", "maxLength", "placeholder", "shouldInterceptMessageSend", "hashtags", "participants", "genericAvatarUrl", "url", "submit", "readonly", "allowServerInfoRequest"], outputs: ["signInSelected", "editAvatarSelected", "focusChange", "textChanged", "serverInfoRequested", "reconnectRequested", "permissionDeniedError"] }, { kind: "pipe", type: i1.JsonPipe, name: "json" }] }); }
9673
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.9", type: BantaCommentsComponent, selector: "banta-comments", inputs: { customMenuItems: "customMenuItems", url: "url", maxCommentLength: "maxCommentLength", loadingMessages: "loadingMessages", useInlineReplies: "useInlineReplies", signInLabel: "signInLabel", sendLabel: "sendLabel", signingInLabel: "signingInLabel", replyLabel: "replyLabel", sendingLabel: "sendingLabel", permissionDeniedLabel: "permissionDeniedLabel", postCommentLabel: "postCommentLabel", postReplyLabel: "postReplyLabel", allowAttachments: "allowAttachments", allowServerInfoRequest: "allowServerInfoRequest", fixedHeight: "fixedHeight", maxMessages: "maxMessages", maxVisibleMessages: "maxVisibleMessages", genericAvatarUrl: "genericAvatarUrl", shouldInterceptMessageSend: "shouldInterceptMessageSend", participants: "participants", source: "source", hashtags: "hashtags", topicID: "topicID", sortOrder: "sortOrder", filterMode: "filterMode", initialMessageCount: "initialMessageCount", metadata: "metadata" }, outputs: { signInSelected: "signInSelected", editAvatarSelected: "editAvatarSelected", permissionDeniedError: "permissionDeniedError", upvoted: "upvoted", reported: "reported", selected: "selected", userSelected: "userSelected", usernameSelected: "usernameSelected", avatarSelected: "avatarSelected", shared: "shared", reconnectRequested: "reconnectRequested" }, host: { properties: { "class.banta-mobile": "this.isMobileSized" } }, queries: [{ propertyName: "sendReplyOptionsTemplate", first: true, predicate: BantaReplySendOptionsDirective, descendants: true, read: TemplateRef }], viewQueries: [{ propertyName: "commentView", first: true, predicate: ["commentView"], descendants: true }, { propertyName: "threadViewQuery", predicate: CommentViewComponent, descendants: true }], ngImport: i0, template: "<ng-container *ngIf=\"loading\">\r\n <div class=\"loading-screen\" [class.visible]=\"showLoadingScreen\">\r\n <h1>{{loadingTitle}}</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 [maxLength]=\"maxCommentLength\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n [readonly]=\"source?.readonly\"\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 (pinned)=\"pinMessage(source, selectedMessage, $event.options)\"\r\n (unpinned)=\"unpinMessage(source, selectedMessage)\"\r\n (selected)=\"toggleSelectedMessage(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 class=\"replies\"\r\n #threadView\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 (pinned)=\"pinMessage(selectedMessageThread, $event.message, $event.options)\"\r\n (unpinned)=\"unpinMessage(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 [customMenuItems]=\"customMenuItems\"\r\n ></banta-comment-view>\r\n\r\n <banta-comment-field\r\n [url]=\"url\"\r\n [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [signingInLabel]=\"signingInLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n [readonly]=\"source?.readonly\"\r\n (signInSelected)=\"showSignIn()\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n [source]=\"selectedMessageThread\"\r\n [maxLength]=\"maxCommentLength\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInState]=\"source?.signInState\"\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 [url]=\"url\"\r\n [source]=\"source\"\r\n [user]=\"user\"\r\n [sendLabel]=\"sendLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [signingInLabel]=\"signingInLabel\"\r\n [signInLabel]=\"signInLabel\"\r\n [signInState]=\"source?.signInState\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n [label]=\"postCommentLabel\"\r\n [maxLength]=\"maxCommentLength\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [submit]=\"sendMessage\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n [readonly]=\"source?.readonly\"\r\n [allowServerInfoRequest]=\"allowServerInfoRequest\"\r\n (serverInfoRequested)=\"showServerInfo()\"\r\n (reconnectRequested)=\"reconnect()\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n (signInSelected)=\"showSignIn()\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n >\r\n \r\n </banta-comment-field>\r\n\r\n @if (serverInfoVisible) {\r\n <div class=\"server-info\">\r\n <div class=\"server-info-header\">\r\n Server Info\r\n <div class=\"spacer\"></div>\r\n <button mat-icon-button matTooltip=\"Reload\" (click)=\"showServerInfo()\">\r\n <mat-icon>refresh</mat-icon>\r\n </button>\r\n <button mat-icon-button matTooltip=\"Hide\" (click)=\"serverInfoVisible = false\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n @if (serverInfoLoading) {\r\n <mat-spinner />\r\n } @else {\r\n <pre>{{ serverInfo | json }}</pre>\r\n }\r\n </div>\r\n }\r\n <mat-menu #filterMenu=\"matMenu\">\r\n <button mat-menu-item *ngFor=\"let filter of filterModes\" (click)=\"filterMode = filter\">\r\n {{filterModeLabels[filter]}}\r\n </button>\r\n </mat-menu>\r\n <mat-menu #sortMenu=\"matMenu\">\r\n <button mat-menu-item *ngFor=\"let sort of sortOrders\" (click)=\"sortOrder = sort\">\r\n {{sortOrderLabels[sort]}}\r\n </button>\r\n </mat-menu>\r\n\r\n <div class=\"settings\">\r\n <button mat-button [matMenuTriggerFor]=\"filterMenu\">\r\n <mat-icon>filter_list</mat-icon>\r\n {{filterModeLabels[filterMode]}}\r\n </button>\r\n <button mat-button [matMenuTriggerFor]=\"sortMenu\">\r\n <mat-icon>sort</mat-icon>\r\n {{sortOrderLabels[sortOrder]}}\r\n </button>\r\n </div>\r\n\r\n <div class=\"loading-comment\" *ngIf=\"loadingSharedComment\">\r\n <h1>Loading the comment you linked to...</h1>\r\n <mat-spinner [diameter]=\"300\" [strokeWidth]=\"2\"></mat-spinner>\r\n <p>\r\n If there are a lot of comments, this might take awhile!\r\n </p>\r\n </div>\r\n <div class=\"loading-comment\" *ngIf=\"!loadingSharedComment && lastSharedCommentID\">\r\n <ng-container *ngIf=\"sharedCommentMissing\">\r\n\r\n <a class=\"close\" mat-icon-button matTooltip=\"Close this notice\" href=\"javascript:;\" (click)=\"lastSharedCommentID = null\">\r\n <mat-icon>close</mat-icon>\r\n </a>\r\n\r\n <h1>\r\n <mat-icon>error</mat-icon>\r\n Uh oh!\r\n </h1>\r\n\r\n <p>The comment you linked to can't be found! It may have been removed.</p>\r\n </ng-container>\r\n <ng-container *ngIf=\"!sharedCommentMissing\">\r\n <a class=\"close\" mat-icon-button matTooltip=\"Close this notice\" href=\"javascript:;\" (click)=\"lastSharedCommentID = null\">\r\n <mat-icon>close</mat-icon>\r\n </a>\r\n <button mat-button (click)=\"navigateToSharedComment(lastSharedCommentID)\">\r\n <mat-icon>move_down</mat-icon> Jump to shared comment\r\n </button>\r\n </ng-container>\r\n </div>\r\n\r\n <banta-comment-view\r\n #commentView\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 [customMenuItems]=\"customMenuItems\"\r\n [holdNewMessages]=\"selectedMessageVisible\"\r\n (userSelected)=\"selectMessageUser($event)\"\r\n (sortOrderChanged)=\"sortOrder = $event\"\r\n (filterModeChanged)=\"filterMode = $event\"\r\n (selected)=\"toggleSelectedMessage($event)\"\r\n (liked)=\"likeMessage(source, $event)\"\r\n (unliked)=\"unlikeMessage(source, $event)\"\r\n (pinned)=\"pinMessage(source, $event.message, $event.options)\"\r\n (unpinned)=\"unpinMessage(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 [enableHoldOnClick]=\"false\"\r\n [holdNewMessages]=\"replyFieldFocused\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (liked)=\"likeMessage(selectedMessageThread, $event)\"\r\n (unliked)=\"unlikeMessage(selectedMessageThread, $event)\"\r\n (pinned)=\"pinMessage(selectedMessageThread, $event.message, $event.options)\"\r\n (unpinned)=\"unpinMessage(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 [url]=\"url\"\r\n [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [signingInLabel]=\"signingInLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n (signInSelected)=\"showSignIn()\"\r\n [maxLength]=\"maxCommentLength\"\r\n [source]=\"selectedMessageThread\"\r\n [signInState]=\"source?.signInState\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInLabel]=\"signInLabel\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n [readonly]=\"source?.readonly\"\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 (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n (focusChange)=\"replyFieldFocused = $event\"\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 <div class=\"reconnecting\" *ngIf=\"connectionState === 'lost'\">\r\n <strong>Connection to Live Comments lost.</strong> Reconnecting...\r\n </div>\r\n</ng-container>\r\n", styles: [":host{display:flex;flex-direction:column}@keyframes select-comment{0%{transform:scale(1.15)}to{transform:scale(1)}}.focused{animation-name:select-comment;animation-duration:.4s;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:.4s opacity ease-in-out}banta-comment-view.faded{opacity:.25}.loading{display:block;width:fit-content;margin:0 auto;min-height:16em}.main.hidden{display:none}.loading-screen{text-align:center;opacity:0;transition:.25s ease-in-out opacity}.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:.25s ease-in-out opacity;width:500px;max-width:100%;margin:0 auto}.loading-screen .loading-message.visible{opacity:1}banta-comment-sort{margin:0 0 0 auto;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%}.loading-comment{z-index:100;border:1px solid #333;background:#000;color:#fff;padding:1em;border-radius:4px;text-align:center;position:relative}.loading-comment a.close{position:absolute;top:1em;right:1em}.loading-comment h1{font-weight:100;text-align:center}.loading-comment mat-spinner{margin:0 auto}.reconnecting{position:sticky;bottom:1em;background:#380a39;color:#926893;padding:1em;z-index:10;border-radius:4px;text-align:center}.settings{display:flex}.server-info{border:1px solid #0089ff;padding:0 .5em;border-radius:4px;margin:.5em 0}.server-info .server-info-header{display:flex;align-items:center}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2.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-flat-button], a[mat-stroked-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatIconAnchor, selector: "a[mat-icon-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: i9.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "directive", type: i12.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: CommentComponent, selector: "banta-comment", inputs: ["message", "customMenuItems", "showReplyAction", "maxLength", "permissions", "mine", "editing", "genericAvatarUrl", "readonly"], outputs: ["liked", "unliked", "selected", "edited", "deleted", "editStarted", "editEnded", "shared", "userSelected", "usernameSelected", "avatarSelected", "reported", "loaded", "pinned", "unpinned"] }, { kind: "component", type: CommentViewComponent, selector: "banta-comment-view", inputs: ["source", "maxMessages", "maxVisibleMessages", "collapsePins", "newestLast", "holdNewMessages", "showEmptyState", "allowReplies", "enableHoldOnClick", "enableHoldOnScroll", "customMenuItems", "fixedHeight", "selectedMessage", "genericAvatarUrl"], outputs: ["userSelected", "reported", "liked", "unliked", "pinned", "unpinned", "usernameSelected", "avatarSelected", "shared", "deleted", "selected", "messageEdited", "sortOrderChanged", "filterModeChanged"] }, { kind: "component", type: CommentFieldComponent, selector: "banta-comment-field", inputs: ["source", "user", "canComment", "signInState", "allowAttachments", "transientMessage", "sendLabel", "signingInLabel", "sendingLabel", "label", "permissionDeniedLabel", "signInLabel", "maxLength", "placeholder", "shouldInterceptMessageSend", "hashtags", "participants", "genericAvatarUrl", "url", "submit", "readonly", "allowServerInfoRequest"], outputs: ["signInSelected", "editAvatarSelected", "focusChange", "textChanged", "serverInfoRequested", "reconnectRequested", "permissionDeniedError"] }, { kind: "pipe", type: i1.JsonPipe, name: "json" }] }); }
9567
9674
  }
9568
9675
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: BantaCommentsComponent, decorators: [{
9569
9676
  type: Component,
9570
- args: [{ selector: 'banta-comments', template: "<ng-container *ngIf=\"loading\">\r\n <div class=\"loading-screen\" [class.visible]=\"showLoadingScreen\">\r\n <h1>{{loadingTitle}}</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 [maxLength]=\"maxCommentLength\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n [readonly]=\"source?.readonly\"\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)=\"toggleSelectedMessage(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 class=\"replies\"\r\n #threadView\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 [customMenuItems]=\"customMenuItems\"\r\n ></banta-comment-view>\r\n\r\n <banta-comment-field\r\n [url]=\"url\"\r\n [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [signingInLabel]=\"signingInLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n [readonly]=\"source?.readonly\"\r\n (signInSelected)=\"showSignIn()\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n [source]=\"selectedMessageThread\"\r\n [maxLength]=\"maxCommentLength\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInState]=\"source?.signInState\"\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 [url]=\"url\"\r\n [source]=\"source\"\r\n [user]=\"user\"\r\n [sendLabel]=\"sendLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [signingInLabel]=\"signingInLabel\"\r\n [signInLabel]=\"signInLabel\"\r\n [signInState]=\"source?.signInState\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n [label]=\"postCommentLabel\"\r\n [maxLength]=\"maxCommentLength\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [submit]=\"sendMessage\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n [readonly]=\"source?.readonly\"\r\n [allowServerInfoRequest]=\"allowServerInfoRequest\"\r\n (serverInfoRequested)=\"showServerInfo()\"\r\n (reconnectRequested)=\"reconnect()\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n (signInSelected)=\"showSignIn()\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n >\r\n \r\n </banta-comment-field>\r\n\r\n @if (serverInfoVisible) {\r\n <div class=\"server-info\">\r\n <div class=\"server-info-header\">\r\n Server Info\r\n <div class=\"spacer\"></div>\r\n <button mat-icon-button matTooltip=\"Reload\" (click)=\"showServerInfo()\">\r\n <mat-icon>refresh</mat-icon>\r\n </button>\r\n <button mat-icon-button matTooltip=\"Hide\" (click)=\"serverInfoVisible = false\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n @if (serverInfoLoading) {\r\n <mat-spinner />\r\n } @else {\r\n <pre>{{ serverInfo | json }}</pre>\r\n }\r\n </div>\r\n }\r\n <mat-menu #filterMenu=\"matMenu\">\r\n <button mat-menu-item *ngFor=\"let filter of filterModes\" (click)=\"filterMode = filter\">\r\n {{filterModeLabels[filter]}}\r\n </button>\r\n </mat-menu>\r\n <mat-menu #sortMenu=\"matMenu\">\r\n <button mat-menu-item *ngFor=\"let sort of sortOrders\" (click)=\"sortOrder = sort\">\r\n {{sortOrderLabels[sort]}}\r\n </button>\r\n </mat-menu>\r\n\r\n <div class=\"settings\">\r\n <button mat-button [matMenuTriggerFor]=\"filterMenu\">\r\n <mat-icon>filter_list</mat-icon>\r\n {{filterModeLabels[filterMode]}}\r\n </button>\r\n <button mat-button [matMenuTriggerFor]=\"sortMenu\">\r\n <mat-icon>sort</mat-icon>\r\n {{sortOrderLabels[sortOrder]}}\r\n </button>\r\n </div>\r\n\r\n <div class=\"loading-comment\" *ngIf=\"loadingSharedComment\">\r\n <h1>Loading the comment you linked to...</h1>\r\n <mat-spinner [diameter]=\"300\" [strokeWidth]=\"2\"></mat-spinner>\r\n <p>\r\n If there are a lot of comments, this might take awhile!\r\n </p>\r\n </div>\r\n <div class=\"loading-comment\" *ngIf=\"!loadingSharedComment && lastSharedCommentID\">\r\n <ng-container *ngIf=\"sharedCommentMissing\">\r\n\r\n <a class=\"close\" mat-icon-button matTooltip=\"Close this notice\" href=\"javascript:;\" (click)=\"lastSharedCommentID = null\">\r\n <mat-icon>close</mat-icon>\r\n </a>\r\n\r\n <h1>\r\n <mat-icon>error</mat-icon>\r\n Uh oh!\r\n </h1>\r\n\r\n <p>The comment you linked to can't be found! It may have been removed.</p>\r\n </ng-container>\r\n <ng-container *ngIf=\"!sharedCommentMissing\">\r\n <a class=\"close\" mat-icon-button matTooltip=\"Close this notice\" href=\"javascript:;\" (click)=\"lastSharedCommentID = null\">\r\n <mat-icon>close</mat-icon>\r\n </a>\r\n <button mat-button (click)=\"navigateToSharedComment(lastSharedCommentID)\">\r\n <mat-icon>move_down</mat-icon> Jump to shared comment\r\n </button>\r\n </ng-container>\r\n </div>\r\n\r\n <banta-comment-view\r\n #commentView\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 [customMenuItems]=\"customMenuItems\"\r\n [holdNewMessages]=\"selectedMessageVisible\"\r\n (userSelected)=\"selectMessageUser($event)\"\r\n (sortOrderChanged)=\"sortOrder = $event\"\r\n (filterModeChanged)=\"filterMode = $event\"\r\n (selected)=\"toggleSelectedMessage($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 [enableHoldOnClick]=\"false\"\r\n [holdNewMessages]=\"replyFieldFocused\"\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 [url]=\"url\"\r\n [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [signingInLabel]=\"signingInLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n (signInSelected)=\"showSignIn()\"\r\n [maxLength]=\"maxCommentLength\"\r\n [source]=\"selectedMessageThread\"\r\n [signInState]=\"source?.signInState\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInLabel]=\"signInLabel\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n [readonly]=\"source?.readonly\"\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 (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n (focusChange)=\"replyFieldFocused = $event\"\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 <div class=\"reconnecting\" *ngIf=\"connectionState === 'lost'\">\r\n <strong>Connection to Live Comments lost.</strong> Reconnecting...\r\n </div>\r\n</ng-container>\r\n", styles: [":host{display:flex;flex-direction:column}@keyframes select-comment{0%{transform:scale(1.15)}to{transform:scale(1)}}.focused{animation-name:select-comment;animation-duration:.4s;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:.4s opacity ease-in-out}banta-comment-view.faded{opacity:.25}.loading{display:block;width:fit-content;margin:0 auto;min-height:16em}.main.hidden{display:none}.loading-screen{text-align:center;opacity:0;transition:.25s ease-in-out opacity}.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:.25s ease-in-out opacity;width:500px;max-width:100%;margin:0 auto}.loading-screen .loading-message.visible{opacity:1}banta-comment-sort{margin:0 0 0 auto;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%}.loading-comment{z-index:100;border:1px solid #333;background:#000;color:#fff;padding:1em;border-radius:4px;text-align:center;position:relative}.loading-comment a.close{position:absolute;top:1em;right:1em}.loading-comment h1{font-weight:100;text-align:center}.loading-comment mat-spinner{margin:0 auto}.reconnecting{position:sticky;bottom:1em;background:#380a39;color:#926893;padding:1em;z-index:10;border-radius:4px;text-align:center}.settings{display:flex}.server-info{border:1px solid #0089ff;padding:0 .5em;border-radius:4px;margin:.5em 0}.server-info .server-info-header{display:flex;align-items:center}\n"] }]
9677
+ args: [{ selector: 'banta-comments', template: "<ng-container *ngIf=\"loading\">\r\n <div class=\"loading-screen\" [class.visible]=\"showLoadingScreen\">\r\n <h1>{{loadingTitle}}</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 [maxLength]=\"maxCommentLength\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n [readonly]=\"source?.readonly\"\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 (pinned)=\"pinMessage(source, selectedMessage, $event.options)\"\r\n (unpinned)=\"unpinMessage(source, selectedMessage)\"\r\n (selected)=\"toggleSelectedMessage(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 class=\"replies\"\r\n #threadView\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 (pinned)=\"pinMessage(selectedMessageThread, $event.message, $event.options)\"\r\n (unpinned)=\"unpinMessage(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 [customMenuItems]=\"customMenuItems\"\r\n ></banta-comment-view>\r\n\r\n <banta-comment-field\r\n [url]=\"url\"\r\n [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [signingInLabel]=\"signingInLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n [readonly]=\"source?.readonly\"\r\n (signInSelected)=\"showSignIn()\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n [source]=\"selectedMessageThread\"\r\n [maxLength]=\"maxCommentLength\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInState]=\"source?.signInState\"\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 [url]=\"url\"\r\n [source]=\"source\"\r\n [user]=\"user\"\r\n [sendLabel]=\"sendLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [signingInLabel]=\"signingInLabel\"\r\n [signInLabel]=\"signInLabel\"\r\n [signInState]=\"source?.signInState\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n [label]=\"postCommentLabel\"\r\n [maxLength]=\"maxCommentLength\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [submit]=\"sendMessage\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n [readonly]=\"source?.readonly\"\r\n [allowServerInfoRequest]=\"allowServerInfoRequest\"\r\n (serverInfoRequested)=\"showServerInfo()\"\r\n (reconnectRequested)=\"reconnect()\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n (signInSelected)=\"showSignIn()\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n >\r\n \r\n </banta-comment-field>\r\n\r\n @if (serverInfoVisible) {\r\n <div class=\"server-info\">\r\n <div class=\"server-info-header\">\r\n Server Info\r\n <div class=\"spacer\"></div>\r\n <button mat-icon-button matTooltip=\"Reload\" (click)=\"showServerInfo()\">\r\n <mat-icon>refresh</mat-icon>\r\n </button>\r\n <button mat-icon-button matTooltip=\"Hide\" (click)=\"serverInfoVisible = false\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n @if (serverInfoLoading) {\r\n <mat-spinner />\r\n } @else {\r\n <pre>{{ serverInfo | json }}</pre>\r\n }\r\n </div>\r\n }\r\n <mat-menu #filterMenu=\"matMenu\">\r\n <button mat-menu-item *ngFor=\"let filter of filterModes\" (click)=\"filterMode = filter\">\r\n {{filterModeLabels[filter]}}\r\n </button>\r\n </mat-menu>\r\n <mat-menu #sortMenu=\"matMenu\">\r\n <button mat-menu-item *ngFor=\"let sort of sortOrders\" (click)=\"sortOrder = sort\">\r\n {{sortOrderLabels[sort]}}\r\n </button>\r\n </mat-menu>\r\n\r\n <div class=\"settings\">\r\n <button mat-button [matMenuTriggerFor]=\"filterMenu\">\r\n <mat-icon>filter_list</mat-icon>\r\n {{filterModeLabels[filterMode]}}\r\n </button>\r\n <button mat-button [matMenuTriggerFor]=\"sortMenu\">\r\n <mat-icon>sort</mat-icon>\r\n {{sortOrderLabels[sortOrder]}}\r\n </button>\r\n </div>\r\n\r\n <div class=\"loading-comment\" *ngIf=\"loadingSharedComment\">\r\n <h1>Loading the comment you linked to...</h1>\r\n <mat-spinner [diameter]=\"300\" [strokeWidth]=\"2\"></mat-spinner>\r\n <p>\r\n If there are a lot of comments, this might take awhile!\r\n </p>\r\n </div>\r\n <div class=\"loading-comment\" *ngIf=\"!loadingSharedComment && lastSharedCommentID\">\r\n <ng-container *ngIf=\"sharedCommentMissing\">\r\n\r\n <a class=\"close\" mat-icon-button matTooltip=\"Close this notice\" href=\"javascript:;\" (click)=\"lastSharedCommentID = null\">\r\n <mat-icon>close</mat-icon>\r\n </a>\r\n\r\n <h1>\r\n <mat-icon>error</mat-icon>\r\n Uh oh!\r\n </h1>\r\n\r\n <p>The comment you linked to can't be found! It may have been removed.</p>\r\n </ng-container>\r\n <ng-container *ngIf=\"!sharedCommentMissing\">\r\n <a class=\"close\" mat-icon-button matTooltip=\"Close this notice\" href=\"javascript:;\" (click)=\"lastSharedCommentID = null\">\r\n <mat-icon>close</mat-icon>\r\n </a>\r\n <button mat-button (click)=\"navigateToSharedComment(lastSharedCommentID)\">\r\n <mat-icon>move_down</mat-icon> Jump to shared comment\r\n </button>\r\n </ng-container>\r\n </div>\r\n\r\n <banta-comment-view\r\n #commentView\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 [customMenuItems]=\"customMenuItems\"\r\n [holdNewMessages]=\"selectedMessageVisible\"\r\n (userSelected)=\"selectMessageUser($event)\"\r\n (sortOrderChanged)=\"sortOrder = $event\"\r\n (filterModeChanged)=\"filterMode = $event\"\r\n (selected)=\"toggleSelectedMessage($event)\"\r\n (liked)=\"likeMessage(source, $event)\"\r\n (unliked)=\"unlikeMessage(source, $event)\"\r\n (pinned)=\"pinMessage(source, $event.message, $event.options)\"\r\n (unpinned)=\"unpinMessage(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 [enableHoldOnClick]=\"false\"\r\n [holdNewMessages]=\"replyFieldFocused\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (liked)=\"likeMessage(selectedMessageThread, $event)\"\r\n (unliked)=\"unlikeMessage(selectedMessageThread, $event)\"\r\n (pinned)=\"pinMessage(selectedMessageThread, $event.message, $event.options)\"\r\n (unpinned)=\"unpinMessage(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 [url]=\"url\"\r\n [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [signingInLabel]=\"signingInLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n (signInSelected)=\"showSignIn()\"\r\n [maxLength]=\"maxCommentLength\"\r\n [source]=\"selectedMessageThread\"\r\n [signInState]=\"source?.signInState\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInLabel]=\"signInLabel\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n [readonly]=\"source?.readonly\"\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 (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n (focusChange)=\"replyFieldFocused = $event\"\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 <div class=\"reconnecting\" *ngIf=\"connectionState === 'lost'\">\r\n <strong>Connection to Live Comments lost.</strong> Reconnecting...\r\n </div>\r\n</ng-container>\r\n", styles: [":host{display:flex;flex-direction:column}@keyframes select-comment{0%{transform:scale(1.15)}to{transform:scale(1)}}.focused{animation-name:select-comment;animation-duration:.4s;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:.4s opacity ease-in-out}banta-comment-view.faded{opacity:.25}.loading{display:block;width:fit-content;margin:0 auto;min-height:16em}.main.hidden{display:none}.loading-screen{text-align:center;opacity:0;transition:.25s ease-in-out opacity}.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:.25s ease-in-out opacity;width:500px;max-width:100%;margin:0 auto}.loading-screen .loading-message.visible{opacity:1}banta-comment-sort{margin:0 0 0 auto;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%}.loading-comment{z-index:100;border:1px solid #333;background:#000;color:#fff;padding:1em;border-radius:4px;text-align:center;position:relative}.loading-comment a.close{position:absolute;top:1em;right:1em}.loading-comment h1{font-weight:100;text-align:center}.loading-comment mat-spinner{margin:0 auto}.reconnecting{position:sticky;bottom:1em;background:#380a39;color:#926893;padding:1em;z-index:10;border-radius:4px;text-align:center}.settings{display:flex}.server-info{border:1px solid #0089ff;padding:0 .5em;border-radius:4px;margin:.5em 0}.server-info .server-info-header{display:flex;align-items:center}\n"] }]
9571
9678
  }], ctorParameters: () => [{ type: ChatBackendBase }, { type: i0.ElementRef }, { type: i2$2.ActivatedRoute }, { type: i3$2.MatSnackBar }, { type: i0.NgZone }], propDecorators: { isMobileSized: [{
9572
9679
  type: HostBinding,
9573
9680
  args: ['class.banta-mobile']
@@ -10127,7 +10234,7 @@ class LiveCommentComponent {
10127
10234
  (reported)="report()"
10128
10235
  (selected)="select()"
10129
10236
  ></banta-comment>
10130
- `, isInline: true, styles: [""], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: CommentComponent, selector: "banta-comment", inputs: ["message", "customMenuItems", "showReplyAction", "maxLength", "permissions", "mine", "editing", "genericAvatarUrl", "readonly"], outputs: ["liked", "unliked", "selected", "edited", "deleted", "editStarted", "editEnded", "shared", "userSelected", "usernameSelected", "avatarSelected", "reported", "loaded"] }] }); }
10237
+ `, isInline: true, styles: [""], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: CommentComponent, selector: "banta-comment", inputs: ["message", "customMenuItems", "showReplyAction", "maxLength", "permissions", "mine", "editing", "genericAvatarUrl", "readonly"], outputs: ["liked", "unliked", "selected", "edited", "deleted", "editStarted", "editEnded", "shared", "userSelected", "usernameSelected", "avatarSelected", "reported", "loaded", "pinned", "unpinned"] }] }); }
10131
10238
  }
10132
10239
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: LiveCommentComponent, decorators: [{
10133
10240
  type: Component,
@@ -10481,7 +10588,7 @@ class BantaComponent {
10481
10588
  this.showAux(`Report message from @${message.user.username}`, 'report');
10482
10589
  }
10483
10590
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: BantaComponent, deps: [{ token: ChatBackendBase }, { token: i2$3.MatDialog }], target: i0.ɵɵFactoryTarget.Component }); }
10484
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: BantaComponent, selector: "banta", inputs: { topicID: "topicID", chatLabel: "chatLabel", commentsLabel: "commentsLabel", allowServerInfoRequest: "allowServerInfoRequest" }, outputs: { signInSelected: "signInSelected" }, host: { properties: { "class.point-focus": "this.hasPoint" } }, viewQueries: [{ propertyName: "firehose", first: true, predicate: ["firehose"], descendants: true, static: true }], ngImport: i0, template: "\r\n<mat-menu #userMenu=\"matMenu\">\r\n <ng-container *ngIf=\"currentUser\">\r\n <button [disabled]=\"true\" mat-menu-item>{{currentUser.displayName}} (&#64;{{currentUser.username}})</button>\r\n <button mat-menu-item (click)=\"signOut()\">Sign Out</button>\r\n </ng-container>\r\n <ng-container *ngIf=\"!currentUser\">\r\n <button mat-menu-item>Sign In</button>\r\n </ng-container>\r\n <button mat-menu-item>Help</button>\r\n</mat-menu>\r\n\r\n<div class=\"tabs\">\r\n <div>\r\n <a mat-button (click)=\"mobileFocus = 'chat'\">{{chatLabel}}</a>\r\n <a mat-button (click)=\"mobileFocus = 'comments'\">{{commentsLabel}}</a>\r\n </div>\r\n <div class=\"spacer\"></div>\r\n <div>\r\n <ng-container *ngIf=\"currentUser\">\r\n <button mat-button [matMenuTriggerFor]=\"userMenu\">\r\n &#64;{{currentUser.username}}\r\n </button>\r\n <button mat-icon-button (click)=\"showNotifications()\">\r\n <mat-icon>notification_important</mat-icon>\r\n </button>\r\n </ng-container>\r\n \r\n <button mat-button *ngIf=\"!currentUser\" (click)=\"showSignIn()\">\r\n Sign In\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<div class=\"firehose\" [class.focus]=\"mobileFocus === 'chat'\">\r\n <header>\r\n <div>\r\n <label (click)=\"mobileFocus = 'chat'\">{{chatLabel}}</label>\r\n <div class=\"spacer\"></div>\r\n\r\n <ng-container *ngIf=\"currentUser\">\r\n <button mat-button [matMenuTriggerFor]=\"userMenu\">\r\n &#64;{{currentUser.username}}\r\n </button>\r\n <button mat-icon-button (click)=\"showNotifications()\">\r\n <mat-icon>notification_important</mat-icon>\r\n </button>\r\n </ng-container>\r\n \r\n <button mat-button *ngIf=\"!currentUser\" (click)=\"showSignIn()\">\r\n Sign In\r\n </button>\r\n </div>\r\n </header>\r\n <banta-chat \r\n #firehose\r\n [source]=\"firehoseSource\"\r\n (signInSelected)=\"showSignIn()\"\r\n (upvoted)=\"upvoteMessage($event)\"\r\n (userSelected)=\"showProfile($event.user)\"\r\n (reported)=\"reportMessage($event)\"\r\n ></banta-chat>\r\n</div>\r\n\r\n<div class=\"aux\" [class.focus]=\"mobileFocus === 'aux'\" [class.open]=\"auxOpen\">\r\n <header>\r\n <div>\r\n <label>{{auxTitle}}</label>\r\n <div class=\"spacer\"></div>\r\n <button mat-icon-button (click)=\"auxOpen = false\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n </header>\r\n <div class=\"aux-contents\">\r\n <ng-container *ngIf=\"auxMode === 'profile'\">\r\n <ng-container *ngIf=\"profileUser\">\r\n\r\n <div>\r\n <strong style=\"font-size: 125%;\">\r\n {{profileUser.displayName}}\r\n </strong>\r\n &#64;{{profileUser.username}}\r\n </div>\r\n\r\n <br/>\r\n <strong>Top Messages</strong>\r\n\r\n <div>\r\n <em>Not yet available</em>\r\n </div>\r\n\r\n <br/>\r\n <strong>Recent Messages</strong>\r\n\r\n <div>\r\n <em>Not yet available</em>\r\n </div>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"auxMode === 'report'\">\r\n <p>Are you sure you want to report this message?</p>\r\n\r\n <banta-live-message [message]=\"reportedMessage\"></banta-live-message>\r\n\r\n <div style=\"text-align: center;\">\r\n <button mat-raised-button color=\"primary\" (click)=\"sendReport(reportedMessage)\">Yes, Report</button>\r\n &nbsp;\r\n <button mat-raised-button color=\"secondary\" (click)=\"auxOpen = false\">No, Cancel</button>\r\n </div>\r\n\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"auxMode === 'notifications'\">\r\n\r\n <div *ngIf=\"!notifications || notifications.length === 0\">\r\n <em>You do not have any notifications yet</em>\r\n </div>\r\n \r\n <div class=\"notifications\">\r\n <div class=\"notification\" *ngFor=\"let notif of notifications\">\r\n <div>\r\n <ng-container *ngIf=\"notif.type === 'upvote'\">\r\n &#64;{{notif.message?.user?.username}} upvoted your post\r\n \r\n <banta-live-message\r\n [message]=\"notif.message\"\r\n (upvoted)=\"upvoteMessage(notif.message)\"\r\n (reported)=\"reportMessage(notif.message)\"\r\n (selected)=\"goToMessage(notif.message)\">\r\n </banta-live-message>\r\n\r\n </ng-container>\r\n <ng-container *ngIf=\"notif.type === 'notice'\">\r\n <div>\r\n {{notif.message}}\r\n </div>\r\n <a mat-button target=\"_blank\" href=\"{{notif.actionUrl}}\">\r\n {{notif.actionLabel}}\r\n </a>\r\n </ng-container>\r\n <ng-container *ngIf=\"notif.type === 'mention'\">\r\n You were mentioned by &#64;{{notif.message?.user?.username}}\r\n\r\n <banta-live-message\r\n [message]=\"notif.message\"\r\n (upvoted)=\"upvoteMessage(notif.message)\"\r\n (reported)=\"reportMessage(notif.message)\"\r\n (selected)=\"goToMessage(notif.message)\">\r\n </banta-live-message>\r\n\r\n </ng-container>\r\n <ng-container *ngIf=\"notif.type === 'reply'\">\r\n &#64;{{notif.replyMessage?.user?.username}} replied to your post\r\n \r\n <banta-live-message\r\n [message]=\"notif.replyMessage\"\r\n (upvoted)=\"upvoteMessage(notif.replyMessage)\"\r\n (reported)=\"reportMessage(notif.replyMessage)\"\r\n (selected)=\"goToMessage(notif.replyMessage)\">\r\n </banta-live-message>\r\n </ng-container>\r\n </div>\r\n\r\n <banta-timestamp [value]=\"notif.sentAt\"></banta-timestamp>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n</div>\r\n<div class=\"points\" [class.focus]=\"mobileFocus === 'points'\">\r\n <header>\r\n <div>\r\n <label>{{commentsLabel}}</label>\r\n </div>\r\n </header>\r\n <div class=\"point-focus\">\r\n <div class=\"actions\">\r\n <button mat-button (click)=\"pointUnfocus()\">\r\n <mat-icon>arrow_back</mat-icon>\r\n Back\r\n </button>\r\n\r\n <div class=\"spacer\"></div>\r\n \r\n <ng-container *ngIf=\"pointOpen\">\r\n <div class=\"counted-action\">\r\n <div class=\"count-indicator\"> \r\n {{pointOpen.likes}}\r\n </div>\r\n <button mat-icon-button>\r\n <mat-icon>thumb_up</mat-icon>\r\n </button>\r\n </div>\r\n\r\n </ng-container>\r\n </div>\r\n\r\n <div *ngIf=\"!pointSubChat\">\r\n Error: No subchat\r\n </div>\r\n \r\n <banta-comment-view\r\n class=\"subcomments\"\r\n *ngIf=\"pointSubChat\"\r\n [newestLast]=\"true\"\r\n [allowReplies]=\"false\"\r\n [source]=\"pointSubChat\"\r\n (upvoted)=\"upvoteMessage($event)\"\r\n (reported)=\"reportMessage($event)\"\r\n (userSelected)=\"showProfile($event.user)\"\r\n >\r\n \r\n <banta-comment\r\n class=\"focused-comment\"\r\n data-before\r\n *ngIf=\"pointOpen\"\r\n [showReplyAction]=\"false\"\r\n [message]=\"pointOpen\"\r\n [readonly]=\"pointSubChat?.readonly\"\r\n (upvoted)=\"upvoteMessage(pointOpen)\"\r\n (userSelected)=\"showProfile(pointOpen.user)\"\r\n (reported)=\"reportMessage(pointOpen)\"\r\n ></banta-comment>\r\n \r\n <div class=\"message reply\">\r\n Reply:\r\n <form class=\"new-message\" (submit)=\"sendPointSubMessage()\">\r\n <textarea \r\n name=\"message\" \r\n (keydown)=\"newPointSubMessageKeyDown($event)\"\r\n [(ngModel)]=\"newPointSubMessage.message\"></textarea>\r\n \r\n <div class=\"actions\">\r\n <button [disabled]=\"!newPointSubMessage.message\" \r\n mat-raised-button color=\"primary\">Send</button>\r\n </div>\r\n </form>\r\n </div>\r\n </banta-comment-view>\r\n </div>\r\n <div class=\"points-section\">\r\n <banta-comments\r\n [source]=\"pointSource\"\r\n [allowServerInfoRequest]=\"allowServerInfoRequest\"\r\n (signInSelected)=\"showSignIn()\"\r\n (upvoted)=\"upvoteMessage($event)\"\r\n (reported)=\"reportMessage($event)\"\r\n (selected)=\"goToMessage($event)\"\r\n (userSelected)=\"showProfile($event.user)\"\r\n ></banta-comments>\r\n </div>\r\n</div>", styles: [":host{display:flex;flex-direction:row;padding:.5em;height:40em;position:relative}.counted-action{display:flex;align-items:center}.count-indicator{font-size:9pt;padding:0 3px;border-radius:3px;border:1px solid #333}header{position:relative;margin-bottom:1em}header div{display:flex;align-items:center;height:30px}header button{color:#666}header label{text-transform:uppercase;z-index:1;font-size:12pt;letter-spacing:2px;font-weight:100;color:#333;margin:0 auto 0 0;display:block;width:fit-content;position:relative;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis}header:after{content:\"\";border:1px solid;border-color:#ccc;height:0px;width:100%;display:block;position:relative;z-index:0}.points{width:33%;max-width:50em;display:flex;flex-direction:column}:host.point-focus .points{width:66%;max-width:50em}:host.point-focus .points .points-section{opacity:0;pointer-events:none}:host.point-focus .points .point-focus{opacity:1;pointer-events:initial}:host.point-focus .points .point-focus .actions{display:flex}banta-comments{flex-grow:1}.points{width:33%;margin-left:.5em;font-size:12pt;flex-shrink:0;max-width:30em;transition:.2s width ease-in,.2s max-width ease-in;position:relative}.points .points-section{flex-grow:1;display:flex;flex-direction:column;opacity:1;transition:.2s opacity ease-in;z-index:2}.points .point-focus{position:absolute;width:100%;inset:1.75em 0 0;padding:.5em;opacity:0;transition:.2s opacity ease-in;flex-grow:1;display:flex;flex-direction:column}.firehose{flex-grow:1;font-size:10pt;display:flex;flex-direction:column}form{display:flex;padding:.5em 0;align-items:center}form textarea{font-size:14pt;background:#000;color:#fff;border:1px solid #333;min-height:6em;width:100%}form input[type=text]{background:#000;color:#fff;border:1px solid #333;width:100%;height:1em}form .actions{margin-left:1em}form button{display:block;margin:0 0 0 auto}.subcomments ::ng-deep banta-comment{font-size:10pt}.subcomments ::ng-deep banta-comment.focused-comment{background:#001321;color:#fff;font-size:12pt}.aux{width:0px;min-width:0px;overflow-x:hidden;transition:.4s width ease-out,.4s min-width ease-out;display:flex;flex-direction:column}.aux.open{width:30em;min-width:18em}.aux .aux-contents{width:30em;min-width:10em;max-width:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;flex-grow:1}.notifications .notification{border-bottom:1px solid #333;padding:1em}.notifications .notification banta-timestamp{display:block;text-align:right;font-size:9pt;color:#999}.message.reply{padding:1em}.tabs{display:none}@media (max-width: 1015px){:host{flex-direction:column}.tabs{display:flex;position:absolute;top:0;left:0;right:0;width:100%;z-index:10;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);background:#00000080}.points{width:100%;max-width:100%;margin-left:0}header{display:none}:host.point-focus .points{width:100%;max-width:100%}.aux{width:100%;min-width:initial;max-width:100%}.points,.firehose,.aux{position:absolute;inset:2em 0 0;z-index:0;background:#000}.points.focus,.firehose.focus,.aux.focus{z-index:2}}:host-context(.mat-dark-theme) :host{background:#090909;color:#fff}:host-context(.mat-dark-theme) form textarea{background:#ccc;color:#333}:host-context(.mat-dark-theme) header:after{border-color:#222}:host-context(.mat-dark-theme) header label{color:#aaa}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3$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: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: TimestampComponent, selector: "banta-timestamp", inputs: ["value"] }, { kind: "component", type: CommentComponent, selector: "banta-comment", inputs: ["message", "customMenuItems", "showReplyAction", "maxLength", "permissions", "mine", "editing", "genericAvatarUrl", "readonly"], outputs: ["liked", "unliked", "selected", "edited", "deleted", "editStarted", "editEnded", "shared", "userSelected", "usernameSelected", "avatarSelected", "reported", "loaded"] }, { kind: "component", type: CommentViewComponent, selector: "banta-comment-view", inputs: ["source", "maxMessages", "maxVisibleMessages", "newestLast", "holdNewMessages", "showEmptyState", "allowReplies", "enableHoldOnClick", "enableHoldOnScroll", "customMenuItems", "fixedHeight", "selectedMessage", "genericAvatarUrl"], outputs: ["userSelected", "reported", "liked", "unliked", "usernameSelected", "avatarSelected", "shared", "deleted", "selected", "messageEdited", "sortOrderChanged", "filterModeChanged"] }, { kind: "component", type: BantaCommentsComponent, selector: "banta-comments", inputs: ["customMenuItems", "url", "maxCommentLength", "loadingMessages", "useInlineReplies", "signInLabel", "sendLabel", "signingInLabel", "replyLabel", "sendingLabel", "permissionDeniedLabel", "postCommentLabel", "postReplyLabel", "allowAttachments", "allowServerInfoRequest", "fixedHeight", "maxMessages", "maxVisibleMessages", "genericAvatarUrl", "shouldInterceptMessageSend", "participants", "source", "hashtags", "topicID", "sortOrder", "filterMode", "initialMessageCount", "metadata"], outputs: ["signInSelected", "editAvatarSelected", "permissionDeniedError", "upvoted", "reported", "selected", "userSelected", "usernameSelected", "avatarSelected", "shared", "reconnectRequested"] }, { kind: "component", type: BantaChatComponent, selector: "banta-chat", inputs: ["shouldInterceptMessageSend", "url", "source", "topicID", "metadata", "signInLabel", "sendLabel", "permissionDeniedLabel", "messageFieldPlaceholder", "emptyLabel"], outputs: ["selected", "reported", "upvoted", "userSelected", "permissionDeniedError", "signInSelected", "received"] }, { kind: "component", type: i2.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-flat-button], a[mat-stroked-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: LiveMessageComponent, selector: "banta-live-message", inputs: ["message"], outputs: ["upvoted", "reported", "selected"] }] }); }
10591
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.9", type: BantaComponent, selector: "banta", inputs: { topicID: "topicID", chatLabel: "chatLabel", commentsLabel: "commentsLabel", allowServerInfoRequest: "allowServerInfoRequest" }, outputs: { signInSelected: "signInSelected" }, host: { properties: { "class.point-focus": "this.hasPoint" } }, viewQueries: [{ propertyName: "firehose", first: true, predicate: ["firehose"], descendants: true, static: true }], ngImport: i0, template: "\r\n<mat-menu #userMenu=\"matMenu\">\r\n <ng-container *ngIf=\"currentUser\">\r\n <button [disabled]=\"true\" mat-menu-item>{{currentUser.displayName}} (&#64;{{currentUser.username}})</button>\r\n <button mat-menu-item (click)=\"signOut()\">Sign Out</button>\r\n </ng-container>\r\n <ng-container *ngIf=\"!currentUser\">\r\n <button mat-menu-item>Sign In</button>\r\n </ng-container>\r\n <button mat-menu-item>Help</button>\r\n</mat-menu>\r\n\r\n<div class=\"tabs\">\r\n <div>\r\n <a mat-button (click)=\"mobileFocus = 'chat'\">{{chatLabel}}</a>\r\n <a mat-button (click)=\"mobileFocus = 'comments'\">{{commentsLabel}}</a>\r\n </div>\r\n <div class=\"spacer\"></div>\r\n <div>\r\n <ng-container *ngIf=\"currentUser\">\r\n <button mat-button [matMenuTriggerFor]=\"userMenu\">\r\n &#64;{{currentUser.username}}\r\n </button>\r\n <button mat-icon-button (click)=\"showNotifications()\">\r\n <mat-icon>notification_important</mat-icon>\r\n </button>\r\n </ng-container>\r\n \r\n <button mat-button *ngIf=\"!currentUser\" (click)=\"showSignIn()\">\r\n Sign In\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<div class=\"firehose\" [class.focus]=\"mobileFocus === 'chat'\">\r\n <header>\r\n <div>\r\n <label (click)=\"mobileFocus = 'chat'\">{{chatLabel}}</label>\r\n <div class=\"spacer\"></div>\r\n\r\n <ng-container *ngIf=\"currentUser\">\r\n <button mat-button [matMenuTriggerFor]=\"userMenu\">\r\n &#64;{{currentUser.username}}\r\n </button>\r\n <button mat-icon-button (click)=\"showNotifications()\">\r\n <mat-icon>notification_important</mat-icon>\r\n </button>\r\n </ng-container>\r\n \r\n <button mat-button *ngIf=\"!currentUser\" (click)=\"showSignIn()\">\r\n Sign In\r\n </button>\r\n </div>\r\n </header>\r\n <banta-chat \r\n #firehose\r\n [source]=\"firehoseSource\"\r\n (signInSelected)=\"showSignIn()\"\r\n (upvoted)=\"upvoteMessage($event)\"\r\n (userSelected)=\"showProfile($event.user)\"\r\n (reported)=\"reportMessage($event)\"\r\n ></banta-chat>\r\n</div>\r\n\r\n<div class=\"aux\" [class.focus]=\"mobileFocus === 'aux'\" [class.open]=\"auxOpen\">\r\n <header>\r\n <div>\r\n <label>{{auxTitle}}</label>\r\n <div class=\"spacer\"></div>\r\n <button mat-icon-button (click)=\"auxOpen = false\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n </header>\r\n <div class=\"aux-contents\">\r\n <ng-container *ngIf=\"auxMode === 'profile'\">\r\n <ng-container *ngIf=\"profileUser\">\r\n\r\n <div>\r\n <strong style=\"font-size: 125%;\">\r\n {{profileUser.displayName}}\r\n </strong>\r\n &#64;{{profileUser.username}}\r\n </div>\r\n\r\n <br/>\r\n <strong>Top Messages</strong>\r\n\r\n <div>\r\n <em>Not yet available</em>\r\n </div>\r\n\r\n <br/>\r\n <strong>Recent Messages</strong>\r\n\r\n <div>\r\n <em>Not yet available</em>\r\n </div>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"auxMode === 'report'\">\r\n <p>Are you sure you want to report this message?</p>\r\n\r\n <banta-live-message [message]=\"reportedMessage\"></banta-live-message>\r\n\r\n <div style=\"text-align: center;\">\r\n <button mat-raised-button color=\"primary\" (click)=\"sendReport(reportedMessage)\">Yes, Report</button>\r\n &nbsp;\r\n <button mat-raised-button color=\"secondary\" (click)=\"auxOpen = false\">No, Cancel</button>\r\n </div>\r\n\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"auxMode === 'notifications'\">\r\n\r\n <div *ngIf=\"!notifications || notifications.length === 0\">\r\n <em>You do not have any notifications yet</em>\r\n </div>\r\n \r\n <div class=\"notifications\">\r\n <div class=\"notification\" *ngFor=\"let notif of notifications\">\r\n <div>\r\n <ng-container *ngIf=\"notif.type === 'upvote'\">\r\n &#64;{{notif.message?.user?.username}} upvoted your post\r\n \r\n <banta-live-message\r\n [message]=\"notif.message\"\r\n (upvoted)=\"upvoteMessage(notif.message)\"\r\n (reported)=\"reportMessage(notif.message)\"\r\n (selected)=\"goToMessage(notif.message)\">\r\n </banta-live-message>\r\n\r\n </ng-container>\r\n <ng-container *ngIf=\"notif.type === 'notice'\">\r\n <div>\r\n {{notif.message}}\r\n </div>\r\n <a mat-button target=\"_blank\" href=\"{{notif.actionUrl}}\">\r\n {{notif.actionLabel}}\r\n </a>\r\n </ng-container>\r\n <ng-container *ngIf=\"notif.type === 'mention'\">\r\n You were mentioned by &#64;{{notif.message?.user?.username}}\r\n\r\n <banta-live-message\r\n [message]=\"notif.message\"\r\n (upvoted)=\"upvoteMessage(notif.message)\"\r\n (reported)=\"reportMessage(notif.message)\"\r\n (selected)=\"goToMessage(notif.message)\">\r\n </banta-live-message>\r\n\r\n </ng-container>\r\n <ng-container *ngIf=\"notif.type === 'reply'\">\r\n &#64;{{notif.replyMessage?.user?.username}} replied to your post\r\n \r\n <banta-live-message\r\n [message]=\"notif.replyMessage\"\r\n (upvoted)=\"upvoteMessage(notif.replyMessage)\"\r\n (reported)=\"reportMessage(notif.replyMessage)\"\r\n (selected)=\"goToMessage(notif.replyMessage)\">\r\n </banta-live-message>\r\n </ng-container>\r\n </div>\r\n\r\n <banta-timestamp [value]=\"notif.sentAt\"></banta-timestamp>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n</div>\r\n<div class=\"points\" [class.focus]=\"mobileFocus === 'points'\">\r\n <header>\r\n <div>\r\n <label>{{commentsLabel}}</label>\r\n </div>\r\n </header>\r\n <div class=\"point-focus\">\r\n <div class=\"actions\">\r\n <button mat-button (click)=\"pointUnfocus()\">\r\n <mat-icon>arrow_back</mat-icon>\r\n Back\r\n </button>\r\n\r\n <div class=\"spacer\"></div>\r\n \r\n <ng-container *ngIf=\"pointOpen\">\r\n <div class=\"counted-action\">\r\n <div class=\"count-indicator\"> \r\n {{pointOpen.likes}}\r\n </div>\r\n <button mat-icon-button>\r\n <mat-icon>thumb_up</mat-icon>\r\n </button>\r\n </div>\r\n\r\n </ng-container>\r\n </div>\r\n\r\n <div *ngIf=\"!pointSubChat\">\r\n Error: No subchat\r\n </div>\r\n \r\n <banta-comment-view\r\n class=\"subcomments\"\r\n *ngIf=\"pointSubChat\"\r\n [newestLast]=\"true\"\r\n [allowReplies]=\"false\"\r\n [source]=\"pointSubChat\"\r\n (upvoted)=\"upvoteMessage($event)\"\r\n (reported)=\"reportMessage($event)\"\r\n (userSelected)=\"showProfile($event.user)\"\r\n >\r\n \r\n <banta-comment\r\n class=\"focused-comment\"\r\n data-before\r\n *ngIf=\"pointOpen\"\r\n [showReplyAction]=\"false\"\r\n [message]=\"pointOpen\"\r\n [readonly]=\"pointSubChat?.readonly\"\r\n (upvoted)=\"upvoteMessage(pointOpen)\"\r\n (userSelected)=\"showProfile(pointOpen.user)\"\r\n (reported)=\"reportMessage(pointOpen)\"\r\n ></banta-comment>\r\n \r\n <div class=\"message reply\">\r\n Reply:\r\n <form class=\"new-message\" (submit)=\"sendPointSubMessage()\">\r\n <textarea \r\n name=\"message\" \r\n (keydown)=\"newPointSubMessageKeyDown($event)\"\r\n [(ngModel)]=\"newPointSubMessage.message\"></textarea>\r\n \r\n <div class=\"actions\">\r\n <button [disabled]=\"!newPointSubMessage.message\" \r\n mat-raised-button color=\"primary\">Send</button>\r\n </div>\r\n </form>\r\n </div>\r\n </banta-comment-view>\r\n </div>\r\n <div class=\"points-section\">\r\n <banta-comments\r\n [source]=\"pointSource\"\r\n [allowServerInfoRequest]=\"allowServerInfoRequest\"\r\n (signInSelected)=\"showSignIn()\"\r\n (upvoted)=\"upvoteMessage($event)\"\r\n (reported)=\"reportMessage($event)\"\r\n (selected)=\"goToMessage($event)\"\r\n (userSelected)=\"showProfile($event.user)\"\r\n ></banta-comments>\r\n </div>\r\n</div>", styles: [":host{display:flex;flex-direction:row;padding:.5em;height:40em;position:relative}.counted-action{display:flex;align-items:center}.count-indicator{font-size:9pt;padding:0 3px;border-radius:3px;border:1px solid #333}header{position:relative;margin-bottom:1em}header div{display:flex;align-items:center;height:30px}header button{color:#666}header label{text-transform:uppercase;z-index:1;font-size:12pt;letter-spacing:2px;font-weight:100;color:#333;margin:0 auto 0 0;display:block;width:fit-content;position:relative;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis}header:after{content:\"\";border:1px solid;border-color:#ccc;height:0px;width:100%;display:block;position:relative;z-index:0}.points{width:33%;max-width:50em;display:flex;flex-direction:column}:host.point-focus .points{width:66%;max-width:50em}:host.point-focus .points .points-section{opacity:0;pointer-events:none}:host.point-focus .points .point-focus{opacity:1;pointer-events:initial}:host.point-focus .points .point-focus .actions{display:flex}banta-comments{flex-grow:1}.points{width:33%;margin-left:.5em;font-size:12pt;flex-shrink:0;max-width:30em;transition:.2s width ease-in,.2s max-width ease-in;position:relative}.points .points-section{flex-grow:1;display:flex;flex-direction:column;opacity:1;transition:.2s opacity ease-in;z-index:2}.points .point-focus{position:absolute;width:100%;inset:1.75em 0 0;padding:.5em;opacity:0;transition:.2s opacity ease-in;flex-grow:1;display:flex;flex-direction:column}.firehose{flex-grow:1;font-size:10pt;display:flex;flex-direction:column}form{display:flex;padding:.5em 0;align-items:center}form textarea{font-size:14pt;background:#000;color:#fff;border:1px solid #333;min-height:6em;width:100%}form input[type=text]{background:#000;color:#fff;border:1px solid #333;width:100%;height:1em}form .actions{margin-left:1em}form button{display:block;margin:0 0 0 auto}.subcomments ::ng-deep banta-comment{font-size:10pt}.subcomments ::ng-deep banta-comment.focused-comment{background:#001321;color:#fff;font-size:12pt}.aux{width:0px;min-width:0px;overflow-x:hidden;transition:.4s width ease-out,.4s min-width ease-out;display:flex;flex-direction:column}.aux.open{width:30em;min-width:18em}.aux .aux-contents{width:30em;min-width:10em;max-width:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;flex-grow:1}.notifications .notification{border-bottom:1px solid #333;padding:1em}.notifications .notification banta-timestamp{display:block;text-align:right;font-size:9pt;color:#999}.message.reply{padding:1em}.tabs{display:none}@media (max-width: 1015px){:host{flex-direction:column}.tabs{display:flex;position:absolute;top:0;left:0;right:0;width:100%;z-index:10;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);background:#00000080}.points{width:100%;max-width:100%;margin-left:0}header{display:none}:host.point-focus .points{width:100%;max-width:100%}.aux{width:100%;min-width:initial;max-width:100%}.points,.firehose,.aux{position:absolute;inset:2em 0 0;z-index:0;background:#000}.points.focus,.firehose.focus,.aux.focus{z-index:2}}:host-context(.mat-dark-theme) :host{background:#090909;color:#fff}:host-context(.mat-dark-theme) form textarea{background:#ccc;color:#333}:host-context(.mat-dark-theme) header:after{border-color:#222}:host-context(.mat-dark-theme) header label{color:#aaa}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3$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: i3$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3$1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: TimestampComponent, selector: "banta-timestamp", inputs: ["value"] }, { kind: "component", type: CommentComponent, selector: "banta-comment", inputs: ["message", "customMenuItems", "showReplyAction", "maxLength", "permissions", "mine", "editing", "genericAvatarUrl", "readonly"], outputs: ["liked", "unliked", "selected", "edited", "deleted", "editStarted", "editEnded", "shared", "userSelected", "usernameSelected", "avatarSelected", "reported", "loaded", "pinned", "unpinned"] }, { kind: "component", type: CommentViewComponent, selector: "banta-comment-view", inputs: ["source", "maxMessages", "maxVisibleMessages", "collapsePins", "newestLast", "holdNewMessages", "showEmptyState", "allowReplies", "enableHoldOnClick", "enableHoldOnScroll", "customMenuItems", "fixedHeight", "selectedMessage", "genericAvatarUrl"], outputs: ["userSelected", "reported", "liked", "unliked", "pinned", "unpinned", "usernameSelected", "avatarSelected", "shared", "deleted", "selected", "messageEdited", "sortOrderChanged", "filterModeChanged"] }, { kind: "component", type: BantaCommentsComponent, selector: "banta-comments", inputs: ["customMenuItems", "url", "maxCommentLength", "loadingMessages", "useInlineReplies", "signInLabel", "sendLabel", "signingInLabel", "replyLabel", "sendingLabel", "permissionDeniedLabel", "postCommentLabel", "postReplyLabel", "allowAttachments", "allowServerInfoRequest", "fixedHeight", "maxMessages", "maxVisibleMessages", "genericAvatarUrl", "shouldInterceptMessageSend", "participants", "source", "hashtags", "topicID", "sortOrder", "filterMode", "initialMessageCount", "metadata"], outputs: ["signInSelected", "editAvatarSelected", "permissionDeniedError", "upvoted", "reported", "selected", "userSelected", "usernameSelected", "avatarSelected", "shared", "reconnectRequested"] }, { kind: "component", type: BantaChatComponent, selector: "banta-chat", inputs: ["shouldInterceptMessageSend", "url", "source", "topicID", "metadata", "signInLabel", "sendLabel", "permissionDeniedLabel", "messageFieldPlaceholder", "emptyLabel"], outputs: ["selected", "reported", "upvoted", "userSelected", "permissionDeniedError", "signInSelected", "received"] }, { kind: "component", type: i2.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-flat-button], a[mat-stroked-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: LiveMessageComponent, selector: "banta-live-message", inputs: ["message"], outputs: ["upvoted", "reported", "selected"] }] }); }
10485
10592
  }
10486
10593
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: BantaComponent, decorators: [{
10487
10594
  type: Component,
@@ -10612,11 +10719,14 @@ class CommentsModule {
10612
10719
  MatInputModule,
10613
10720
  MatButtonModule,
10614
10721
  MatMenuModule,
10722
+ MatDividerModule,
10615
10723
  MatProgressSpinnerModule,
10616
10724
  BantaCommonModule,
10617
10725
  EmojiModule,
10618
10726
  MatTooltipModule,
10727
+ MatDatepickerModule,
10619
10728
  MatSelectModule,
10729
+ MatRadioModule,
10620
10730
  OverlayModule,
10621
10731
  PortalModule], exports: [CommentComponent,
10622
10732
  CommentViewComponent,
@@ -10635,11 +10745,14 @@ class CommentsModule {
10635
10745
  MatInputModule,
10636
10746
  MatButtonModule,
10637
10747
  MatMenuModule,
10748
+ MatDividerModule,
10638
10749
  MatProgressSpinnerModule,
10639
10750
  BantaCommonModule,
10640
10751
  EmojiModule,
10641
10752
  MatTooltipModule,
10753
+ MatDatepickerModule,
10642
10754
  MatSelectModule,
10755
+ MatRadioModule,
10643
10756
  OverlayModule,
10644
10757
  PortalModule] }); }
10645
10758
  }
@@ -10656,11 +10769,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImpor
10656
10769
  MatInputModule,
10657
10770
  MatButtonModule,
10658
10771
  MatMenuModule,
10772
+ MatDividerModule,
10659
10773
  MatProgressSpinnerModule,
10660
10774
  BantaCommonModule,
10661
10775
  EmojiModule,
10662
10776
  MatTooltipModule,
10777
+ MatDatepickerModule,
10663
10778
  MatSelectModule,
10779
+ MatRadioModule,
10664
10780
  OverlayModule,
10665
10781
  PortalModule
10666
10782
  ],
@@ -10785,6 +10901,18 @@ class ChatSource extends SocketRPC {
10785
10901
  return [];
10786
10902
  }
10787
10903
  }
10904
+ async getPinnedMessages() {
10905
+ try {
10906
+ let messages = await this.idempotentPeer.getPinnedMessages();
10907
+ messages = this.mapOrUpdateMessages(messages);
10908
+ return messages;
10909
+ }
10910
+ catch (e) {
10911
+ console.error(`[Banta/${this.identifier}] Error occurred while trying to get pinned messages:`);
10912
+ console.error(e);
10913
+ return [];
10914
+ }
10915
+ }
10788
10916
  async ensureConnection(errorMessage) {
10789
10917
  // let reason = `Connection to chat services is not currently available.`;
10790
10918
  // if (this.state !== 'connected' && this.state !== 'restored') {
@@ -10856,7 +10984,8 @@ class ChatSource extends SocketRPC {
10856
10984
  }
10857
10985
  onChatMessage(message) {
10858
10986
  if (this.messageMap.has(message.id)) {
10859
- return this.mapOrUpdateMessage(message);
10987
+ message = this.mapOrUpdateMessage(message);
10988
+ this._messageUpdated.next(message);
10860
10989
  }
10861
10990
  else if (!message.hidden) {
10862
10991
  // Only process non-hidden messages through here.
@@ -10909,6 +11038,14 @@ class ChatSource extends SocketRPC {
10909
11038
  await this.ensureConnection();
10910
11039
  return await this.idempotentPeer.likeMessage(messageId);
10911
11040
  }
11041
+ async pinMessage(messageId, options) {
11042
+ await this.ensureConnection();
11043
+ return await this.idempotentPeer.pinMessage(messageId, options);
11044
+ }
11045
+ async unpinMessage(messageId) {
11046
+ await this.ensureConnection();
11047
+ return await this.idempotentPeer.unpinMessage(messageId);
11048
+ }
10912
11049
  async unlikeMessage(messageId) {
10913
11050
  await this.ensureConnection();
10914
11051
  return await this.idempotentPeer.unlikeMessage(messageId);
@@ -10987,6 +11124,14 @@ class StaticChatSource {
10987
11124
  return await this.backend.getMessages(this.identifier, this.sortOrder, this.filterMode, 0, this.initialMessageCount);
10988
11125
  }
10989
11126
  }
11127
+ async getPinnedMessages() {
11128
+ if (this.parentIdentifier) {
11129
+ return await this.backend.getReplies(this.parentIdentifier, this.sortOrder, this.filterMode, 0, this.initialMessageCount, true);
11130
+ }
11131
+ else {
11132
+ return await this.backend.getMessages(this.identifier, this.sortOrder, this.filterMode, 0, this.initialMessageCount, true);
11133
+ }
11134
+ }
10990
11135
  async loadAfter(message, count) {
10991
11136
  return []; // no op
10992
11137
  }
@@ -10999,6 +11144,12 @@ class StaticChatSource {
10999
11144
  async unlikeMessage(messageId) {
11000
11145
  throw new Error(`Cannot perform this action in this state.`);
11001
11146
  }
11147
+ pinMessage(messageId, options) {
11148
+ throw new Error(`Cannot perform this action in this state.`);
11149
+ }
11150
+ unpinMessage(messageId) {
11151
+ throw new Error(`Cannot perform this action in this state.`);
11152
+ }
11002
11153
  async editMessage(messageId, text) {
11003
11154
  throw new Error(`Cannot perform this action in this state.`);
11004
11155
  }
@@ -11147,8 +11298,8 @@ class ChatBackend extends ChatBackendBase {
11147
11298
  * @param topicId
11148
11299
  * @returns
11149
11300
  */
11150
- async getMessages(topicId, sort, filter, offset, limit) {
11151
- let response = await fetch(`${this.serviceUrl}/topics/${topicId}/messages?${buildQuery({ sort, filter, offset, limit })}`);
11301
+ async getMessages(topicId, sort, filter, offset, limit, pinned) {
11302
+ let response = await fetch(`${this.serviceUrl}/topics/${topicId}/messages?${buildQuery({ sort, filter, offset, limit, pinned })}`);
11152
11303
  if (response.status >= 400)
11153
11304
  throw new Error(`Failed to fetch messages for topic: ${response.status}`);
11154
11305
  return await response.json();
@@ -11158,8 +11309,8 @@ class ChatBackend extends ChatBackendBase {
11158
11309
  * @param topicId
11159
11310
  * @returns
11160
11311
  */
11161
- async getReplies(parentMessageId, sort, filter, offset, limit) {
11162
- let response = await fetch(`${this.serviceUrl}/messages/${parentMessageId}/replies?${buildQuery({ sort, filter, offset, limit })}`);
11312
+ async getReplies(parentMessageId, sort, filter, offset, limit, pinned) {
11313
+ let response = await fetch(`${this.serviceUrl}/messages/${parentMessageId}/replies?${buildQuery({ sort, filter, offset, limit, pinned })}`);
11163
11314
  if (response.status >= 400)
11164
11315
  throw new Error(`Failed to fetch replies: ${response.status}`);
11165
11316
  return await response.json();