@banta/sdk 4.4.1 → 4.4.4
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/banta-sdk.metadata.json +1 -1
- package/bundles/banta-sdk.umd.js +367 -173
- 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/attachment-scraper.js +2 -87
- package/esm2015/lib/banta-sdk.module.js +23 -1
- package/esm2015/lib/chat-backend-base.js +1 -6
- package/esm2015/lib/chat-source-base.js +1 -1
- package/esm2015/lib/chat-source.js +31 -3
- package/esm2015/lib/comments/banta-comments/banta-comments.component.js +26 -7
- package/esm2015/lib/comments/comment/comment.component.js +2 -2
- package/esm2015/lib/comments/comment-field/comment-field.component.js +37 -6
- package/esm2015/lib/common/attachment/attachment.component.js +29 -3
- package/esm2015/lib/giphy-attachments.js +20 -0
- package/esm2015/lib/index.js +6 -1
- package/esm2015/lib/tweet-attachments.js +16 -0
- package/esm2015/lib/url-attachments.js +46 -0
- package/esm2015/lib/youtube-attachments.js +25 -0
- package/fesm2015/banta-sdk.js +239 -104
- package/fesm2015/banta-sdk.js.map +1 -1
- package/lib/attachment-scraper.d.ts +0 -15
- package/lib/banta-sdk.module.d.ts +2 -0
- package/lib/chat-backend-base.d.ts +2 -2
- package/lib/chat-source-base.d.ts +1 -0
- package/lib/chat-source.d.ts +8 -3
- package/lib/comments/comment-field/comment-field.component.d.ts +5 -1
- package/lib/common/attachment/attachment.component.d.ts +4 -0
- package/lib/giphy-attachments.d.ts +5 -0
- package/lib/index.d.ts +5 -0
- package/lib/tweet-attachments.d.ts +5 -0
- package/lib/url-attachments.d.ts +11 -0
- package/lib/youtube-attachments.d.ts +5 -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
2
|
import { publish } from 'rxjs/operators';
|
|
3
|
-
import { Component, Input, ViewChild, Pipe, Output, HostBinding, NgModule, ElementRef,
|
|
3
|
+
import { Component, Input, ViewChild, Pipe, Output, HostBinding, NgModule, ElementRef, 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';
|
|
@@ -251,6 +251,15 @@ class BantaAttachmentComponent {
|
|
|
251
251
|
this.removed = new Subject();
|
|
252
252
|
this.activated = new Subject();
|
|
253
253
|
}
|
|
254
|
+
ngOnInit() {
|
|
255
|
+
if (typeof window !== 'undefined') {
|
|
256
|
+
setTimeout(() => {
|
|
257
|
+
if (!window['twttr'])
|
|
258
|
+
return;
|
|
259
|
+
window['twttr'].widgets.load();
|
|
260
|
+
}, 100);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
254
263
|
activate() {
|
|
255
264
|
this.activated.next();
|
|
256
265
|
}
|
|
@@ -274,14 +283,31 @@ class BantaAttachmentComponent {
|
|
|
274
283
|
return true;
|
|
275
284
|
return false;
|
|
276
285
|
}
|
|
286
|
+
get hasFrame() {
|
|
287
|
+
if (!this.attachment)
|
|
288
|
+
return false;
|
|
289
|
+
return this.attachment.type === 'iframe' || (this.attachment.type === 'card'
|
|
290
|
+
&& this.attachment.card.player);
|
|
291
|
+
}
|
|
292
|
+
get frameUrl() {
|
|
293
|
+
if (!this.attachment)
|
|
294
|
+
return undefined;
|
|
295
|
+
if (this.attachment.type === 'iframe') {
|
|
296
|
+
return this.attachment.url;
|
|
297
|
+
}
|
|
298
|
+
else if (this.attachment.type === 'card') {
|
|
299
|
+
return this.attachment.card.player;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
277
302
|
}
|
|
278
303
|
BantaAttachmentComponent.decorators = [
|
|
279
304
|
{ type: Component, args: [{
|
|
280
305
|
selector: 'banta-attachment',
|
|
281
|
-
template: "<button type=\"button\" (click)=\"remove()\" mat-mini-fab color=\"primary\" class=\"remove-button\" *ngIf=\"editing\">\r\n <mat-icon>close</mat-icon>\r\n</button>\r\n\r\n<ng-container *ngIf=\"isError\">\r\n <mat-icon class=\"error\">close</mat-icon>\r\n <em class=\"error\">{{theErrorMessage}}</em>\r\n</ng-container>\r\n<ng-container *ngIf=\"!isError\">\r\n <ng-container *ngIf=\"isLoading\">\r\n <mat-spinner></mat-spinner>\r\n <em>{{loadingMessage}}</em>\r\n </ng-container>\r\n <ng-container *ngIf=\"!isLoading\">\r\n <iframe
|
|
282
|
-
styles: [":host{position:relative;display:block}:host.loading{outline:1px solid #333;padding:1em 0;width:300px;text-align:center}:host.loading mat-spinner{display:block;margin:0 auto .5em;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}a.card{display:flex;align-items:flex-start;gap:1em;width:100%;border:1px solid #666;border-radius:4px;padding:1em;box-sizing:border-box;background-color:#191919}a.card img{width:
|
|
306
|
+
template: "<button type=\"button\" (click)=\"remove()\" mat-mini-fab color=\"primary\" class=\"remove-button\" *ngIf=\"editing\">\r\n <mat-icon>close</mat-icon>\r\n</button>\r\n\r\n<ng-container *ngIf=\"isError\">\r\n <mat-icon class=\"error\">close</mat-icon>\r\n <em class=\"error\">{{theErrorMessage}}</em>\r\n</ng-container>\r\n<ng-container *ngIf=\"!isError\">\r\n <ng-container *ngIf=\"isLoading\">\r\n <mat-spinner></mat-spinner>\r\n <em>{{loadingMessage}}</em>\r\n </ng-container>\r\n <ng-container *ngIf=\"!isLoading\">\r\n <iframe *ngIf=\"hasFrame\"\r\n sandbox=\"allow-scripts allow-popups allow-same-origin allow-presentation\" \r\n [src]=\"frameUrl | trustResourceUrl\"></iframe>\r\n <a *ngIf=\"attachment.type === 'card'\" class=\"card\" [href]=\"attachment.url\" target=\"_blank\" [class.has-image]=\"attachment.card.image\">\r\n <img \r\n *ngIf=\"attachment.card.image\"\r\n class=\"thumbnail\" \r\n [src]=\"attachment.card.image\"\r\n />\r\n <div class=\"description\">\r\n <h1>{{attachment.card.title}}</h1>\r\n <div>\r\n {{attachment.card.description}}\r\n </div>\r\n <cite>{{attachment.card.url}}</cite>\r\n </div>\r\n </a>\r\n <a class=\"image-attachment\" *ngIf=\"isImageAttachment\" href=\"javascript:;\" (click)=\"activate()\">\r\n <img [src]=\"attachment.url\" alt=\"Image Attachment\">\r\n </a>\r\n <blockquote *ngIf=\"attachment.type === 'tweet'\" \r\n class=\"twitter-tweet\">\r\n <p lang=\"en\" dir=\"ltr\"></p>\r\n <a href=\"https://twitter.com/seldo/status/1562553608083714050?ref_src=twsrc%5Etfw\"></a>\r\n </blockquote>\r\n </ng-container>\r\n</ng-container>",
|
|
307
|
+
styles: [":host{position:relative;display:block}:host.loading{outline:1px solid #333;padding:1em 0;width:300px;text-align:center}:host.loading mat-spinner{display:block;margin:0 auto .5em;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}a.card{display:flex;align-items:flex-start;gap:1em;width:100%;border:1px solid #666;border-radius:4px;padding:1em;box-sizing:border-box;background-color:#191919;margin:1em 0}a.card img{width:250px;aspect-ratio:16/9;-o-object-fit:cover;object-fit:cover;border-radius:10px}a.card.has-image h1{font-size:22px}a.card h1{min-width:0;margin:0 0 .5em;font-size:26px}a.card cite{min-width:0;opacity:.75;margin-top:1em;display:block;font-size:90%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}a.card .description{min-width:0}.remove-button{position:absolute;right:10px;top:10px;margin:0;z-index:1}a.image-attachment{width:300px;position:relative;text-align:center}a.image-attachment.with-border{outline:1px solid #333;padding:1em 0}a.image-attachment mat-spinner{display:block;margin:0 auto .5em;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}a.image-attachment mat-icon.error{display:block;font-size:48px;width:48px;height:48px;margin:0 auto .5em}a.image-attachment .error{color:#b76363}a.image-attachment img{width:300px;border-radius:10px;max-width:100%;max-height:20em;-o-object-fit:cover;object-fit:cover}iframe{border:none;width:100%;aspect-ratio:16/9}"]
|
|
283
308
|
},] }
|
|
284
309
|
];
|
|
310
|
+
BantaAttachmentComponent.ctorParameters = () => [];
|
|
285
311
|
BantaAttachmentComponent.propDecorators = {
|
|
286
312
|
attachment: [{ type: Input }],
|
|
287
313
|
loading: [{ type: Input }],
|
|
@@ -7124,99 +7150,11 @@ ChatMessageComponent.propDecorators = {
|
|
|
7124
7150
|
upvoted: [{ type: Output }]
|
|
7125
7151
|
};
|
|
7126
7152
|
|
|
7127
|
-
const URL_REGEX = new RegExp('(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?', 'ig');
|
|
7128
|
-
class UrlAttachmentScraper {
|
|
7129
|
-
findFragments(message) {
|
|
7130
|
-
var _a;
|
|
7131
|
-
// If a message already has a URL attachment, don't add another one.
|
|
7132
|
-
if (message.attachments && message.attachments.filter(x => x.type === 'url').length > 0)
|
|
7133
|
-
return null;
|
|
7134
|
-
return (Array.from((_a = message.message.match(URL_REGEX)) !== null && _a !== void 0 ? _a : []))
|
|
7135
|
-
.reduce((a, item) => (a.includes(item) ? undefined : a.push(item), a), [])
|
|
7136
|
-
.map(url => ({
|
|
7137
|
-
text: url,
|
|
7138
|
-
offset: message.message.indexOf(url),
|
|
7139
|
-
type: 'url'
|
|
7140
|
-
}));
|
|
7141
|
-
}
|
|
7142
|
-
}
|
|
7143
|
-
class GiphyAttachmentResolver {
|
|
7144
|
-
resolveFragment(message, fragment) {
|
|
7145
|
-
var _a;
|
|
7146
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
7147
|
-
if (fragment.type === 'url' && fragment.text.startsWith('https://giphy.com/gifs')) {
|
|
7148
|
-
let gifId = (_a = /[^-\/]+$/.exec(fragment.text)) === null || _a === void 0 ? void 0 : _a.toString();
|
|
7149
|
-
if (!gifId)
|
|
7150
|
-
return null;
|
|
7151
|
-
return {
|
|
7152
|
-
type: 'iframe',
|
|
7153
|
-
url: `https://giphy.com/embed/${gifId}`,
|
|
7154
|
-
style: 'inline'
|
|
7155
|
-
};
|
|
7156
|
-
}
|
|
7157
|
-
return null;
|
|
7158
|
-
});
|
|
7159
|
-
}
|
|
7160
|
-
}
|
|
7161
|
-
class YouTubeAttachmentResolver {
|
|
7162
|
-
resolveFragment(message, fragment) {
|
|
7163
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
7164
|
-
if (fragment.type !== 'url')
|
|
7165
|
-
return null;
|
|
7166
|
-
let videoId;
|
|
7167
|
-
if (fragment.text.match(/https?:\/\/(www\.)?youtube.com\/watch\?v=/)) {
|
|
7168
|
-
let match = /watch\?v=([^&]+)/.exec(fragment.text);
|
|
7169
|
-
if (match) {
|
|
7170
|
-
videoId = match[1];
|
|
7171
|
-
}
|
|
7172
|
-
}
|
|
7173
|
-
if (videoId) {
|
|
7174
|
-
return {
|
|
7175
|
-
type: 'iframe',
|
|
7176
|
-
url: `https://www.youtube.com/embed/${videoId}`,
|
|
7177
|
-
style: 'block'
|
|
7178
|
-
};
|
|
7179
|
-
}
|
|
7180
|
-
return null;
|
|
7181
|
-
});
|
|
7182
|
-
}
|
|
7183
|
-
}
|
|
7184
|
-
class UrlAttachmentResolver {
|
|
7185
|
-
constructor(backend) {
|
|
7186
|
-
this.backend = backend;
|
|
7187
|
-
}
|
|
7188
|
-
resolveFragment(message, fragment) {
|
|
7189
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
7190
|
-
if (fragment.type !== 'url')
|
|
7191
|
-
return null;
|
|
7192
|
-
let urlCard = yield this.backend.getCardForUrl(fragment.text);
|
|
7193
|
-
if (urlCard) {
|
|
7194
|
-
return {
|
|
7195
|
-
type: 'card',
|
|
7196
|
-
url: fragment.text,
|
|
7197
|
-
card: urlCard,
|
|
7198
|
-
style: 'block'
|
|
7199
|
-
};
|
|
7200
|
-
}
|
|
7201
|
-
});
|
|
7202
|
-
}
|
|
7203
|
-
}
|
|
7204
|
-
UrlAttachmentResolver.decorators = [
|
|
7205
|
-
{ type: Injectable }
|
|
7206
|
-
];
|
|
7207
|
-
UrlAttachmentResolver.ctorParameters = () => [
|
|
7208
|
-
{ type: ChatBackendBase }
|
|
7209
|
-
];
|
|
7210
|
-
|
|
7211
7153
|
class ChatBackendBase {
|
|
7212
7154
|
constructor() {
|
|
7213
7155
|
this._userChanged = new BehaviorSubject(null);
|
|
7214
7156
|
this._attachmentScrapers = [];
|
|
7215
7157
|
this._attachmentResolvers = [];
|
|
7216
|
-
this.registerAttachmentScraper(new UrlAttachmentScraper());
|
|
7217
|
-
this.registerAttachmentResolver(new GiphyAttachmentResolver());
|
|
7218
|
-
this.registerAttachmentResolver(new YouTubeAttachmentResolver());
|
|
7219
|
-
this.registerAttachmentResolver(new UrlAttachmentResolver(this));
|
|
7220
7158
|
}
|
|
7221
7159
|
get userChanged() {
|
|
7222
7160
|
return this._userChanged;
|
|
@@ -8027,7 +7965,7 @@ class CommentComponent {
|
|
|
8027
7965
|
CommentComponent.decorators = [
|
|
8028
7966
|
{ type: Component, args: [{
|
|
8029
7967
|
selector: 'banta-comment',
|
|
8030
|
-
template: "\r\n<mat-menu #pointItemMenu=\"matMenu\">\r\n <button mat-menu-item (click)=\"share()\">\r\n <mat-icon>share</mat-icon>\r\n Share\r\n </button>\r\n <button *ngIf=\"!mine\" mat-menu-item (click)=\"report()\">\r\n <mat-icon>warning</mat-icon>\r\n Report\r\n </button>\r\n <button *ngIf=\"mine\" [disabled]=\"!permissions?.canEdit\" mat-menu-item (click)=\"startEdit()\">\r\n <mat-icon>edit</mat-icon>\r\n Edit\r\n </button>\r\n <button *ngIf=\"mine\" [disabled]=\"!permissions?.canDelete\" mat-menu-item (click)=\"delete()\">\r\n <mat-icon>delete</mat-icon>\r\n Delete\r\n </button>\r\n</mat-menu>\r\n\r\n<div class=\"message-content\">\r\n <div class=\"user\">\r\n <div class=\"user-1\">\r\n <a\r\n href=\"javascript:;\"\r\n class=\"avatar\"\r\n (click)=\"selectAvatar(message.user)\"\r\n [style.background-image]=\"avatarForUser(message.user)\"></a>\r\n <div class=\"user-identity\">\r\n <a href=\"javascript:;\" class=\"display-name\" (click)=\"selectUser()\">{{message.user.displayName}}</a>\r\n <a href=\"javascript:;\" class=\"username\" (click)=\"selectUsername(message.user)\">@{{message.user.username}}</a>\r\n </div>\r\n </div>\r\n <div class=\"user-2\">\r\n <span class=\"user-tag\" *ngIf=\"message.user.tag\">{{message.user.tag}}</span>\r\n <banta-timestamp [value]=\"message.sentAt\"></banta-timestamp>\r\n <span class=\"spacer\"></span>\r\n </div>\r\n </div>\r\n <div class=\"content\" *ngIf=\"!editing\">\r\n <span class=\"banta-message-content\" [innerHTML]=\"message.message | markdownToHtml\"></span>\r\n <banta-attachments [attachments]=\"message.attachments\"></banta-attachments>\r\n <ul class=\"message-facts\">\r\n <li *ngIf=\"message.edits?.length > 0\">(Edited)</li>\r\n </ul>\r\n </div>\r\n <div class=\"content\" *ngIf=\"editing\" style=\"padding-bottom: 2em;\">\r\n <div>\r\n <mat-form-field floatLabel=\"always\" appearance=\"outline\" style=\"width: 100%;\">\r\n <mat-label>Edit Message</mat-label>\r\n <textarea matInput [(ngModel)]=\"editedMessage\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n <button mat-raised-button (click)=\"saveEdit()\">Save</button> \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 [
|
|
7968
|
+
template: "\r\n<mat-menu #pointItemMenu=\"matMenu\">\r\n <button mat-menu-item (click)=\"share()\">\r\n <mat-icon>share</mat-icon>\r\n Share\r\n </button>\r\n <button *ngIf=\"!mine\" mat-menu-item (click)=\"report()\">\r\n <mat-icon>warning</mat-icon>\r\n Report\r\n </button>\r\n <button *ngIf=\"mine\" [disabled]=\"!permissions?.canEdit\" mat-menu-item (click)=\"startEdit()\">\r\n <mat-icon>edit</mat-icon>\r\n Edit\r\n </button>\r\n <button *ngIf=\"mine\" [disabled]=\"!permissions?.canDelete\" mat-menu-item (click)=\"delete()\">\r\n <mat-icon>delete</mat-icon>\r\n Delete\r\n </button>\r\n</mat-menu>\r\n\r\n<div class=\"message-content\">\r\n <div class=\"user\">\r\n <div class=\"user-1\">\r\n <a\r\n href=\"javascript:;\"\r\n class=\"avatar\"\r\n (click)=\"selectAvatar(message.user)\"\r\n [style.background-image]=\"avatarForUser(message.user)\"></a>\r\n <div class=\"user-identity\">\r\n <a href=\"javascript:;\" class=\"display-name\" (click)=\"selectUser()\">{{message.user.displayName}}</a>\r\n <a href=\"javascript:;\" class=\"username\" (click)=\"selectUsername(message.user)\">@{{message.user.username}}</a>\r\n </div>\r\n </div>\r\n <div class=\"user-2\">\r\n <span class=\"user-tag\" *ngIf=\"message.user.tag\">{{message.user.tag}}</span>\r\n <banta-timestamp [value]=\"message.sentAt\"></banta-timestamp>\r\n <span class=\"spacer\"></span>\r\n </div>\r\n </div>\r\n <div class=\"content\" *ngIf=\"!editing\">\r\n <span class=\"banta-message-content\" [innerHTML]=\"message.message | markdownToHtml\"></span>\r\n <banta-attachments [attachments]=\"message.attachments\"></banta-attachments>\r\n <ul class=\"message-facts\">\r\n <li *ngIf=\"message.edits?.length > 0\">(Edited)</li>\r\n </ul>\r\n </div>\r\n <div class=\"content\" *ngIf=\"editing\" style=\"padding-bottom: 2em;\">\r\n <div>\r\n <mat-form-field floatLabel=\"always\" appearance=\"outline\" style=\"width: 100%;\">\r\n <mat-label>Edit Message</mat-label>\r\n <textarea matInput [(ngModel)]=\"editedMessage\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n <button mat-raised-button (click)=\"saveEdit()\">Save</button> \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",
|
|
8031
7969
|
styles: ["@-webkit-keyframes comment-appear{0%{transform:translate(100vw)}to{transform:translate(0)}}@keyframes comment-appear{0%{transform:translate(100vw)}to{transform:translate(0)}}:host{display:flex;flex-direction:column;position:relative;padding:.5em;visibility:hidden}:host.new{visibility:visible;-webkit-animation-name:comment-appear;animation-name:comment-appear;-webkit-animation-duration:.4s;animation-duration:.4s;-webkit-animation-fill-mode:both;animation-fill-mode:both}:host.highlighted{background:#00223a;outline:2px solid #003277}:host.visible{visibility:visible}:host:hover{background:#eee}:host .message-content .content{margin-left:60px;margin-right:.5em}:host .message-content .attachments-row{margin-top:15px;display:flex;gap:10px}:host .message-content .attachments-row img{border-radius:10px;width:300px;max-width:100%;max-height:20em;-o-object-fit:cover;object-fit:cover}:host.abbreviated .message-content .content{text-overflow:ellipsis;overflow-y:hidden}:host .actions{display:flex;padding-right:10px;margin-left:60px;align-items:center}:host .actions button,banta-timestamp{color:#666;flex-shrink:0}banta-timestamp{font-size:10pt;margin-left:1em;text-align:right}.user{position:relative;margin:1em 0 0;display:flex;align-items:center;flex-wrap:wrap}.user .user-1,.user .user-2{display:flex;flex-wrap:nowrap;align-items:center;min-width:0}.user .user-2{margin:1em 0}.user .user-identity{display:flex;flex-direction:column;min-width:0}.user .display-name,.user .username{z-index:1;position:relative;padding:0 0 0 1em;font-size:10pt;color:#000;margin:0 auto 0 0;display:block;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;max-width:100%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;flex-shrink:1;flex-grow:0;min-width:0}.user .display-name.username.username.username,.user .username.username.username.username{color:#666}.avatar{height:48px;width:48px;background-position:50%;background-size:cover;background-color:#333;border-radius:100%;flex-shrink:0;flex-grow:0}.counted-action{display:flex;align-items:center}.counted-action.active .count-indicator,.counted-action.active button{color:#00a5ff}.counted-action button .count-indicator{margin-left:.5em}.count-indicator{font-size:9pt;padding:0 0 0 3px;color:#666}:host-context(.mat-dark-theme) .count-indicator{border-color:#333}:host-context(.mat-dark-theme):hover{background:#060606}.user-tag,:host-context(.mat-dark-theme) .user .display-name,:host-context(.mat-dark-theme) .user .username{color:#fff}.user-tag{text-transform:uppercase;font-size:12px;border:1px solid #b27373;background:#7a412b;padding:3px 5px;margin:0 .5em 0 1em;border-radius:3px}.spacer{flex-shrink:1;flex-grow:1}ul.message-facts{margin:0;padding:0;color:#666}ul.message-facts li{list-style-type:none;border-left:1px solid #666;font-size:10pt;padding-left:.5em;margin-left:.5em;margin-top:.5em}ul.message-facts li:first-child{border-left:1px solid transparent;margin-left:0;padding-left:0}@media (max-width:400px){.avatar{height:32px;width:32px}:host .actions{margin-left:0;margin-top:.5em}:host .message-content .content{margin-left:44px;margin-right:.5em}}:host-context(.banta-mobile) .avatar{height:32px;width:32px}:host-context(.banta-mobile) :host .actions{margin-left:0;margin-top:.5em}:host-context(.banta-mobile) :host .message-content .content{margin-left:44px;margin-right:.5em}.card-attachment a{display:flex;align-items:flex-start;gap:1em;width:100%;border:1px solid #666;border-radius:4px;padding:1em;box-sizing:border-box;background-color:#191919}.card-attachment a img{width:300px;aspect-ratio:16/9;-o-object-fit:cover;object-fit:cover;border-radius:10px}.card-attachment a h1{margin:0;font-size:30px}"]
|
|
8032
7970
|
},] }
|
|
8033
7971
|
];
|
|
@@ -8652,25 +8590,32 @@ class BantaCommentsComponent {
|
|
|
8652
8590
|
}
|
|
8653
8591
|
// Actions
|
|
8654
8592
|
likeMessage(source, message) {
|
|
8655
|
-
var _a;
|
|
8656
8593
|
return __awaiter(this, void 0, void 0, function* () {
|
|
8594
|
+
if (!this.user) {
|
|
8595
|
+
yield this.showSignIn();
|
|
8596
|
+
return;
|
|
8597
|
+
}
|
|
8657
8598
|
this._upvoted.next(message);
|
|
8658
8599
|
message.transientState.liking = true;
|
|
8659
|
-
if (!((_a = message.userState) === null || _a === void 0 ? void 0 : _a.liked))
|
|
8660
|
-
message.likes = (message.likes || 0) + 1;
|
|
8661
8600
|
try {
|
|
8662
8601
|
yield source.likeMessage(message.id);
|
|
8663
8602
|
}
|
|
8664
8603
|
catch (e) {
|
|
8665
8604
|
this.handleBackendExceptionAsAlert(e, 'Could not like this message: ');
|
|
8666
8605
|
}
|
|
8667
|
-
|
|
8668
|
-
|
|
8606
|
+
finally {
|
|
8607
|
+
yield new Promise(resolve => setTimeout(() => resolve(), 250));
|
|
8608
|
+
message.transientState.liking = false;
|
|
8609
|
+
}
|
|
8669
8610
|
});
|
|
8670
8611
|
}
|
|
8671
8612
|
unlikeMessage(source, message) {
|
|
8672
8613
|
var _a;
|
|
8673
8614
|
return __awaiter(this, void 0, void 0, function* () {
|
|
8615
|
+
if (!this.user) {
|
|
8616
|
+
yield this.showSignIn();
|
|
8617
|
+
return;
|
|
8618
|
+
}
|
|
8674
8619
|
this._upvoted.next(message);
|
|
8675
8620
|
message.transientState.liking = true;
|
|
8676
8621
|
if ((_a = message.userState) === null || _a === void 0 ? void 0 : _a.liked)
|
|
@@ -8752,6 +8697,10 @@ class BantaCommentsComponent {
|
|
|
8752
8697
|
}
|
|
8753
8698
|
deleteMessage(message) {
|
|
8754
8699
|
return __awaiter(this, void 0, void 0, function* () {
|
|
8700
|
+
if (!this.user) {
|
|
8701
|
+
yield this.showSignIn();
|
|
8702
|
+
return;
|
|
8703
|
+
}
|
|
8755
8704
|
if (!confirm("Are you sure you want to delete this comment? You cannot undo this action."))
|
|
8756
8705
|
return;
|
|
8757
8706
|
try {
|
|
@@ -8764,6 +8713,10 @@ class BantaCommentsComponent {
|
|
|
8764
8713
|
}
|
|
8765
8714
|
editMessage(source, message, newText) {
|
|
8766
8715
|
return __awaiter(this, void 0, void 0, function* () {
|
|
8716
|
+
if (!this.user) {
|
|
8717
|
+
yield this.showSignIn();
|
|
8718
|
+
return;
|
|
8719
|
+
}
|
|
8767
8720
|
try {
|
|
8768
8721
|
yield source.editMessage(message.id, newText);
|
|
8769
8722
|
}
|
|
@@ -8783,6 +8736,10 @@ class BantaCommentsComponent {
|
|
|
8783
8736
|
}
|
|
8784
8737
|
saveEdit(message, text) {
|
|
8785
8738
|
return __awaiter(this, void 0, void 0, function* () {
|
|
8739
|
+
if (!this.user) {
|
|
8740
|
+
yield this.showSignIn();
|
|
8741
|
+
return;
|
|
8742
|
+
}
|
|
8786
8743
|
try {
|
|
8787
8744
|
yield this.source.editMessage(message.id, text);
|
|
8788
8745
|
message.transientState.editing = false;
|
|
@@ -8796,7 +8753,7 @@ class BantaCommentsComponent {
|
|
|
8796
8753
|
BantaCommentsComponent.decorators = [
|
|
8797
8754
|
{ type: Component, args: [{
|
|
8798
8755
|
selector: 'banta-comments',
|
|
8799
|
-
template: "<ng-container *ngIf=\"loading\">\r\n <div class=\"loading-screen\" [class.visible]=\"showLoadingScreen\">\r\n <h1>Loading Comments</h1>\r\n <div>\r\n <mat-spinner [diameter]=\"300\" [strokeWidth]=\"2\"></mat-spinner>\r\n </div>\r\n\r\n <p class=\"loading-message\" [class.visible]=\"loadingMessageVisible\">{{loadingMessage}}</p>\r\n </div>\r\n</ng-container>\r\n<ng-container *ngIf=\"!loading\">\r\n <div class=\"focused\" [class.visible]=\"selectedMessageVisible\" *ngIf=\"selectedMessage && !useInlineReplies\">\r\n\r\n <div>\r\n <a mat-button href=\"javascript:;\" (click)=\"unselectMessage()\">\r\n <mat-icon>arrow_back</mat-icon>\r\n Latest Comments\r\n </a>\r\n </div>\r\n\r\n <banta-comment\r\n [message]=\"selectedMessage\"\r\n [liking]=\"selectedMessage.transientState.liking\"\r\n [mine]=\"user?.id === selectedMessage.user?.id\"\r\n [permissions]=\"source?.permissions\"\r\n [showReplyAction]=\"false\"\r\n [editing]=\"selectedMessage.transientState.editing\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (editStarted)=\"startEditing(selectedMessage)\"\r\n (editEnded)=\"selectedMessage.transientState.editing = false\"\r\n (edited)=\"saveEdit(selectedMessage, $event)\"\r\n (userSelected)=\"selectMessageUser(selectedMessage)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (liked)=\"likeMessage(source, selectedMessage)\"\r\n (unliked)=\"unlikeMessage(source, selectedMessage)\"\r\n (reported)=\"reportMessage(selectedMessage)\"\r\n (selected)=\"selectMessage(selectedMessage)\"\r\n (shared)=\"shareMessage($event)\"\r\n (deleted)=\"deleteMessage(selectedMessage)\"\r\n ></banta-comment>\r\n\r\n <div class=\"replies\">\r\n\r\n <ng-container *ngIf=\"!selectedMessageThread\">\r\n <div class=\"loading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedMessageThread\">\r\n <banta-comment-view\r\n [source]=\"selectedMessageThread\"\r\n [allowReplies]=\"false\"\r\n [fixedHeight]=\"false\"\r\n [showEmptyState]=\"false\"\r\n [newestLast]=\"true\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (liked)=\"likeMessage(selectedMessageThread, $event)\"\r\n (unliked)=\"unlikeMessage(selectedMessageThread, $event)\"\r\n (messageEdited)=\"editMessage(selectedMessageThread, $event.message, $event.newMessage)\"\r\n (reported)=\"reportMessage($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (shared)=\"shareMessage($event)\"\r\n (deleted)=\"deleteMessage($event)\"\r\n ></banta-comment-view>\r\n\r\n <banta-comment-field\r\n [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n (signInSelected)=\"showSignIn()\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n [source]=\"selectedMessageThread\"\r\n [maxLength]=\"maxCommentLength\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInLabel]=\"signInLabel\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [user]=\"user\"\r\n [label]=\"postReplyLabel\"\r\n [submit]=\"sendReply\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"sendReplyOptionsTemplate\"></ng-container>\r\n </banta-comment-field>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <div class=\"main\" [class.hidden]=\"selectedMessage && !useInlineReplies\">\r\n <banta-comment-field\r\n [source]=\"source\"\r\n [user]=\"user\"\r\n [sendLabel]=\"sendLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [signInLabel]=\"signInLabel\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n [label]=\"postCommentLabel\"\r\n [maxLength]=\"maxCommentLength\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n (signInSelected)=\"showSignIn()\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [submit]=\"sendMessage\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n >\r\n \r\n </banta-comment-field>\r\n\r\n <banta-comment-sort\r\n [(sort)]=\"sortOrder\"></banta-comment-sort>\r\n\r\n <banta-comment-view\r\n [class.faded]=\"selectedMessage && !useInlineReplies\"\r\n [source]=\"source\"\r\n [fixedHeight]=\"fixedHeight\"\r\n [maxMessages]=\"maxMessages\"\r\n [maxVisibleMessages]=\"maxVisibleMessages\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (userSelected)=\"selectMessageUser($event)\"\r\n (sortOrderChanged)=\"sortOrder = $event\"\r\n (selected)=\"selectMessage($event)\"\r\n (liked)=\"likeMessage(source, $event)\"\r\n (unliked)=\"unlikeMessage(source, $event)\"\r\n (messageEdited)=\"editMessage(source, $event.message, $event.newMessage)\"\r\n (reported)=\"reportMessage($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (shared)=\"shareMessage($event)\"\r\n [selectedMessage]=\"selectedMessage\"\r\n (deleted)=\"deleteMessage($event)\"\r\n >\r\n <div class=\"inline-replies\">\r\n <div class=\"focused\" [class.visible]=\"selectedMessageVisible\" *ngIf=\"selectedMessage\">\r\n <div class=\"replies\">\r\n \r\n <ng-container *ngIf=\"!selectedMessageThread\">\r\n <div class=\"loading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n </ng-container>\r\n \r\n <ng-container *ngIf=\"selectedMessageThread\">\r\n <banta-comment-view\r\n [source]=\"selectedMessageThread\"\r\n [allowReplies]=\"false\"\r\n [fixedHeight]=\"false\"\r\n [showEmptyState]=\"false\"\r\n [newestLast]=\"true\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (liked)=\"likeMessage(selectedMessageThread, $event)\"\r\n (unliked)=\"unlikeMessage(selectedMessageThread, $event)\"\r\n (messageEdited)=\"editMessage(selectedMessageThread, $event.message, $event.newMessage)\"\r\n (reported)=\"reportMessage($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (shared)=\"shareMessage($event)\"\r\n (deleted)=\"deleteMessage($event)\"\r\n ></banta-comment-view>\r\n \r\n <banta-comment-field\r\n [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n (signInSelected)=\"showSignIn()\"\r\n [maxLength]=\"maxCommentLength\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n [source]=\"selectedMessageThread\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInLabel]=\"signInLabel\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [user]=\"user\"\r\n [label]=\"postReplyLabel\"\r\n [submit]=\"sendReply\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"sendReplyOptionsTemplate\"></ng-container>\r\n </banta-comment-field>\r\n </ng-container>\r\n </div>\r\n </div> \r\n </div>\r\n </banta-comment-view>\r\n </div>\r\n</ng-container>\r\n",
|
|
8756
|
+
template: "<ng-container *ngIf=\"loading\">\r\n <div class=\"loading-screen\" [class.visible]=\"showLoadingScreen\">\r\n <h1>Loading...</h1>\r\n <div>\r\n <mat-spinner [diameter]=\"300\" [strokeWidth]=\"2\"></mat-spinner>\r\n </div>\r\n\r\n <p class=\"loading-message\" [class.visible]=\"loadingMessageVisible\">{{loadingMessage}}</p>\r\n </div>\r\n</ng-container>\r\n<ng-container *ngIf=\"!loading\">\r\n <div class=\"focused\" [class.visible]=\"selectedMessageVisible\" *ngIf=\"selectedMessage && !useInlineReplies\">\r\n\r\n <div>\r\n <a mat-button href=\"javascript:;\" (click)=\"unselectMessage()\">\r\n <mat-icon>arrow_back</mat-icon>\r\n Latest Comments\r\n </a>\r\n </div>\r\n\r\n <banta-comment\r\n [message]=\"selectedMessage\"\r\n [liking]=\"selectedMessage.transientState.liking\"\r\n [mine]=\"user?.id === selectedMessage.user?.id\"\r\n [permissions]=\"source?.permissions\"\r\n [showReplyAction]=\"false\"\r\n [editing]=\"selectedMessage.transientState.editing\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (editStarted)=\"startEditing(selectedMessage)\"\r\n (editEnded)=\"selectedMessage.transientState.editing = false\"\r\n (edited)=\"saveEdit(selectedMessage, $event)\"\r\n (userSelected)=\"selectMessageUser(selectedMessage)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (liked)=\"likeMessage(source, selectedMessage)\"\r\n (unliked)=\"unlikeMessage(source, selectedMessage)\"\r\n (reported)=\"reportMessage(selectedMessage)\"\r\n (selected)=\"selectMessage(selectedMessage)\"\r\n (shared)=\"shareMessage($event)\"\r\n (deleted)=\"deleteMessage(selectedMessage)\"\r\n ></banta-comment>\r\n\r\n <div class=\"replies\">\r\n\r\n <ng-container *ngIf=\"!selectedMessageThread\">\r\n <div class=\"loading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"selectedMessageThread\">\r\n <banta-comment-view\r\n [source]=\"selectedMessageThread\"\r\n [allowReplies]=\"false\"\r\n [fixedHeight]=\"false\"\r\n [showEmptyState]=\"false\"\r\n [newestLast]=\"true\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (liked)=\"likeMessage(selectedMessageThread, $event)\"\r\n (unliked)=\"unlikeMessage(selectedMessageThread, $event)\"\r\n (messageEdited)=\"editMessage(selectedMessageThread, $event.message, $event.newMessage)\"\r\n (reported)=\"reportMessage($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (shared)=\"shareMessage($event)\"\r\n (deleted)=\"deleteMessage($event)\"\r\n ></banta-comment-view>\r\n\r\n <banta-comment-field\r\n [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n (signInSelected)=\"showSignIn()\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n [source]=\"selectedMessageThread\"\r\n [maxLength]=\"maxCommentLength\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInLabel]=\"signInLabel\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [user]=\"user\"\r\n [label]=\"postReplyLabel\"\r\n [submit]=\"sendReply\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"sendReplyOptionsTemplate\"></ng-container>\r\n </banta-comment-field>\r\n </ng-container>\r\n </div>\r\n </div>\r\n\r\n <div class=\"main\" [class.hidden]=\"selectedMessage && !useInlineReplies\">\r\n <banta-comment-field\r\n [source]=\"source\"\r\n [user]=\"user\"\r\n [sendLabel]=\"sendLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [signInLabel]=\"signInLabel\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n [label]=\"postCommentLabel\"\r\n [maxLength]=\"maxCommentLength\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n (signInSelected)=\"showSignIn()\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [submit]=\"sendMessage\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n >\r\n \r\n </banta-comment-field>\r\n\r\n <banta-comment-sort\r\n [(sort)]=\"sortOrder\"></banta-comment-sort>\r\n\r\n <banta-comment-view\r\n [class.faded]=\"selectedMessage && !useInlineReplies\"\r\n [source]=\"source\"\r\n [fixedHeight]=\"fixedHeight\"\r\n [maxMessages]=\"maxMessages\"\r\n [maxVisibleMessages]=\"maxVisibleMessages\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (userSelected)=\"selectMessageUser($event)\"\r\n (sortOrderChanged)=\"sortOrder = $event\"\r\n (selected)=\"selectMessage($event)\"\r\n (liked)=\"likeMessage(source, $event)\"\r\n (unliked)=\"unlikeMessage(source, $event)\"\r\n (messageEdited)=\"editMessage(source, $event.message, $event.newMessage)\"\r\n (reported)=\"reportMessage($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (shared)=\"shareMessage($event)\"\r\n [selectedMessage]=\"selectedMessage\"\r\n (deleted)=\"deleteMessage($event)\"\r\n >\r\n <div class=\"inline-replies\">\r\n <div class=\"focused\" [class.visible]=\"selectedMessageVisible\" *ngIf=\"selectedMessage\">\r\n <div class=\"replies\">\r\n \r\n <ng-container *ngIf=\"!selectedMessageThread\">\r\n <div class=\"loading\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n </ng-container>\r\n \r\n <ng-container *ngIf=\"selectedMessageThread\">\r\n <banta-comment-view\r\n [source]=\"selectedMessageThread\"\r\n [allowReplies]=\"false\"\r\n [fixedHeight]=\"false\"\r\n [showEmptyState]=\"false\"\r\n [newestLast]=\"true\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n (liked)=\"likeMessage(selectedMessageThread, $event)\"\r\n (unliked)=\"unlikeMessage(selectedMessageThread, $event)\"\r\n (messageEdited)=\"editMessage(selectedMessageThread, $event.message, $event.newMessage)\"\r\n (reported)=\"reportMessage($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (shared)=\"shareMessage($event)\"\r\n (deleted)=\"deleteMessage($event)\"\r\n ></banta-comment-view>\r\n \r\n <banta-comment-field\r\n [sendLabel]=\"replyLabel\"\r\n [sendingLabel]=\"sendingLabel\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n (signInSelected)=\"showSignIn()\"\r\n [maxLength]=\"maxCommentLength\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n [source]=\"selectedMessageThread\"\r\n [canComment]=\"source?.permissions?.canPost\"\r\n [signInLabel]=\"signInLabel\"\r\n [permissionDeniedLabel]=\"source?.permissions?.canPostErrorMessage || permissionDeniedLabel\"\r\n (permissionDeniedError)=\"handlePermissionDenied($event)\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [user]=\"user\"\r\n [label]=\"postReplyLabel\"\r\n [submit]=\"sendReply\"\r\n [allowAttachments]=\"allowAttachments\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n >\r\n <ng-container *ngTemplateOutlet=\"sendReplyOptionsTemplate\"></ng-container>\r\n </banta-comment-field>\r\n </ng-container>\r\n </div>\r\n </div> \r\n </div>\r\n </banta-comment-view>\r\n </div>\r\n</ng-container>\r\n",
|
|
8800
8757
|
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%}"]
|
|
8801
8758
|
},] }
|
|
8802
8759
|
];
|
|
@@ -8913,6 +8870,7 @@ LiveCommentComponent.propDecorators = {
|
|
|
8913
8870
|
class CommentFieldComponent {
|
|
8914
8871
|
constructor(chatBackend) {
|
|
8915
8872
|
this.chatBackend = chatBackend;
|
|
8873
|
+
this._subs = new Subscription();
|
|
8916
8874
|
this.canComment = true;
|
|
8917
8875
|
this.allowAttachments = false;
|
|
8918
8876
|
this.signInSelected = new Subject();
|
|
@@ -8937,6 +8895,35 @@ class CommentFieldComponent {
|
|
|
8937
8895
|
this.autoCompleteSelected = 0;
|
|
8938
8896
|
this.chatMessageAttachments = [];
|
|
8939
8897
|
}
|
|
8898
|
+
get source() {
|
|
8899
|
+
return this._source;
|
|
8900
|
+
}
|
|
8901
|
+
set source(value) {
|
|
8902
|
+
var _a;
|
|
8903
|
+
if (this._source) {
|
|
8904
|
+
(_a = this._subs) === null || _a === void 0 ? void 0 : _a.unsubscribe();
|
|
8905
|
+
this._source = null;
|
|
8906
|
+
}
|
|
8907
|
+
this._source = value;
|
|
8908
|
+
this._subs = new Subscription();
|
|
8909
|
+
if (this._source) {
|
|
8910
|
+
setTimeout(() => {
|
|
8911
|
+
if (this._source.connectionStateChanged) {
|
|
8912
|
+
this._subs.add(this._source.connectionStateChanged.subscribe(state => {
|
|
8913
|
+
if (state === 'lost') {
|
|
8914
|
+
this.transientMessage = `Reconnecting...`;
|
|
8915
|
+
}
|
|
8916
|
+
else if (state === 'restored') {
|
|
8917
|
+
this.transientMessage = undefined;
|
|
8918
|
+
}
|
|
8919
|
+
else if (state === 'connecting') {
|
|
8920
|
+
this.transientMessage = `Connecting...`;
|
|
8921
|
+
}
|
|
8922
|
+
}));
|
|
8923
|
+
}
|
|
8924
|
+
});
|
|
8925
|
+
}
|
|
8926
|
+
}
|
|
8940
8927
|
get text() {
|
|
8941
8928
|
return this._text;
|
|
8942
8929
|
}
|
|
@@ -9251,8 +9238,8 @@ class CommentFieldComponent {
|
|
|
9251
9238
|
CommentFieldComponent.decorators = [
|
|
9252
9239
|
{ type: Component, args: [{
|
|
9253
9240
|
selector: 'banta-comment-field',
|
|
9254
|
-
template: "<form class=\"new-message\" (submit)=\"sendMessage()\">\r\n <div class=\"avatar-container\">\r\n <a href=\"javascript:;\"\r\n class=\"avatar\"\r\n (click)=\"showEditAvatar()\"\r\n [style.background-image]=\"'url(' + userAvatarUrl + ')'\"\r\n ></a>\r\n </div>\r\n <div class=\"text-container\">\r\n <div class=\"field-container\">\r\n <div class=\"field-row\">\r\n <mat-form-field appearance=\"outline\" floatLabel=\"always\">\r\n <mat-label>{{label}}</mat-label>\r\n <textarea\r\n #textarea\r\n name=\"message\"\r\n [placeholder]=\"placeholder\"\r\n matInput\r\n cdkTextareaAutosize\r\n [maxlength]=\"maxLength\"\r\n (keydown)=\"onKeyDown($event)\"\r\n (blur)=\"onBlur()\"\r\n [disabled]=\"sending\"\r\n [(ngModel)]=\"text\"></textarea>\r\n </mat-form-field>\r\n <div class=\"options-line\">\r\n <mat-spinner *ngIf=\"sending\" class=\"icon loading\" diameter=\"18\" strokeWidth=\"2\"></mat-spinner>\r\n <div *ngIf=\"sendError\" class=\"error-message\" [class.expanded]=\"expandError\" [matTooltip]=\"sendError.message\" (click)=\"alertError()\">\r\n <mat-icon *ngIf=\"sendError\">error</mat-icon>\r\n {{sendError.message}}\r\n </div>\r\n <div class=\"spacer\"></div>\r\n <div class=\"custom\">\r\n <ng-content></ng-content>\r\n </div>\r\n <banta-attachment-button \r\n *ngIf=\"allowAttachments\"\r\n (addedAttachment)=\"addedAttachment($event)\"\r\n (attachmentError)=\"attachmentError($event)\"\r\n ></banta-attachment-button>\r\n <emoji-selector-button (selected)=\"insertEmoji($event)\"></emoji-selector-button>\r\n </div>\r\n \r\n </div>\r\n <div #autocompleteContainer class=\"autocomplete-container\">\r\n <div #autocomplete class=\"autocomplete\" [class.visible]=\"autocompleteVisible\">\r\n\r\n <div>\r\n <strong>{{completionPrefix}}</strong>...\r\n </div>\r\n <a\r\n mat-button\r\n *ngFor=\"let option of autocompleteOptions; index as index\"\r\n (click)=\"activateAutoComplete(option)\"\r\n [class.active]=\"autoCompleteSelected === index\"\r\n >\r\n {{option.label}}\r\n </a>\r\n </div>\r\n </div>\r\n\r\n <banta-attachments \r\n [attachments]=\"chatMessageAttachments\"\r\n [editing]=\"true\"\r\n (remove)=\"removeAttachment($event)\"\r\n ></banta-attachments>\r\n </div>\r\n </div>\r\n <div class=\"actions\">\r\n <ng-container *ngIf=\"!user\">\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n type=\"button\"\r\n (click)=\"showSignIn()\"\r\n >{{signInLabel}}</button>\r\n </ng-container>\r\n <ng-container *ngIf=\"user\">\r\n <button\r\n mat-raised-button\r\n class=\"send\"\r\n color=\"primary\"\r\n [disabled]=\"!sendButtonEnabled\"\r\n >\r\n <ng-container *ngIf=\"canComment\">\r\n <mat-icon *ngIf=\"!sending\">chevron_right</mat-icon>\r\n <mat-spinner *ngIf=\"sending\" class=\"icon\" diameter=\"18\" strokeWidth=\"2\"></mat-spinner>\r\n </ng-container>\r\n <span class=\"label\">\r\n <ng-container *ngIf=\"!canComment\">\r\n {{permissionDeniedLabel}}\r\n </ng-container>\r\n <ng-container *ngIf=\"canComment\">\r\n <ng-container *ngIf=\"!sending\">\r\n {{sendLabel}}\r\n </ng-container>\r\n <ng-container *ngIf=\"sending\">\r\n {{sendingLabel}}\r\n </ng-container>\r\n </ng-container>\r\n </span>\r\n </button>\r\n </ng-container>\r\n </div>\r\n</form>",
|
|
9255
|
-
styles: ["@-webkit-keyframes comment-field-appear{0%{transform:translateY(128px);opacity:0}to{transform:translate(0);opacity:1}}@keyframes comment-field-appear{0%{transform:translateY(128px);opacity:0}to{transform:translate(0);opacity:1}}:host{margin:0 2em 0 0;display:block;-webkit-animation-name:comment-field-appear;animation-name:comment-field-appear;-webkit-animation-duration:.8s;animation-duration:.8s;-webkit-animation-delay:.4s;animation-delay:.4s;-webkit-animation-fill-mode:both;animation-fill-mode:both;position:relative;z-index:20}.avatar-container{width:calc(48px + 1.75em);display:flex;justify-content:flex-end;flex-shrink:0}.avatar-container .avatar{width:48px;height:48px;background:#000;border-radius:100%;background-size:cover;background-repeat:no-repeat;background-position:50%;margin-top:.75em;margin-right:.75em}form{display:flex;padding:.5em;align-items:center}form .text-container{position:relative;display:flex;flex-grow:1;min-width:0}form .text-container textarea{font-size:14pt;width:100%}form .text-container textarea[disabled]{opacity:.5}form .text-container mat-spinner.loading{position:absolute;left:.5em;bottom:.5em}form .text-container .options-line{display:flex;align-items:center}form .text-container .options-line>*{flex-shrink:0}form .text-container .options-line .error-message{left:.5em;bottom:.5em;color:#683333;overflow-x:hidden;max-width:1.5em;white-space:nowrap;transition:max-width 2s ease-in-out;text-overflow:ellipsis;overflow:hidden;flex-shrink:1}form .text-container .options-line .error-message.expanded,form .text-container .options-line .error-message:hover{max-width:100%}form .text-container .options-line .error-message mat-icon{vertical-align:middle}form input[type=text]{background:#000;color:#fff;border:1px solid #333;width:100%;height:1em}form .actions{margin-left:1em;flex-shrink:0}form button{display:block;margin:0 0 0 auto}form.new-message{display:flex;align-items:flex-start;min-width:0}form.new-message .field-container{flex-grow:1;display:flex;flex-direction:column;min-width:0}form.new-message mat-form-field{width:100%}form.new-message mat-form-field ::ng-deep .mat-form-field-wrapper{padding-bottom:0}form.new-message button{margin:1.25em 0 0}button.send{min-width:9em}textarea{max-height:7em}.autocomplete-container{width:calc(100% - 2em);position:relative;pointer-events:none;top:-2em}.autocomplete{visibility:hidden;pointer-events:none;position:absolute;background:#333;padding:.5em;display:flex;flex-direction:column;z-index:100}.autocomplete.visible{visibility:visible;pointer-events:auto}.autocomplete a{width:100%;text-align:left}.autocomplete a.active{background:#555}
|
|
9241
|
+
template: "<form class=\"new-message\" (submit)=\"sendMessage()\">\r\n <div class=\"avatar-container\">\r\n <a href=\"javascript:;\"\r\n class=\"avatar\"\r\n (click)=\"showEditAvatar()\"\r\n [style.background-image]=\"'url(' + userAvatarUrl + ')'\"\r\n ></a>\r\n </div>\r\n <div class=\"text-container\">\r\n <div class=\"field-container\">\r\n <div class=\"field-row\">\r\n <mat-form-field class=\"message-field\" appearance=\"outline\" floatLabel=\"always\">\r\n <mat-label>{{label}}</mat-label>\r\n <textarea\r\n #textarea\r\n name=\"message\"\r\n [placeholder]=\"placeholder\"\r\n matInput\r\n cdkTextareaAutosize\r\n [maxlength]=\"maxLength\"\r\n (keydown)=\"onKeyDown($event)\"\r\n (blur)=\"onBlur()\"\r\n [disabled]=\"sending\"\r\n [(ngModel)]=\"text\"></textarea>\r\n </mat-form-field>\r\n <div class=\"options-line\">\r\n <mat-spinner *ngIf=\"sending\" class=\"icon loading\" diameter=\"18\" strokeWidth=\"2\"></mat-spinner>\r\n <div *ngIf=\"sendError\" class=\"error-message\" [class.expanded]=\"expandError\" [matTooltip]=\"sendError.message\" (click)=\"alertError()\">\r\n <mat-icon *ngIf=\"sendError\">error</mat-icon>\r\n {{sendError.message}}\r\n </div>\r\n <div *ngIf=\"!sendError && transientMessage\" class=\"transient-message\" [class.expanded]=\"true\" [matTooltip]=\"transientMessage\" (click)=\"alertError()\">\r\n <mat-spinner [inline]=\"true\" [diameter]=\"15\"></mat-spinner>\r\n {{transientMessage}}\r\n </div>\r\n <div class=\"spacer\"></div>\r\n <div class=\"custom\">\r\n <ng-content></ng-content>\r\n </div>\r\n <banta-attachment-button \r\n *ngIf=\"allowAttachments\"\r\n (addedAttachment)=\"addedAttachment($event)\"\r\n (attachmentError)=\"attachmentError($event)\"\r\n ></banta-attachment-button>\r\n <emoji-selector-button (selected)=\"insertEmoji($event)\"></emoji-selector-button>\r\n </div>\r\n \r\n </div>\r\n <div #autocompleteContainer class=\"autocomplete-container\">\r\n <div #autocomplete class=\"autocomplete\" [class.visible]=\"autocompleteVisible\">\r\n\r\n <div>\r\n <strong>{{completionPrefix}}</strong>...\r\n </div>\r\n <a\r\n mat-button\r\n *ngFor=\"let option of autocompleteOptions; index as index\"\r\n (click)=\"activateAutoComplete(option)\"\r\n [class.active]=\"autoCompleteSelected === index\"\r\n >\r\n {{option.label}}\r\n </a>\r\n </div>\r\n </div>\r\n\r\n <banta-attachments \r\n [attachments]=\"chatMessageAttachments\"\r\n [editing]=\"true\"\r\n (remove)=\"removeAttachment($event)\"\r\n ></banta-attachments>\r\n </div>\r\n </div>\r\n <div class=\"actions\">\r\n <ng-container *ngIf=\"!user\">\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n type=\"button\"\r\n (click)=\"showSignIn()\"\r\n >{{signInLabel}}</button>\r\n </ng-container>\r\n <ng-container *ngIf=\"user\">\r\n <button\r\n mat-raised-button\r\n class=\"send\"\r\n color=\"primary\"\r\n [disabled]=\"!sendButtonEnabled\"\r\n >\r\n <ng-container *ngIf=\"canComment\">\r\n <mat-icon *ngIf=\"!sending\">chevron_right</mat-icon>\r\n <mat-spinner *ngIf=\"sending\" class=\"icon\" diameter=\"18\" strokeWidth=\"2\"></mat-spinner>\r\n </ng-container>\r\n <span class=\"label\">\r\n <ng-container *ngIf=\"!canComment\">\r\n {{permissionDeniedLabel}}\r\n </ng-container>\r\n <ng-container *ngIf=\"canComment\">\r\n <ng-container *ngIf=\"!sending\">\r\n {{sendLabel}}\r\n </ng-container>\r\n <ng-container *ngIf=\"sending\">\r\n {{sendingLabel}}\r\n </ng-container>\r\n </ng-container>\r\n </span>\r\n </button>\r\n </ng-container>\r\n </div>\r\n</form>",
|
|
9242
|
+
styles: ["@-webkit-keyframes comment-field-appear{0%{transform:translateY(128px);opacity:0}to{transform:translate(0);opacity:1}}@keyframes comment-field-appear{0%{transform:translateY(128px);opacity:0}to{transform:translate(0);opacity:1}}:host{margin:0 2em 0 0;display:block;-webkit-animation-name:comment-field-appear;animation-name:comment-field-appear;-webkit-animation-duration:.8s;animation-duration:.8s;-webkit-animation-delay:.4s;animation-delay:.4s;-webkit-animation-fill-mode:both;animation-fill-mode:both;position:relative;z-index:20}.avatar-container{width:calc(48px + 1.75em);display:flex;justify-content:flex-end;flex-shrink:0}.avatar-container .avatar{width:48px;height:48px;background:#000;border-radius:100%;background-size:cover;background-repeat:no-repeat;background-position:50%;margin-top:.75em;margin-right:.75em}form{display:flex;padding:.5em;align-items:center}form .text-container{position:relative;display:flex;flex-grow:1;min-width:0}form .text-container textarea{font-size:14pt;width:100%}form .text-container textarea[disabled]{opacity:.5}form .text-container mat-spinner.loading{position:absolute;left:.5em;bottom:.5em}form .text-container .options-line{display:flex;align-items:center}form .text-container .options-line>*{flex-shrink:0}form .text-container .options-line .transient-message{display:flex;flex-direction:row;align-items:center;gap:.5em}form .text-container .options-line .error-message{left:.5em;bottom:.5em;color:#683333;overflow-x:hidden;max-width:1.5em;white-space:nowrap;transition:max-width 2s ease-in-out;text-overflow:ellipsis;overflow:hidden;flex-shrink:1}form .text-container .options-line .error-message.expanded,form .text-container .options-line .error-message:hover{max-width:100%}form .text-container .options-line .error-message mat-icon{vertical-align:middle}form input[type=text]{background:#000;color:#fff;border:1px solid #333;width:100%;height:1em}form .actions{margin-left:1em;flex-shrink:0}form button{display:block;margin:0 0 0 auto}form.new-message{display:flex;align-items:flex-start;min-width:0}form.new-message .field-container{flex-grow:1;display:flex;flex-direction:column;min-width:0}form.new-message mat-form-field{width:100%}form.new-message mat-form-field ::ng-deep .mat-form-field-wrapper{padding-bottom:0}form.new-message button{margin:1.25em 0 0}button.send{min-width:9em}textarea{max-height:7em}.autocomplete-container{width:calc(100% - 2em);position:relative;pointer-events:none;top:-2em}.autocomplete{visibility:hidden;pointer-events:none;position:absolute;background:#333;padding:.5em;display:flex;flex-direction:column;z-index:100}.autocomplete.visible{visibility:visible;pointer-events:auto}.autocomplete a{width:100%;text-align:left}.autocomplete a.active{background:#555}.image-attachments-container{display:flex;gap:20px}.image-attachments-container .image-attachment{width:300px;position:relative;text-align:center}.image-attachments-container .image-attachment.with-border{outline:1px solid #333;padding:1em 0}.image-attachments-container .image-attachment mat-spinner{display:block;margin:0 auto .5em;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.image-attachments-container .image-attachment mat-icon.error{display:block;font-size:48px;width:48px;height:48px;margin:0 auto .5em}.image-attachments-container .image-attachment .error{color:#b76363}.image-attachments-container .image-attachment img{width:300px;border-radius:10px}.image-attachments-container .image-attachment .remove-img{position:absolute;right:10px;top:10px;margin:0}.card-attachment,.field-row{position:relative}.card-attachment a{display:flex;align-items:flex-start;gap:1em;width:100%;border:1px solid #666;border-radius:4px;padding:2em;box-sizing:border-box;background-color:#191919}.card-attachment a img{width:300px;aspect-ratio:16/9;-o-object-fit:cover;object-fit:cover;border-radius:10px}.card-attachment a h1{margin:0;font-size:30px}.card-attachment .remove-img{position:absolute;right:10px;top:10px;margin:0}@media (max-width:500px){:host{margin:0}.avatar-container{width:auto;flex-shrink:0}.avatar-container .avatar{width:32px;height:32px;margin-top:1.5em}:host.can-comment button.send .label,:host:not(.can-comment) .text-container,:host:not(.can-comment) mat-form-field.message-field{display:none}button.send{min-width:auto;margin-top:1.5em}}:host-context(.banta-mobile) :host{margin:0}:host-context(.banta-mobile) .avatar-container{width:auto;flex-shrink:0}:host-context(.banta-mobile) .avatar-container .avatar{width:32px;height:32px;margin-top:1.5em}:host-context(.banta-mobile) :host.can-comment button.send .label,:host-context(.banta-mobile) :host:not(.can-comment) .text-container,:host-context(.banta-mobile) :host:not(.can-comment) mat-form-field.message-field{display:none}:host-context(.banta-mobile) button.send{min-width:auto;margin-top:1.5em}"]
|
|
9256
9243
|
},] }
|
|
9257
9244
|
];
|
|
9258
9245
|
CommentFieldComponent.ctorParameters = () => [
|
|
@@ -9261,10 +9248,11 @@ CommentFieldComponent.ctorParameters = () => [
|
|
|
9261
9248
|
CommentFieldComponent.propDecorators = {
|
|
9262
9249
|
source: [{ type: Input }],
|
|
9263
9250
|
user: [{ type: Input }],
|
|
9264
|
-
canComment: [{ type: Input }],
|
|
9251
|
+
canComment: [{ type: HostBinding, args: ['class.can-comment',] }, { type: Input }],
|
|
9265
9252
|
allowAttachments: [{ type: Input }],
|
|
9266
9253
|
signInSelected: [{ type: Output }],
|
|
9267
9254
|
editAvatarSelected: [{ type: Output }],
|
|
9255
|
+
transientMessage: [{ type: Input }],
|
|
9268
9256
|
sendLabel: [{ type: Input }],
|
|
9269
9257
|
sendingLabel: [{ type: Input }],
|
|
9270
9258
|
label: [{ type: Input }],
|
|
@@ -9425,7 +9413,8 @@ class ChatSource extends SocketRPC {
|
|
|
9425
9413
|
this.parentIdentifier = parentIdentifier;
|
|
9426
9414
|
this.sortOrder = sortOrder;
|
|
9427
9415
|
this.subscription = new Subscription();
|
|
9428
|
-
this.
|
|
9416
|
+
this._state = 'connecting';
|
|
9417
|
+
this._connectionStateChanged = new Subject();
|
|
9429
9418
|
this.messageMap = new Map();
|
|
9430
9419
|
this._messageReceived = new Subject();
|
|
9431
9420
|
this._messageUpdated = new Subject();
|
|
@@ -9433,6 +9422,16 @@ class ChatSource extends SocketRPC {
|
|
|
9433
9422
|
this.messages = [];
|
|
9434
9423
|
this.ready = new Promise(resolve => this.markReady = resolve);
|
|
9435
9424
|
}
|
|
9425
|
+
get state() {
|
|
9426
|
+
return this._state;
|
|
9427
|
+
}
|
|
9428
|
+
set state(value) {
|
|
9429
|
+
this._state = value;
|
|
9430
|
+
setTimeout(() => this._connectionStateChanged.next(this._state));
|
|
9431
|
+
}
|
|
9432
|
+
get connectionStateChanged() {
|
|
9433
|
+
return this._connectionStateChanged.asObservable();
|
|
9434
|
+
}
|
|
9436
9435
|
bind(socket) {
|
|
9437
9436
|
const _super = Object.create(null, {
|
|
9438
9437
|
bind: { get: () => super.bind }
|
|
@@ -9471,9 +9470,21 @@ class ChatSource extends SocketRPC {
|
|
|
9471
9470
|
return messages;
|
|
9472
9471
|
});
|
|
9473
9472
|
}
|
|
9473
|
+
ensureConnection(errorMessage) {
|
|
9474
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9475
|
+
let reason = `Connection to chat services is not currently available.`;
|
|
9476
|
+
if (this.state !== 'connected' && this.state !== 'restored') {
|
|
9477
|
+
if (errorMessage)
|
|
9478
|
+
throw new Error(`${errorMessage}: ${reason}`);
|
|
9479
|
+
else
|
|
9480
|
+
throw new Error(`${reason}`);
|
|
9481
|
+
}
|
|
9482
|
+
});
|
|
9483
|
+
}
|
|
9474
9484
|
editMessage(messageId, text) {
|
|
9475
9485
|
return __awaiter(this, void 0, void 0, function* () {
|
|
9476
|
-
this.
|
|
9486
|
+
yield this.ensureConnection();
|
|
9487
|
+
yield this.peer.editMessage(messageId, text);
|
|
9477
9488
|
});
|
|
9478
9489
|
}
|
|
9479
9490
|
subscribeToTopic() {
|
|
@@ -9521,6 +9532,7 @@ class ChatSource extends SocketRPC {
|
|
|
9521
9532
|
get messageSent() { return this._messageSent.asObservable(); }
|
|
9522
9533
|
send(message) {
|
|
9523
9534
|
return __awaiter(this, void 0, void 0, function* () {
|
|
9535
|
+
yield this.ensureConnection();
|
|
9524
9536
|
return yield this.peer.sendMessage(message);
|
|
9525
9537
|
});
|
|
9526
9538
|
}
|
|
@@ -9537,6 +9549,7 @@ class ChatSource extends SocketRPC {
|
|
|
9537
9549
|
return __awaiter(this, void 0, void 0, function* () {
|
|
9538
9550
|
if (this.messageMap.has(id))
|
|
9539
9551
|
return this.messageMap.get(id);
|
|
9552
|
+
yield this.ensureConnection(`Could not get message`);
|
|
9540
9553
|
let message = yield this.peer.getMessage(id);
|
|
9541
9554
|
this.messageMap.set(id, message);
|
|
9542
9555
|
return message;
|
|
@@ -9549,16 +9562,19 @@ class ChatSource extends SocketRPC {
|
|
|
9549
9562
|
}
|
|
9550
9563
|
likeMessage(messageId) {
|
|
9551
9564
|
return __awaiter(this, void 0, void 0, function* () {
|
|
9565
|
+
yield this.ensureConnection();
|
|
9552
9566
|
return yield this.peer.likeMessage(messageId);
|
|
9553
9567
|
});
|
|
9554
9568
|
}
|
|
9555
9569
|
unlikeMessage(messageId) {
|
|
9556
9570
|
return __awaiter(this, void 0, void 0, function* () {
|
|
9571
|
+
yield this.ensureConnection();
|
|
9557
9572
|
return yield this.peer.unlikeMessage(messageId);
|
|
9558
9573
|
});
|
|
9559
9574
|
}
|
|
9560
9575
|
deleteMessage(messageId) {
|
|
9561
9576
|
return __awaiter(this, void 0, void 0, function* () {
|
|
9577
|
+
yield this.ensureConnection();
|
|
9562
9578
|
return yield this.peer.deleteMessage(messageId);
|
|
9563
9579
|
});
|
|
9564
9580
|
}
|
|
@@ -9664,7 +9680,123 @@ ChatBackend.ctorParameters = () => [
|
|
|
9664
9680
|
{ type: undefined, decorators: [{ type: Inject, args: [BANTA_SDK_OPTIONS,] }] }
|
|
9665
9681
|
];
|
|
9666
9682
|
|
|
9683
|
+
const URL_REGEX = new RegExp('(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?', 'ig');
|
|
9684
|
+
class UrlAttachmentScraper {
|
|
9685
|
+
findFragments(message) {
|
|
9686
|
+
var _a;
|
|
9687
|
+
// If a message already has a URL attachment, don't add another one.
|
|
9688
|
+
if (message.attachments && message.attachments.filter(x => x.type === 'url').length > 0)
|
|
9689
|
+
return null;
|
|
9690
|
+
return (Array.from((_a = message.message.match(URL_REGEX)) !== null && _a !== void 0 ? _a : []))
|
|
9691
|
+
.reduce((a, item) => (a.includes(item) ? undefined : a.push(item), a), [])
|
|
9692
|
+
.map(url => ({
|
|
9693
|
+
text: url,
|
|
9694
|
+
offset: message.message.indexOf(url),
|
|
9695
|
+
type: 'url'
|
|
9696
|
+
}));
|
|
9697
|
+
}
|
|
9698
|
+
}
|
|
9699
|
+
class UrlAttachmentResolver {
|
|
9700
|
+
constructor(backend) {
|
|
9701
|
+
this.backend = backend;
|
|
9702
|
+
}
|
|
9703
|
+
resolveFragment(message, fragment) {
|
|
9704
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9705
|
+
if (fragment.type !== 'url')
|
|
9706
|
+
return null;
|
|
9707
|
+
let urlCard = yield this.backend.getCardForUrl(fragment.text);
|
|
9708
|
+
if (urlCard) {
|
|
9709
|
+
return {
|
|
9710
|
+
type: 'card',
|
|
9711
|
+
url: fragment.text,
|
|
9712
|
+
card: urlCard,
|
|
9713
|
+
style: 'block'
|
|
9714
|
+
};
|
|
9715
|
+
}
|
|
9716
|
+
});
|
|
9717
|
+
}
|
|
9718
|
+
}
|
|
9719
|
+
UrlAttachmentResolver.decorators = [
|
|
9720
|
+
{ type: Injectable }
|
|
9721
|
+
];
|
|
9722
|
+
UrlAttachmentResolver.ctorParameters = () => [
|
|
9723
|
+
{ type: ChatBackendBase }
|
|
9724
|
+
];
|
|
9725
|
+
|
|
9726
|
+
class YouTubeAttachmentResolver {
|
|
9727
|
+
resolveFragment(message, fragment) {
|
|
9728
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9729
|
+
if (fragment.type !== 'url')
|
|
9730
|
+
return null;
|
|
9731
|
+
let videoId;
|
|
9732
|
+
if (fragment.text.match(/https?:\/\/(www\.)?youtube.com\/watch\?v=/)) {
|
|
9733
|
+
let match = /watch\?v=([^&]+)/.exec(fragment.text);
|
|
9734
|
+
if (match) {
|
|
9735
|
+
videoId = match[1];
|
|
9736
|
+
}
|
|
9737
|
+
}
|
|
9738
|
+
if (videoId) {
|
|
9739
|
+
return {
|
|
9740
|
+
type: 'iframe',
|
|
9741
|
+
url: `https://www.youtube.com/embed/${videoId}`,
|
|
9742
|
+
style: 'block'
|
|
9743
|
+
};
|
|
9744
|
+
}
|
|
9745
|
+
return null;
|
|
9746
|
+
});
|
|
9747
|
+
}
|
|
9748
|
+
}
|
|
9749
|
+
|
|
9750
|
+
class GiphyAttachmentResolver {
|
|
9751
|
+
resolveFragment(message, fragment) {
|
|
9752
|
+
var _a;
|
|
9753
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9754
|
+
if (fragment.type === 'url' && fragment.text.startsWith('https://giphy.com/gifs')) {
|
|
9755
|
+
let gifId = (_a = /[^-\/]+$/.exec(fragment.text)) === null || _a === void 0 ? void 0 : _a.toString();
|
|
9756
|
+
if (!gifId)
|
|
9757
|
+
return null;
|
|
9758
|
+
return {
|
|
9759
|
+
type: 'iframe',
|
|
9760
|
+
url: `https://giphy.com/embed/${gifId}`,
|
|
9761
|
+
style: 'inline'
|
|
9762
|
+
};
|
|
9763
|
+
}
|
|
9764
|
+
return null;
|
|
9765
|
+
});
|
|
9766
|
+
}
|
|
9767
|
+
}
|
|
9768
|
+
|
|
9769
|
+
class TweetAttachmentResolver {
|
|
9770
|
+
resolveFragment(message, fragment) {
|
|
9771
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9772
|
+
if (fragment.type === 'url' && fragment.text.startsWith('https://twitter.com/')) {
|
|
9773
|
+
return {
|
|
9774
|
+
type: 'tweet',
|
|
9775
|
+
url: fragment.text,
|
|
9776
|
+
style: 'block'
|
|
9777
|
+
};
|
|
9778
|
+
}
|
|
9779
|
+
return null;
|
|
9780
|
+
});
|
|
9781
|
+
}
|
|
9782
|
+
}
|
|
9783
|
+
|
|
9667
9784
|
class BantaSdkModule {
|
|
9785
|
+
constructor(chatBackend) {
|
|
9786
|
+
if (typeof window !== 'undefined') {
|
|
9787
|
+
if (!document.querySelector('script[src="https://platform.twitter.com/widgets.js"]')) {
|
|
9788
|
+
let script = document.createElement('script');
|
|
9789
|
+
script.src = 'https://platform.twitter.com/widgets.js';
|
|
9790
|
+
script.async = true;
|
|
9791
|
+
document.body.appendChild(script);
|
|
9792
|
+
}
|
|
9793
|
+
}
|
|
9794
|
+
chatBackend.registerAttachmentScraper(new UrlAttachmentScraper());
|
|
9795
|
+
chatBackend.registerAttachmentResolver(new GiphyAttachmentResolver());
|
|
9796
|
+
chatBackend.registerAttachmentResolver(new YouTubeAttachmentResolver());
|
|
9797
|
+
chatBackend.registerAttachmentResolver(new TweetAttachmentResolver());
|
|
9798
|
+
chatBackend.registerAttachmentResolver(new UrlAttachmentResolver(chatBackend));
|
|
9799
|
+
}
|
|
9668
9800
|
static configure(options) {
|
|
9669
9801
|
return {
|
|
9670
9802
|
ngModule: BantaSdkModule,
|
|
@@ -9712,6 +9844,9 @@ BantaSdkModule.decorators = [
|
|
|
9712
9844
|
CommentsModule
|
|
9713
9845
|
]
|
|
9714
9846
|
},] }
|
|
9847
|
+
];
|
|
9848
|
+
BantaSdkModule.ctorParameters = () => [
|
|
9849
|
+
{ type: ChatBackendBase }
|
|
9715
9850
|
];
|
|
9716
9851
|
|
|
9717
9852
|
/*
|
|
@@ -9722,5 +9857,5 @@ BantaSdkModule.decorators = [
|
|
|
9722
9857
|
* Generated bundle index. Do not edit.
|
|
9723
9858
|
*/
|
|
9724
9859
|
|
|
9725
|
-
export { AttachmentButtonComponent, BANTA_SDK_OPTIONS, BantaAttachmentComponent, BantaAttachmentsComponent, BantaChatComponent, BantaCommentsComponent, BantaCommonModule, BantaComponent, BantaLogoComponent, BantaMarkdownToHtmlPipe, BantaReplySendOptionsDirective, BantaSdkModule, BantaTrustResourceUrlPipe, ChatBackend, ChatBackendBase, ChatMessageComponent, ChatModule, ChatSource, ChatViewComponent, CommentComponent, CommentFieldComponent, CommentSortComponent, CommentViewComponent, CommentsModule, EMOJIS, EmojiModule, EmojiSelectorButtonComponent, EmojiSelectorPanelComponent, LightboxComponent, LiveChatMessageComponent, LiveCommentComponent, LiveMessageComponent, TimestampComponent, lazyConnection };
|
|
9860
|
+
export { AttachmentButtonComponent, BANTA_SDK_OPTIONS, BantaAttachmentComponent, BantaAttachmentsComponent, BantaChatComponent, BantaCommentsComponent, BantaCommonModule, BantaComponent, BantaLogoComponent, BantaMarkdownToHtmlPipe, BantaReplySendOptionsDirective, BantaSdkModule, BantaTrustResourceUrlPipe, ChatBackend, ChatBackendBase, ChatMessageComponent, ChatModule, ChatSource, ChatViewComponent, CommentComponent, CommentFieldComponent, CommentSortComponent, CommentViewComponent, CommentsModule, EMOJIS, EmojiModule, EmojiSelectorButtonComponent, EmojiSelectorPanelComponent, GiphyAttachmentResolver, LightboxComponent, LiveChatMessageComponent, LiveCommentComponent, LiveMessageComponent, TimestampComponent, TweetAttachmentResolver, UrlAttachmentResolver, UrlAttachmentScraper, YouTubeAttachmentResolver, lazyConnection };
|
|
9726
9861
|
//# sourceMappingURL=banta-sdk.js.map
|