@banta/sdk 4.6.3 → 4.6.5
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.
- package/bundles/banta-sdk.umd.js +205 -62
- package/bundles/banta-sdk.umd.js.map +1 -1
- package/bundles/banta-sdk.umd.min.js +1 -1
- package/bundles/banta-sdk.umd.min.js.map +1 -1
- package/esm2015/lib/chat-source-base.js +1 -1
- package/esm2015/lib/chat-source.js +8 -3
- package/esm2015/lib/comments/banta-comments/banta-comments.component.js +28 -17
- package/esm2015/lib/comments/comment/comment.component.js +32 -2
- package/esm2015/lib/comments/comment-field/comment-field.component.js +7 -5
- package/esm2015/lib/comments/comment-view/comment-view.component.js +13 -10
- package/esm2015/lib/common/attachment/attachment.component.js +28 -4
- package/esm2015/lib/common/attachments/attachments.component.js +22 -3
- package/fesm2015/banta-sdk.js +130 -38
- package/fesm2015/banta-sdk.js.map +1 -1
- package/lib/chat-source-base.d.ts +1 -0
- package/lib/chat-source.d.ts +2 -0
- package/lib/comments/banta-comments/banta-comments.component.d.ts +3 -1
- package/lib/comments/comment/comment.component.d.ts +8 -1
- package/lib/comments/comment-view/comment-view.component.d.ts +5 -0
- package/lib/common/attachment/attachment.component.d.ts +10 -2
- package/lib/common/attachments/attachments.component.d.ts +7 -0
- package/package.json +1 -1
package/fesm2015/banta-sdk.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Observable, Subject, BehaviorSubject, Subscription } from 'rxjs';
|
|
2
|
-
import { publish } from 'rxjs/operators';
|
|
3
|
-
import { Component, Input, ViewChild, Pipe, Output, HostBinding, NgModule,
|
|
2
|
+
import { publish, take } from 'rxjs/operators';
|
|
3
|
+
import { Component, Input, ViewChild, Pipe, ElementRef, Output, HostBinding, NgModule, ViewChildren, Directive, NgZone, ContentChild, TemplateRef, Injectable, Inject } from '@angular/core';
|
|
4
4
|
import { marked, Renderer } from 'marked';
|
|
5
5
|
import { sanitize } from 'dompurify';
|
|
6
6
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
@@ -244,7 +244,8 @@ BantaTrustResourceUrlPipe.ctorParameters = () => [
|
|
|
244
244
|
];
|
|
245
245
|
|
|
246
246
|
class BantaAttachmentComponent {
|
|
247
|
-
constructor() {
|
|
247
|
+
constructor(elementRef) {
|
|
248
|
+
this.elementRef = elementRef;
|
|
248
249
|
this.loading = false;
|
|
249
250
|
this.editing = false;
|
|
250
251
|
this.loadingMessage = 'Please wait...';
|
|
@@ -252,6 +253,13 @@ class BantaAttachmentComponent {
|
|
|
252
253
|
this.errorMessage = 'An error has occurred';
|
|
253
254
|
this.removed = new Subject();
|
|
254
255
|
this.activated = new Subject();
|
|
256
|
+
this.loaded = new Subject();
|
|
257
|
+
this._viewLoaded = false;
|
|
258
|
+
}
|
|
259
|
+
get attachment() { return this._attachment; }
|
|
260
|
+
set attachment(value) {
|
|
261
|
+
this._attachment = value;
|
|
262
|
+
this.checkLoad();
|
|
255
263
|
}
|
|
256
264
|
ngOnInit() {
|
|
257
265
|
if (typeof window !== 'undefined') {
|
|
@@ -262,6 +270,19 @@ class BantaAttachmentComponent {
|
|
|
262
270
|
}, 100);
|
|
263
271
|
}
|
|
264
272
|
}
|
|
273
|
+
ngAfterViewInit() {
|
|
274
|
+
this._viewLoaded = true;
|
|
275
|
+
this.checkLoad();
|
|
276
|
+
}
|
|
277
|
+
checkLoad() {
|
|
278
|
+
var _a;
|
|
279
|
+
if (!this._attachment || !this._viewLoaded || !((_a = this.elementRef) === null || _a === void 0 ? void 0 : _a.nativeElement))
|
|
280
|
+
return;
|
|
281
|
+
if (typeof window === 'undefined')
|
|
282
|
+
this.loaded.next();
|
|
283
|
+
else
|
|
284
|
+
setTimeout(() => this.loaded.next(), 250);
|
|
285
|
+
}
|
|
265
286
|
activate() {
|
|
266
287
|
this.activated.next();
|
|
267
288
|
}
|
|
@@ -309,7 +330,9 @@ BantaAttachmentComponent.decorators = [
|
|
|
309
330
|
styles: [":host{position:relative;display:block}:host.loading{outline:1px solid #333;padding:1em 0;width:300px;text-align:center}:host.loading mat-spinner{display:block;margin:0 auto .5em;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}a.card-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;-o-object-fit:cover;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:-webkit-fit-content;width:-moz-fit-content;width:fit-content}a.image-attachment mat-icon.error{display:block;font-size:48px;width:48px;height:48px;margin:0 auto .5em}a.image-attachment .error{color:#b76363}a.image-attachment img{width:300px;border-radius:10px;max-width:100%;max-height:20em;-o-object-fit:cover;object-fit:cover}iframe{border:none;width:100%;aspect-ratio:16/9}@media (max-width:700px){a.card-attachment{flex-direction:column}a.card-attachment img{width:100%}}"]
|
|
310
331
|
},] }
|
|
311
332
|
];
|
|
312
|
-
BantaAttachmentComponent.ctorParameters = () => [
|
|
333
|
+
BantaAttachmentComponent.ctorParameters = () => [
|
|
334
|
+
{ type: ElementRef }
|
|
335
|
+
];
|
|
313
336
|
BantaAttachmentComponent.propDecorators = {
|
|
314
337
|
attachment: [{ type: Input }],
|
|
315
338
|
loading: [{ type: Input }],
|
|
@@ -319,6 +342,7 @@ BantaAttachmentComponent.propDecorators = {
|
|
|
319
342
|
errorMessage: [{ type: Input }],
|
|
320
343
|
removed: [{ type: Output }],
|
|
321
344
|
activated: [{ type: Output }],
|
|
345
|
+
loaded: [{ type: Output }],
|
|
322
346
|
isLoading: [{ type: HostBinding, args: ['class.loading',] }]
|
|
323
347
|
};
|
|
324
348
|
|
|
@@ -326,6 +350,21 @@ class BantaAttachmentsComponent {
|
|
|
326
350
|
constructor() {
|
|
327
351
|
this.editing = false;
|
|
328
352
|
this.remove = new Subject();
|
|
353
|
+
this.loaded = new Subject();
|
|
354
|
+
this.loadedAttachments = new WeakMap();
|
|
355
|
+
}
|
|
356
|
+
ngAfterViewInit() {
|
|
357
|
+
}
|
|
358
|
+
markAttachmentLoaded(attachment) {
|
|
359
|
+
this.loadedAttachments.set(attachment, true);
|
|
360
|
+
if (this.allAttachmentsLoaded)
|
|
361
|
+
this.loaded.next();
|
|
362
|
+
}
|
|
363
|
+
isAttachmentLoaded(attachment) {
|
|
364
|
+
return this.loadedAttachments.has(attachment);
|
|
365
|
+
}
|
|
366
|
+
get allAttachmentsLoaded() {
|
|
367
|
+
return this.attachments.every(x => this.isAttachmentLoaded(x));
|
|
329
368
|
}
|
|
330
369
|
removeAttachment(attachment) {
|
|
331
370
|
this.remove.next(attachment);
|
|
@@ -351,11 +390,14 @@ class BantaAttachmentsComponent {
|
|
|
351
390
|
get blockAttachments() {
|
|
352
391
|
return this.attachments.filter(x => x.style === 'block' || x.type === 'card');
|
|
353
392
|
}
|
|
393
|
+
attachmentId(index, attachment) {
|
|
394
|
+
return attachment.url;
|
|
395
|
+
}
|
|
354
396
|
}
|
|
355
397
|
BantaAttachmentsComponent.decorators = [
|
|
356
398
|
{ type: Component, args: [{
|
|
357
399
|
selector: 'banta-attachments',
|
|
358
|
-
template: "<ng-container *ngIf=\"attachments?.length > 0\">\r\n <banta-lightbox #lightbox></banta-lightbox>\r\n <div class=\"block-attachments\">\r\n <ng-container *ngFor=\"let attachment of blockAttachments\">\r\n <banta-attachment \r\n [attachment]=\"attachment\"\r\n [editing]=\"editing\"\r\n (removed)=\"removeAttachment(attachment)\"\r\n (activated)=\"showLightbox(attachment)\"\r\n ></banta-attachment>\r\n </ng-container>\r\n </div>\r\n\r\n <div \r\n class=\"inline-attachments\" \r\n [class.single]=\"attachments?.length === 1\" \r\n *ngIf=\"attachments && attachments?.length > 0\"\r\n >\r\n <ng-container *ngFor=\"let attachment of inlineAttachments\">\r\n <banta-attachment \r\n [attachment]=\"attachment\"\r\n [editing]=\"editing\"\r\n (removed)=\"removeAttachment(attachment)\"\r\n (activated)=\"showLightbox(attachment)\"\r\n ></banta-attachment>\r\n </ng-container>\r\n </div>\r\n</ng-container>",
|
|
400
|
+
template: "<ng-container *ngIf=\"attachments?.length > 0\">\r\n <banta-lightbox #lightbox></banta-lightbox>\r\n <div class=\"block-attachments\">\r\n <ng-container *ngFor=\"let attachment of blockAttachments; trackBy: attachmentId\">\r\n <banta-attachment \r\n [attachment]=\"attachment\"\r\n [editing]=\"editing\"\r\n (loaded)=\"markAttachmentLoaded(attachment)\"\r\n (removed)=\"removeAttachment(attachment)\"\r\n (activated)=\"showLightbox(attachment)\"\r\n ></banta-attachment>\r\n </ng-container>\r\n </div>\r\n\r\n <div \r\n class=\"inline-attachments\" \r\n [class.single]=\"attachments?.length === 1\" \r\n *ngIf=\"attachments && attachments?.length > 0\"\r\n >\r\n <ng-container *ngFor=\"let attachment of inlineAttachments; trackBy: attachmentId\">\r\n <banta-attachment \r\n [attachment]=\"attachment\"\r\n [editing]=\"editing\"\r\n (loaded)=\"markAttachmentLoaded(attachment)\"\r\n (removed)=\"removeAttachment(attachment)\"\r\n (activated)=\"showLightbox(attachment)\"\r\n ></banta-attachment>\r\n </ng-container>\r\n </div>\r\n</ng-container>",
|
|
359
401
|
styles: [".block-attachments{display:flex;flex-direction:column}.block-attachments banta-attachment{width:100%}.inline-attachments{flex-direction:row;margin-top:15px;display:flex;gap:20px;flex-wrap:wrap}"]
|
|
360
402
|
},] }
|
|
361
403
|
];
|
|
@@ -363,7 +405,8 @@ BantaAttachmentsComponent.propDecorators = {
|
|
|
363
405
|
attachments: [{ type: Input }],
|
|
364
406
|
editing: [{ type: Input }],
|
|
365
407
|
lightbox: [{ type: ViewChild, args: ['lightbox',] }],
|
|
366
|
-
remove: [{ type: Output }]
|
|
408
|
+
remove: [{ type: Output }],
|
|
409
|
+
loaded: [{ type: Output }]
|
|
367
410
|
};
|
|
368
411
|
|
|
369
412
|
const COMPONENTS = [
|
|
@@ -7867,6 +7910,8 @@ class CommentComponent {
|
|
|
7867
7910
|
this.isNew = false;
|
|
7868
7911
|
this.visible = false;
|
|
7869
7912
|
this.showReplyAction = true;
|
|
7913
|
+
this.loaded = new Subject();
|
|
7914
|
+
this.isLoaded = false;
|
|
7870
7915
|
this.mine = false;
|
|
7871
7916
|
this.editing = false;
|
|
7872
7917
|
this._editStarted = new Subject();
|
|
@@ -7887,10 +7932,35 @@ class CommentComponent {
|
|
|
7887
7932
|
setTimeout(() => this.isNew = false, 1000);
|
|
7888
7933
|
}, randomTime);
|
|
7889
7934
|
}
|
|
7935
|
+
markAttachmentsLoaded() {
|
|
7936
|
+
this.isLoaded = true;
|
|
7937
|
+
this.loaded.next();
|
|
7938
|
+
}
|
|
7890
7939
|
get isHighlighted() {
|
|
7891
7940
|
var _a, _b, _c;
|
|
7892
7941
|
return (_c = (_b = (_a = this.message) === null || _a === void 0 ? void 0 : _a.transientState) === null || _b === void 0 ? void 0 : _b.highlighted) !== null && _c !== void 0 ? _c : false;
|
|
7893
7942
|
}
|
|
7943
|
+
get message() {
|
|
7944
|
+
return this._message;
|
|
7945
|
+
}
|
|
7946
|
+
set message(value) {
|
|
7947
|
+
var _a;
|
|
7948
|
+
this._message = value;
|
|
7949
|
+
if (((_a = this._message.attachments) === null || _a === void 0 ? void 0 : _a.length) > 0) {
|
|
7950
|
+
this.isLoaded = false;
|
|
7951
|
+
}
|
|
7952
|
+
else {
|
|
7953
|
+
this.isLoaded = true;
|
|
7954
|
+
this.loaded.next();
|
|
7955
|
+
}
|
|
7956
|
+
}
|
|
7957
|
+
waitForLoad() {
|
|
7958
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
7959
|
+
if (this.isLoaded)
|
|
7960
|
+
return true;
|
|
7961
|
+
yield this.loaded.pipe(take(1)).toPromise();
|
|
7962
|
+
});
|
|
7963
|
+
}
|
|
7894
7964
|
get userSelected() {
|
|
7895
7965
|
return this._userSelected.asObservable();
|
|
7896
7966
|
}
|
|
@@ -7972,7 +8042,7 @@ class CommentComponent {
|
|
|
7972
8042
|
CommentComponent.decorators = [
|
|
7973
8043
|
{ type: Component, args: [{
|
|
7974
8044
|
selector: 'banta-comment',
|
|
7975
|
-
template: "\r\n<mat-menu #pointItemMenu=\"matMenu\">\r\n <button mat-menu-item (click)=\"share()\">\r\n <mat-icon>share</mat-icon>\r\n Share\r\n </button>\r\n <button *ngIf=\"!mine\" mat-menu-item (click)=\"report()\">\r\n <mat-icon>warning</mat-icon>\r\n Report\r\n </button>\r\n <button *ngIf=\"mine\" [disabled]=\"!permissions?.canEdit\" mat-menu-item (click)=\"startEdit()\">\r\n <mat-icon>edit</mat-icon>\r\n Edit\r\n </button>\r\n <button *ngIf=\"mine\" [disabled]=\"!permissions?.canDelete\" mat-menu-item (click)=\"delete()\">\r\n <mat-icon>delete</mat-icon>\r\n Delete\r\n </button>\r\n\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=\"message-content\">\r\n <div class=\"user\">\r\n <div class=\"user-1\">\r\n <a\r\n href=\"javascript:;\"\r\n class=\"avatar\"\r\n (click)=\"selectAvatar(message.user)\"\r\n [style.background-image]=\"avatarForUser(message.user)\"></a>\r\n <div class=\"user-identity\">\r\n <a href=\"javascript:;\" class=\"display-name\" (click)=\"selectUser()\">{{message.user.displayName}}</a>\r\n <a href=\"javascript:;\" class=\"username\" (click)=\"selectUsername(message.user)\">@{{message.user.username}}</a>\r\n </div>\r\n </div>\r\n <div class=\"user-2\">\r\n <span class=\"user-tag\" *ngIf=\"message.user.tag\">{{message.user.tag}}</span>\r\n <banta-timestamp [value]=\"message.sentAt\"></banta-timestamp>\r\n <span class=\"spacer\"></span>\r\n </div>\r\n </div>\r\n <div class=\"content\" *ngIf=\"!editing\">\r\n <span class=\"banta-message-content\" [innerHTML]=\"message.message | markdownToHtml\"></span>\r\n <banta-attachments [attachments]=\"message.attachments\"></banta-attachments>\r\n <ul class=\"message-facts\">\r\n <li *ngIf=\"message.edits?.length > 0\">(Edited)</li>\r\n </ul>\r\n </div>\r\n <div class=\"content\" *ngIf=\"editing\" style=\"padding-bottom: 2em;\">\r\n <div>\r\n <mat-form-field floatLabel=\"always\" appearance=\"outline\" style=\"width: 100%;\">\r\n <mat-label>Edit Message</mat-label>\r\n <textarea matInput [(ngModel)]=\"editedMessage\" [maxlength]=\"maxLength\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n <button mat-raised-button (click)=\"saveEdit()\">Save</button> \r\n <button mat-button (click)=\"endEditing()\">Cancel</button>\r\n </div>\r\n\r\n\r\n <div class=\"actions\">\r\n <div class=\"spacer\"></div>\r\n <div class=\"counted-action\" *ngIf=\"showReplyAction\">\r\n <button mat-button [matTooltip]=\"replyCount > 0 ? 'Replies' : 'Reply'\" matTooltipPosition=\"below\" (click)=\"select()\">\r\n <mat-icon [inline]=\"true\">comment</mat-icon>\r\n <span class=\"count-indicator\">\r\n {{replyCount > 0 ? 'Replies' : 'Reply'}}\r\n {{replyCount > 0 ? '(' + replyCount + ')' : ''}}\r\n </span>\r\n </button>\r\n </div>\r\n <div class=\"counted-action\" [class.active]=\"message.userState?.liked\">\r\n <button \r\n *ngIf=\"message.transientState?.liking\"\r\n mat-icon-button \r\n [disabled]=\"true\" \r\n [matTooltip]=\"upvoting ? 'Please wait...' : message.userState?.liked ? 'Unlike' : 'Like'\" \r\n matTooltipPosition=\"below\" \r\n >\r\n <mat-spinner [diameter]=\"15\" style=\"margin-left: 1em;\"></mat-spinner>\r\n </button>\r\n <button \r\n *ngIf=\"!message.transientState?.liking\"\r\n mat-button \r\n [matTooltip]=\"permissions?.canLike ? upvoting ? 'Please wait...' : 'Like' : permissions?.canLikeErrorMessage\" \r\n matTooltipPosition=\"below\" \r\n (click)=\"message.userState?.liked ? unlike() : like()\" \r\n >\r\n <mat-icon [inline]=\"true\">thumb_up</mat-icon>\r\n <span class=\"count-indicator\" *ngIf=\"message.likes > 0\">\r\n {{message.likes}}\r\n </span>\r\n </button>\r\n </div>\r\n\r\n <button mat-icon-button [matMenuTriggerFor]=\"pointItemMenu\">\r\n <mat-icon [inline]=\"true\">more_vert</mat-icon>\r\n </button>\r\n </div>\r\n</div>\r\n",
|
|
8045
|
+
template: "\r\n<mat-menu #pointItemMenu=\"matMenu\">\r\n <button mat-menu-item (click)=\"share()\">\r\n <mat-icon>share</mat-icon>\r\n Share\r\n </button>\r\n <button *ngIf=\"!mine\" mat-menu-item (click)=\"report()\">\r\n <mat-icon>warning</mat-icon>\r\n Report\r\n </button>\r\n <button *ngIf=\"mine\" [disabled]=\"!permissions?.canEdit\" mat-menu-item (click)=\"startEdit()\">\r\n <mat-icon>edit</mat-icon>\r\n Edit\r\n </button>\r\n <button *ngIf=\"mine\" [disabled]=\"!permissions?.canDelete\" mat-menu-item (click)=\"delete()\">\r\n <mat-icon>delete</mat-icon>\r\n Delete\r\n </button>\r\n\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=\"message-content\">\r\n <div class=\"user\">\r\n <div class=\"user-1\">\r\n <a\r\n href=\"javascript:;\"\r\n class=\"avatar\"\r\n (click)=\"selectAvatar(message.user)\"\r\n [style.background-image]=\"avatarForUser(message.user)\"></a>\r\n <div class=\"user-identity\">\r\n <a href=\"javascript:;\" class=\"display-name\" (click)=\"selectUser()\">{{message.user.displayName}}</a>\r\n <a href=\"javascript:;\" class=\"username\" (click)=\"selectUsername(message.user)\">@{{message.user.username}}</a>\r\n </div>\r\n </div>\r\n <div class=\"user-2\">\r\n <span class=\"user-tag\" *ngIf=\"message.user.tag\">{{message.user.tag}}</span>\r\n <banta-timestamp [value]=\"message.sentAt\"></banta-timestamp>\r\n <span class=\"spacer\"></span>\r\n </div>\r\n </div>\r\n <div class=\"content\" *ngIf=\"!editing\">\r\n <span class=\"banta-message-content\" [innerHTML]=\"message.message | markdownToHtml\"></span>\r\n <banta-attachments \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=\"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> \r\n <button mat-button (click)=\"endEditing()\">Cancel</button>\r\n </div>\r\n\r\n\r\n <div class=\"actions\">\r\n <div class=\"spacer\"></div>\r\n <div class=\"counted-action\" *ngIf=\"showReplyAction\">\r\n <button mat-button [matTooltip]=\"replyCount > 0 ? 'Replies' : 'Reply'\" matTooltipPosition=\"below\" (click)=\"select()\">\r\n <mat-icon [inline]=\"true\">comment</mat-icon>\r\n <span class=\"count-indicator\">\r\n {{replyCount > 0 ? 'Replies' : 'Reply'}}\r\n {{replyCount > 0 ? '(' + replyCount + ')' : ''}}\r\n </span>\r\n </button>\r\n </div>\r\n <div class=\"counted-action\" [class.active]=\"message.userState?.liked\">\r\n <button \r\n *ngIf=\"message.transientState?.liking\"\r\n mat-icon-button \r\n [disabled]=\"true\" \r\n [matTooltip]=\"upvoting ? 'Please wait...' : message.userState?.liked ? 'Unlike' : 'Like'\" \r\n matTooltipPosition=\"below\" \r\n >\r\n <mat-spinner [diameter]=\"15\" style=\"margin-left: 1em;\"></mat-spinner>\r\n </button>\r\n <button \r\n *ngIf=\"!message.transientState?.liking\"\r\n mat-button \r\n [matTooltip]=\"permissions?.canLike ? upvoting ? 'Please wait...' : 'Like' : permissions?.canLikeErrorMessage\" \r\n matTooltipPosition=\"below\" \r\n (click)=\"message.userState?.liked ? unlike() : like()\" \r\n >\r\n <mat-icon [inline]=\"true\">thumb_up</mat-icon>\r\n <span class=\"count-indicator\" *ngIf=\"message.likes > 0\">\r\n {{message.likes}}\r\n </span>\r\n </button>\r\n </div>\r\n\r\n <button mat-icon-button [matMenuTriggerFor]=\"pointItemMenu\">\r\n <mat-icon [inline]=\"true\">more_vert</mat-icon>\r\n </button>\r\n </div>\r\n</div>\r\n",
|
|
7976
8046
|
styles: ["@-webkit-keyframes comment-appear{0%{transform:translate(6em)}to{transform:translate(0)}}@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;-webkit-animation-name:comment-appear;animation-name:comment-appear;-webkit-animation-duration:.25s;animation-duration:.25s;-webkit-animation-fill-mode:both;animation-fill-mode:both}:host.highlighted{background:#00223a;outline:2px solid #003277}:host.visible{visibility:visible}:host:hover{background:#eee}:host .message-content .content{margin-left:60px;margin-right:.5em}:host .message-content .attachments-row{margin-top:15px;display:flex;gap:10px}:host .message-content .attachments-row img{border-radius:10px;width:300px;max-width:100%;max-height:20em;-o-object-fit:cover;object-fit:cover}:host.abbreviated .message-content .content{text-overflow:ellipsis;overflow-y:hidden}:host .actions{display:flex;padding-right:10px;margin-left:60px;align-items:center}:host .actions button,banta-timestamp{color:#666;flex-shrink:0}banta-timestamp{font-size:10pt;margin-left:1em;text-align:right}.user{position:relative;margin:1em 0 0;display:flex;align-items:center;flex-wrap:wrap}.user .user-1,.user .user-2{display:flex;flex-wrap:nowrap;align-items:center;min-width:0}.user .user-2{margin:1em 0}.user .user-identity{display:flex;flex-direction:column;min-width:0}.user .display-name,.user .username{z-index:1;position:relative;padding:0 0 0 1em;font-size:10pt;color:#000;margin:0 auto 0 0;display:block;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;max-width:100%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;flex-shrink:1;flex-grow:0;min-width:0}.user .display-name.username.username.username,.user .username.username.username.username{color:#666}.avatar{height:48px;width:48px;background-position:50%;background-size:cover;background-color:#333;border-radius:100%;flex-shrink:0;flex-grow:0}.counted-action{display:flex;align-items:center}.counted-action.active .count-indicator,.counted-action.active button{color:#00a5ff}.counted-action button .count-indicator{margin-left:.5em}.count-indicator{font-size:9pt;padding:0 0 0 3px;color:#666}:host-context(.mat-dark-theme) .count-indicator{border-color:#333}:host-context(.mat-dark-theme):hover{background:#060606}.user-tag,:host-context(.mat-dark-theme) .user .display-name,:host-context(.mat-dark-theme) .user .username{color:#fff}.user-tag{text-transform:uppercase;font-size:12px;border:1px solid #b27373;background:#7a412b;padding:3px 5px;margin:0 .5em 0 1em;border-radius:3px}.spacer{flex-shrink:1;flex-grow:1}ul.message-facts{margin:0;padding:0;color:#666}ul.message-facts li{list-style-type:none;border-left:1px solid #666;font-size:10pt;padding-left:.5em;margin-left:.5em;margin-top:.5em}ul.message-facts li:first-child{border-left:1px solid transparent;margin-left:0;padding-left:0}@media (max-width:400px){.avatar{height:32px;width:32px}:host .actions{margin-left:0;margin-top:.5em}:host .message-content .content{margin-left:44px;margin-right:.5em}}:host-context(.banta-mobile) .avatar{height:32px;width:32px}:host-context(.banta-mobile) :host .actions{margin-left:0;margin-top:.5em}:host-context(.banta-mobile) :host .message-content .content{margin-left:44px;margin-right:.5em}.card-attachment a{display:flex;align-items:flex-start;gap:1em;width:100%;border:1px solid #666;border-radius:4px;padding:1em;box-sizing:border-box;background-color:#191919}.card-attachment a img{width:300px;aspect-ratio:16/9;-o-object-fit:cover;object-fit:cover;border-radius:10px}.card-attachment a h1{margin:0;font-size:30px}"]
|
|
7977
8047
|
},] }
|
|
7978
8048
|
];
|
|
@@ -7987,6 +8057,7 @@ CommentComponent.propDecorators = {
|
|
|
7987
8057
|
message: [{ type: Input }],
|
|
7988
8058
|
customMenuItems: [{ type: Input }],
|
|
7989
8059
|
showReplyAction: [{ type: Input }],
|
|
8060
|
+
loaded: [{ type: Output }],
|
|
7990
8061
|
userSelected: [{ type: Output }],
|
|
7991
8062
|
usernameSelected: [{ type: Output }],
|
|
7992
8063
|
avatarSelected: [{ type: Output }],
|
|
@@ -8057,7 +8128,6 @@ class CommentViewComponent {
|
|
|
8057
8128
|
console.log(`...Need to load more comments to find ${message.id}`);
|
|
8058
8129
|
yield this.showMore();
|
|
8059
8130
|
}
|
|
8060
|
-
console.log(`Finished loading comments, hasMore=${this.hasMore}`);
|
|
8061
8131
|
if (!this.isMessageLoadedInContext(message)) {
|
|
8062
8132
|
console.error(`Error while loading message in context: Failed to find message ${message.id}, maybe it was deleted!`);
|
|
8063
8133
|
return false;
|
|
@@ -8069,17 +8139,11 @@ class CommentViewComponent {
|
|
|
8069
8139
|
console.error(`Error while loading message in context: Message was not present in message list!`);
|
|
8070
8140
|
return false;
|
|
8071
8141
|
}
|
|
8072
|
-
console.log(`Total messages: ${items.length}`);
|
|
8073
|
-
console.log(`Page size: ${pageSize}`);
|
|
8074
|
-
console.log(`Message index: ${index}`);
|
|
8075
8142
|
let startIndex = Math.max(0, index - pageSize / 2);
|
|
8076
|
-
console.log(`Start index: ${index}`);
|
|
8077
8143
|
this.newMessages = items.splice(0, startIndex);
|
|
8078
8144
|
this.messages = items.splice(0, pageSize);
|
|
8079
8145
|
this.olderMessages = items;
|
|
8080
|
-
|
|
8081
|
-
console.log(`${this.messages.length} current messages`);
|
|
8082
|
-
console.log(`${this.newMessages.length} newer messages`);
|
|
8146
|
+
this.isViewingMore = true;
|
|
8083
8147
|
});
|
|
8084
8148
|
}
|
|
8085
8149
|
/**
|
|
@@ -8215,7 +8279,6 @@ class CommentViewComponent {
|
|
|
8215
8279
|
else {
|
|
8216
8280
|
lastMessage = (_b = this.olderMessages[this.olderMessages.length - 1]) !== null && _b !== void 0 ? _b : this.messages[this.messages.length - 1];
|
|
8217
8281
|
}
|
|
8218
|
-
console.dir(lastMessage);
|
|
8219
8282
|
if (!lastMessage) {
|
|
8220
8283
|
this.isLoadingMore = false;
|
|
8221
8284
|
this.hasMore = false;
|
|
@@ -8276,6 +8339,17 @@ class CommentViewComponent {
|
|
|
8276
8339
|
}
|
|
8277
8340
|
return maxPagingCursor;
|
|
8278
8341
|
}
|
|
8342
|
+
/**
|
|
8343
|
+
* Wait for all currently visible comments to be fully loaded, including all attachments.
|
|
8344
|
+
* Doing this will prevent layout shift when scrolling to a specific comment.
|
|
8345
|
+
*/
|
|
8346
|
+
waitForAllCommentsToLoad() {
|
|
8347
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
8348
|
+
yield new Promise(r => setTimeout(r, 100));
|
|
8349
|
+
yield this.sourceLoaded;
|
|
8350
|
+
yield Promise.all(this.comments.map(x => x.waitForLoad()));
|
|
8351
|
+
});
|
|
8352
|
+
}
|
|
8279
8353
|
sortMessages() {
|
|
8280
8354
|
if (!this.source)
|
|
8281
8355
|
return;
|
|
@@ -8437,6 +8511,7 @@ class BantaCommentsComponent {
|
|
|
8437
8511
|
{ hashtag: 'slow', description: 'Be slow when this message is posted' },
|
|
8438
8512
|
];
|
|
8439
8513
|
this.loadingSharedComment = false;
|
|
8514
|
+
this.sharedCommentMissing = false;
|
|
8440
8515
|
this.sendMessage = (message) => __awaiter(this, void 0, void 0, function* () {
|
|
8441
8516
|
var _a;
|
|
8442
8517
|
try {
|
|
@@ -8508,10 +8583,6 @@ class BantaCommentsComponent {
|
|
|
8508
8583
|
}
|
|
8509
8584
|
get isMobileSized() { return this.width < 500; }
|
|
8510
8585
|
ngAfterViewInit() {
|
|
8511
|
-
this.threadViewQuery.changes.subscribe(changes => {
|
|
8512
|
-
console.log(`i see changes...`);
|
|
8513
|
-
console.dir(changes);
|
|
8514
|
-
});
|
|
8515
8586
|
if (typeof window !== 'undefined') {
|
|
8516
8587
|
let callback = () => {
|
|
8517
8588
|
let size = this.elementRef.nativeElement.getBoundingClientRect();
|
|
@@ -8643,11 +8714,13 @@ class BantaCommentsComponent {
|
|
|
8643
8714
|
if (value) {
|
|
8644
8715
|
if (this.sharedCommentID) {
|
|
8645
8716
|
this.navigateToSharedComment(this.sharedCommentID);
|
|
8717
|
+
this.lastSharedCommentID = this.sharedCommentID;
|
|
8646
8718
|
this.sharedCommentID = null;
|
|
8647
8719
|
}
|
|
8648
8720
|
this._source.messages.forEach(m => this.addParticipant(m));
|
|
8649
8721
|
this._sourceSubscription.add(this._source.messageReceived.subscribe(m => this.addParticipant(m)));
|
|
8650
8722
|
this._sourceSubscription.add(this._source.messageSent.subscribe(m => this.addParticipant(m)));
|
|
8723
|
+
this._sourceSubscription.add(this._source.messageObserved.subscribe(m => this.addParticipant(m)));
|
|
8651
8724
|
this._sourceSubscription.add(this._source.messageUpdated.subscribe(msg => {
|
|
8652
8725
|
var _a;
|
|
8653
8726
|
console.log(`comments received message: `, msg);
|
|
@@ -8689,23 +8762,25 @@ class BantaCommentsComponent {
|
|
|
8689
8762
|
}
|
|
8690
8763
|
// UI Interactions
|
|
8691
8764
|
scrollToComment(commentId) {
|
|
8692
|
-
|
|
8693
|
-
|
|
8694
|
-
|
|
8695
|
-
|
|
8696
|
-
|
|
8697
|
-
|
|
8698
|
-
comment.
|
|
8765
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
8766
|
+
if (typeof window === 'undefined')
|
|
8767
|
+
return;
|
|
8768
|
+
yield this.commentView.waitForAllCommentsToLoad();
|
|
8769
|
+
const comment = document.querySelector(`[data-comment-id="${commentId}"]`);
|
|
8770
|
+
if (comment) {
|
|
8771
|
+
comment.scrollIntoView({
|
|
8699
8772
|
inline: 'center',
|
|
8700
8773
|
block: 'center'
|
|
8701
8774
|
});
|
|
8702
8775
|
}
|
|
8703
|
-
}
|
|
8776
|
+
});
|
|
8704
8777
|
}
|
|
8705
8778
|
navigateToSharedComment(id) {
|
|
8706
8779
|
var _a, _b, _c, _d;
|
|
8707
8780
|
return __awaiter(this, void 0, void 0, function* () {
|
|
8708
8781
|
this.loadingSharedComment = true;
|
|
8782
|
+
yield new Promise(r => setTimeout(r, 10));
|
|
8783
|
+
this.sharedCommentMissing = false;
|
|
8709
8784
|
let source = this.source;
|
|
8710
8785
|
yield source.ready;
|
|
8711
8786
|
yield this.viewReady;
|
|
@@ -8717,7 +8792,17 @@ class BantaCommentsComponent {
|
|
|
8717
8792
|
}
|
|
8718
8793
|
catch (e) {
|
|
8719
8794
|
console.error(`Failed to find comment from URL: ${e.message}`);
|
|
8720
|
-
|
|
8795
|
+
this.sharedCommentMissing = true;
|
|
8796
|
+
this.loadingSharedComment = false;
|
|
8797
|
+
if (typeof window !== 'undefined') {
|
|
8798
|
+
setTimeout(() => {
|
|
8799
|
+
let notice = this.element.querySelector('.loading-comment');
|
|
8800
|
+
notice.scrollIntoView({
|
|
8801
|
+
block: 'center',
|
|
8802
|
+
inline: 'center'
|
|
8803
|
+
});
|
|
8804
|
+
}, 200);
|
|
8805
|
+
}
|
|
8721
8806
|
return;
|
|
8722
8807
|
}
|
|
8723
8808
|
(_a = message.transientState) !== null && _a !== void 0 ? _a : (message.transientState = {});
|
|
@@ -8744,8 +8829,8 @@ class BantaCommentsComponent {
|
|
|
8744
8829
|
(_d = message.transientState) !== null && _d !== void 0 ? _d : (message.transientState = {});
|
|
8745
8830
|
message.transientState.highlighted = true;
|
|
8746
8831
|
}
|
|
8747
|
-
this.scrollToComment(id);
|
|
8748
8832
|
this.loadingSharedComment = false;
|
|
8833
|
+
yield this.scrollToComment(id);
|
|
8749
8834
|
});
|
|
8750
8835
|
}
|
|
8751
8836
|
handlePermissionDenied(errorMessage) {
|
|
@@ -8943,8 +9028,8 @@ class BantaCommentsComponent {
|
|
|
8943
9028
|
BantaCommentsComponent.decorators = [
|
|
8944
9029
|
{ type: Component, args: [{
|
|
8945
9030
|
selector: 'banta-comments',
|
|
8946
|
-
template: "<ng-container *ngIf=\"loading\">\r\n <div class=\"loading-screen\" [class.visible]=\"showLoadingScreen\">\r\n <h1>Loading...</h1>\r\n <div>\r\n <mat-spinner [diameter]=\"300\" [strokeWidth]=\"2\"></mat-spinner>\r\n </div>\r\n\r\n <p class=\"loading-message\" [class.visible]=\"loadingMessageVisible\">{{loadingMessage}}</p>\r\n </div>\r\n</ng-container>\r\n<ng-container *ngIf=\"!loading\">\r\n <div class=\"focused\" [class.visible]=\"selectedMessageVisible\" *ngIf=\"selectedMessage && !useInlineReplies\">\r\n\r\n <div>\r\n <a mat-button href=\"javascript:;\" (click)=\"unselectMessage()\">\r\n <mat-icon>arrow_back</mat-icon>\r\n Latest Comments\r\n </a>\r\n </div>\r\n\r\n <banta-comment\r\n [message]=\"selectedMessage\"\r\n [liking]=\"selectedMessage.transientState.liking\"\r\n [mine]=\"user?.id === selectedMessage.user?.id\"\r\n [permissions]=\"source?.permissions\"\r\n [showReplyAction]=\"false\"\r\n [editing]=\"selectedMessage.transientState.editing\"\r\n [maxLength]=\"maxCommentLength\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (editStarted)=\"startEditing(selectedMessage)\"\r\n (editEnded)=\"selectedMessage.transientState.editing = false\"\r\n (edited)=\"saveEdit(selectedMessage, $event)\"\r\n (userSelected)=\"selectMessageUser(selectedMessage)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (liked)=\"likeMessage(source, selectedMessage)\"\r\n (unliked)=\"unlikeMessage(source, selectedMessage)\"\r\n (reported)=\"reportMessage(selectedMessage)\"\r\n (selected)=\"selectMessage(selectedMessage)\"\r\n (shared)=\"shareMessage($event)\"\r\n (deleted)=\"deleteMessage(selectedMessage)\"\r\n ></banta-comment>\r\n\r\n <div class=\"replies\">\r\n\r\n <ng-container *ngIf=\"!selectedMessageThread\">\r\n <div class=\"loading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedMessageThread\">\r\n <banta-comment-view\r\n 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 [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n (signInSelected)=\"showSignIn()\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n [source]=\"selectedMessageThread\"\r\n [maxLength]=\"maxCommentLength\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInLabel]=\"signInLabel\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [user]=\"user\"\r\n [label]=\"postReplyLabel\"\r\n [submit]=\"sendReply\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"sendReplyOptionsTemplate\"></ng-container>\r\n </banta-comment-field>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <div class=\"main\" [class.hidden]=\"selectedMessage && !useInlineReplies\">\r\n <banta-comment-field\r\n [source]=\"source\"\r\n [user]=\"user\"\r\n [sendLabel]=\"sendLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [signInLabel]=\"signInLabel\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n [label]=\"postCommentLabel\"\r\n [maxLength]=\"maxCommentLength\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n (signInSelected)=\"showSignIn()\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [submit]=\"sendMessage\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n >\r\n \r\n </banta-comment-field>\r\n\r\n <banta-comment-sort\r\n [(sort)]=\"sortOrder\"></banta-comment-sort>\r\n\r\n <div class=\"loading-comment\" *ngIf=\"loadingSharedComment\">\r\n <h1>Loading desired comment...</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 <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 (userSelected)=\"selectMessageUser($event)\"\r\n (sortOrderChanged)=\"sortOrder = $event\"\r\n (selected)=\"selectMessage($event)\"\r\n (liked)=\"likeMessage(source, $event)\"\r\n (unliked)=\"unlikeMessage(source, $event)\"\r\n (messageEdited)=\"editMessage(source, $event.message, $event.newMessage)\"\r\n (reported)=\"reportMessage($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (shared)=\"shareMessage($event)\"\r\n [selectedMessage]=\"selectedMessage\"\r\n (deleted)=\"deleteMessage($event)\"\r\n >\r\n <div class=\"inline-replies\">\r\n <div class=\"focused\" [class.visible]=\"selectedMessageVisible\" *ngIf=\"selectedMessage\">\r\n <div class=\"replies\">\r\n \r\n <ng-container *ngIf=\"!selectedMessageThread\">\r\n <div class=\"loading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n </ng-container>\r\n \r\n <ng-container *ngIf=\"selectedMessageThread\">\r\n <banta-comment-view\r\n [source]=\"selectedMessageThread\"\r\n [allowReplies]=\"false\"\r\n [fixedHeight]=\"false\"\r\n [showEmptyState]=\"false\"\r\n [newestLast]=\"true\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (liked)=\"likeMessage(selectedMessageThread, $event)\"\r\n (unliked)=\"unlikeMessage(selectedMessageThread, $event)\"\r\n (messageEdited)=\"editMessage(selectedMessageThread, $event.message, $event.newMessage)\"\r\n (reported)=\"reportMessage($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (shared)=\"shareMessage($event)\"\r\n (deleted)=\"deleteMessage($event)\"\r\n ></banta-comment-view>\r\n \r\n <banta-comment-field\r\n [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n (signInSelected)=\"showSignIn()\"\r\n [maxLength]=\"maxCommentLength\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n [source]=\"selectedMessageThread\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInLabel]=\"signInLabel\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [user]=\"user\"\r\n [label]=\"postReplyLabel\"\r\n [submit]=\"sendReply\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"sendReplyOptionsTemplate\"></ng-container>\r\n </banta-comment-field>\r\n </ng-container>\r\n </div>\r\n </div> \r\n </div>\r\n </banta-comment-view>\r\n </div>\r\n</ng-container>\r\n",
|
|
8947
|
-
styles: [":host{display:flex;flex-direction:column}@-webkit-keyframes select-comment{0%{transform:scale(1.15)}to{transform:scale(1)}}@keyframes select-comment{0%{transform:scale(1.15)}to{transform:scale(1)}}.focused{-webkit-animation-name:select-comment;animation-name:select-comment;-webkit-animation-duration:.4s;animation-duration:.4s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.focused .replies{margin-top:1em;margin-left:2em;border-left:2px solid #333;padding-left:2em}banta-comment-view{opacity:1;transition:opacity .4s ease-in-out}banta-comment-view.faded{opacity:.25}.loading{display:block;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;margin:0 auto;min-height:16em}.main.hidden{display:none}.loading-screen{text-align:center;opacity:0;transition:opacity .25s ease-in-out}.loading-screen.visible{opacity:1}.loading-screen h1{font-weight:100}.loading-screen mat-spinner{margin:5em auto}.loading-screen .loading-message{opacity:0;transition:opacity .25s ease-in-out;width:500px;max-width:100%;margin:0 auto}.loading-screen .loading-message.visible{opacity:1}banta-comment-sort{margin:0 0 0 auto;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;display:block}.inline-replies{margin-left:4em}@media (max-width:500px){.focused .replies{margin-left:0}.inline-replies{margin-left:1em}.focused .replies{padding-left:.5em}banta-comment-sort{margin:0;width:100%}}:host-context(.banta-mobile) .focused .replies{margin-left:0}:host-context(.banta-mobile) .inline-replies{margin-left:1em}:host-context(.banta-mobile) .focused .replies{padding-left:.5em}:host-context(.banta-mobile) banta-comment-sort{margin:0;width:100%}.loading-comment{z-index:100;border:1px solid #333;background:#000;color:#fff;padding:1em;border-radius:4px;text-align:center}.loading-comment h1{font-weight:100;text-align:center}.loading-comment mat-spinner{margin:0 auto}"]
|
|
9031
|
+
template: "<ng-container *ngIf=\"loading\">\r\n <div class=\"loading-screen\" [class.visible]=\"showLoadingScreen\">\r\n <h1>Loading...</h1>\r\n <div>\r\n <mat-spinner [diameter]=\"300\" [strokeWidth]=\"2\"></mat-spinner>\r\n </div>\r\n\r\n <p class=\"loading-message\" [class.visible]=\"loadingMessageVisible\">{{loadingMessage}}</p>\r\n </div>\r\n</ng-container>\r\n<ng-container *ngIf=\"!loading\">\r\n <div class=\"focused\" [class.visible]=\"selectedMessageVisible\" *ngIf=\"selectedMessage && !useInlineReplies\">\r\n\r\n <div>\r\n <a mat-button href=\"javascript:;\" (click)=\"unselectMessage()\">\r\n <mat-icon>arrow_back</mat-icon>\r\n Latest Comments\r\n </a>\r\n </div>\r\n\r\n <banta-comment\r\n [message]=\"selectedMessage\"\r\n [liking]=\"selectedMessage.transientState.liking\"\r\n [mine]=\"user?.id === selectedMessage.user?.id\"\r\n [permissions]=\"source?.permissions\"\r\n [showReplyAction]=\"false\"\r\n [editing]=\"selectedMessage.transientState.editing\"\r\n [maxLength]=\"maxCommentLength\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (editStarted)=\"startEditing(selectedMessage)\"\r\n (editEnded)=\"selectedMessage.transientState.editing = false\"\r\n (edited)=\"saveEdit(selectedMessage, $event)\"\r\n (userSelected)=\"selectMessageUser(selectedMessage)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (liked)=\"likeMessage(source, selectedMessage)\"\r\n (unliked)=\"unlikeMessage(source, selectedMessage)\"\r\n (reported)=\"reportMessage(selectedMessage)\"\r\n (selected)=\"selectMessage(selectedMessage)\"\r\n (shared)=\"shareMessage($event)\"\r\n (deleted)=\"deleteMessage(selectedMessage)\"\r\n ></banta-comment>\r\n\r\n <div class=\"replies\">\r\n\r\n <ng-container *ngIf=\"!selectedMessageThread\">\r\n <div class=\"loading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedMessageThread\">\r\n <banta-comment-view\r\n 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 [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n (signInSelected)=\"showSignIn()\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n [source]=\"selectedMessageThread\"\r\n [maxLength]=\"maxCommentLength\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInLabel]=\"signInLabel\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [user]=\"user\"\r\n [label]=\"postReplyLabel\"\r\n [submit]=\"sendReply\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"sendReplyOptionsTemplate\"></ng-container>\r\n </banta-comment-field>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <div class=\"main\" [class.hidden]=\"selectedMessage && !useInlineReplies\">\r\n <banta-comment-field\r\n [source]=\"source\"\r\n [user]=\"user\"\r\n [sendLabel]=\"sendLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [signInLabel]=\"signInLabel\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n [label]=\"postCommentLabel\"\r\n [maxLength]=\"maxCommentLength\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n (signInSelected)=\"showSignIn()\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [submit]=\"sendMessage\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n >\r\n \r\n </banta-comment-field>\r\n\r\n <banta-comment-sort\r\n [(sort)]=\"sortOrder\"></banta-comment-sort>\r\n\r\n <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 (userSelected)=\"selectMessageUser($event)\"\r\n (sortOrderChanged)=\"sortOrder = $event\"\r\n (selected)=\"selectMessage($event)\"\r\n (liked)=\"likeMessage(source, $event)\"\r\n (unliked)=\"unlikeMessage(source, $event)\"\r\n (messageEdited)=\"editMessage(source, $event.message, $event.newMessage)\"\r\n (reported)=\"reportMessage($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (shared)=\"shareMessage($event)\"\r\n [selectedMessage]=\"selectedMessage\"\r\n (deleted)=\"deleteMessage($event)\"\r\n >\r\n <div class=\"inline-replies\">\r\n <div class=\"focused\" [class.visible]=\"selectedMessageVisible\" *ngIf=\"selectedMessage\">\r\n <div class=\"replies\">\r\n \r\n <ng-container *ngIf=\"!selectedMessageThread\">\r\n <div class=\"loading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n </ng-container>\r\n \r\n <ng-container *ngIf=\"selectedMessageThread\">\r\n <banta-comment-view\r\n [source]=\"selectedMessageThread\"\r\n [allowReplies]=\"false\"\r\n [fixedHeight]=\"false\"\r\n [showEmptyState]=\"false\"\r\n [newestLast]=\"true\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (liked)=\"likeMessage(selectedMessageThread, $event)\"\r\n (unliked)=\"unlikeMessage(selectedMessageThread, $event)\"\r\n (messageEdited)=\"editMessage(selectedMessageThread, $event.message, $event.newMessage)\"\r\n (reported)=\"reportMessage($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (shared)=\"shareMessage($event)\"\r\n (deleted)=\"deleteMessage($event)\"\r\n ></banta-comment-view>\r\n \r\n <banta-comment-field\r\n [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n (signInSelected)=\"showSignIn()\"\r\n [maxLength]=\"maxCommentLength\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n [source]=\"selectedMessageThread\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInLabel]=\"signInLabel\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [user]=\"user\"\r\n [label]=\"postReplyLabel\"\r\n [submit]=\"sendReply\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"sendReplyOptionsTemplate\"></ng-container>\r\n </banta-comment-field>\r\n </ng-container>\r\n </div>\r\n </div> \r\n </div>\r\n </banta-comment-view>\r\n </div>\r\n</ng-container>\r\n",
|
|
9032
|
+
styles: [":host{display:flex;flex-direction:column}@-webkit-keyframes select-comment{0%{transform:scale(1.15)}to{transform:scale(1)}}@keyframes select-comment{0%{transform:scale(1.15)}to{transform:scale(1)}}.focused{-webkit-animation-name:select-comment;animation-name:select-comment;-webkit-animation-duration:.4s;animation-duration:.4s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.focused .replies{margin-top:1em;margin-left:2em;border-left:2px solid #333;padding-left:2em}banta-comment-view{opacity:1;transition:opacity .4s ease-in-out}banta-comment-view.faded{opacity:.25}.loading{display:block;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;margin:0 auto;min-height:16em}.main.hidden{display:none}.loading-screen{text-align:center;opacity:0;transition:opacity .25s ease-in-out}.loading-screen.visible{opacity:1}.loading-screen h1{font-weight:100}.loading-screen mat-spinner{margin:5em auto}.loading-screen .loading-message{opacity:0;transition:opacity .25s ease-in-out;width:500px;max-width:100%;margin:0 auto}.loading-screen .loading-message.visible{opacity:1}banta-comment-sort{margin:0 0 0 auto;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;display:block}.inline-replies{margin-left:4em}@media (max-width:500px){.focused .replies{margin-left:0}.inline-replies{margin-left:1em}.focused .replies{padding-left:.5em}banta-comment-sort{margin:0;width:100%}}:host-context(.banta-mobile) .focused .replies{margin-left:0}:host-context(.banta-mobile) .inline-replies{margin-left:1em}:host-context(.banta-mobile) .focused .replies{padding-left:.5em}:host-context(.banta-mobile) banta-comment-sort{margin:0;width:100%}.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}"]
|
|
8948
9033
|
},] }
|
|
8949
9034
|
];
|
|
8950
9035
|
BantaCommentsComponent.ctorParameters = () => [
|
|
@@ -9280,10 +9365,12 @@ class CommentFieldComponent {
|
|
|
9280
9365
|
return;
|
|
9281
9366
|
}
|
|
9282
9367
|
if (event.key === 'Enter') {
|
|
9283
|
-
|
|
9284
|
-
|
|
9285
|
-
|
|
9286
|
-
|
|
9368
|
+
if (this.autocompleteOptions[this.autoCompleteSelected]) {
|
|
9369
|
+
this.activateAutoComplete(this.autocompleteOptions[this.autoCompleteSelected]);
|
|
9370
|
+
event.stopPropagation();
|
|
9371
|
+
event.preventDefault();
|
|
9372
|
+
return;
|
|
9373
|
+
}
|
|
9287
9374
|
}
|
|
9288
9375
|
if (event.key === 'ArrowUp') {
|
|
9289
9376
|
if (this.autoCompleteSelected === 0)
|
|
@@ -9616,6 +9703,7 @@ class ChatSource extends SocketRPC {
|
|
|
9616
9703
|
this._messageReceived = new Subject();
|
|
9617
9704
|
this._messageUpdated = new Subject();
|
|
9618
9705
|
this._messageSent = new Subject();
|
|
9706
|
+
this._messageObserved = new Subject();
|
|
9619
9707
|
this.messages = [];
|
|
9620
9708
|
this.ready = new Promise(resolve => this.markReady = resolve);
|
|
9621
9709
|
}
|
|
@@ -9658,10 +9746,13 @@ class ChatSource extends SocketRPC {
|
|
|
9658
9746
|
}
|
|
9659
9747
|
mapOrUpdateMessage(message) {
|
|
9660
9748
|
let existingMessage = this.messageMap.get(message.id);
|
|
9661
|
-
if (existingMessage)
|
|
9749
|
+
if (existingMessage) {
|
|
9662
9750
|
message = Object.assign(existingMessage, message);
|
|
9663
|
-
|
|
9751
|
+
}
|
|
9752
|
+
else {
|
|
9664
9753
|
this.messageMap.set(message.id, message);
|
|
9754
|
+
this._messageObserved.next(message);
|
|
9755
|
+
}
|
|
9665
9756
|
return message;
|
|
9666
9757
|
}
|
|
9667
9758
|
getExistingMessages() {
|
|
@@ -9730,6 +9821,7 @@ class ChatSource extends SocketRPC {
|
|
|
9730
9821
|
get messageReceived() { return this._messageReceived.asObservable(); }
|
|
9731
9822
|
get messageUpdated() { return this._messageUpdated.asObservable(); }
|
|
9732
9823
|
get messageSent() { return this._messageSent.asObservable(); }
|
|
9824
|
+
get messageObserved() { return this._messageObserved.asObservable(); }
|
|
9733
9825
|
send(message) {
|
|
9734
9826
|
return __awaiter(this, void 0, void 0, function* () {
|
|
9735
9827
|
yield this.ensureConnection();
|