@banta/sdk 3.3.10 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/banta-sdk.metadata.json +1 -1
  2. package/bundles/banta-sdk.umd.js +1124 -402
  3. package/bundles/banta-sdk.umd.js.map +1 -1
  4. package/bundles/banta-sdk.umd.min.js +1 -1
  5. package/bundles/banta-sdk.umd.min.js.map +1 -1
  6. package/esm2015/lib/banta/banta.component.js +9 -15
  7. package/esm2015/lib/banta-sdk.module.js +10 -4
  8. package/esm2015/lib/chat/banta-chat/banta-chat.component.js +14 -17
  9. package/esm2015/lib/chat/chat-message/chat-message.component.js +2 -2
  10. package/esm2015/lib/chat/chat-view/chat-view.component.js +7 -6
  11. package/esm2015/lib/chat/live-chat-message.component.js +3 -3
  12. package/esm2015/lib/chat-backend-base.js +17 -0
  13. package/esm2015/lib/chat-backend.js +74 -0
  14. package/esm2015/lib/chat-source-base.js +2 -0
  15. package/esm2015/lib/chat-source.js +151 -0
  16. package/esm2015/lib/comments/banta-comments/banta-comments.component.js +331 -173
  17. package/esm2015/lib/comments/comment/comment.component.js +56 -18
  18. package/esm2015/lib/comments/comment-field/comment-field.component.js +16 -14
  19. package/esm2015/lib/comments/comment-view/comment-view.component.js +77 -39
  20. package/esm2015/lib/comments/live-comment.component.js +3 -3
  21. package/esm2015/lib/common/index.js +1 -3
  22. package/esm2015/lib/index.js +6 -1
  23. package/esm2015/lib/sdk-options.js +2 -0
  24. package/fesm2015/banta-sdk.js +743 -302
  25. package/fesm2015/banta-sdk.js.map +1 -1
  26. package/lib/banta/banta.component.d.ts +7 -8
  27. package/lib/banta-sdk.module.d.ts +2 -1
  28. package/lib/chat/banta-chat/banta-chat.component.d.ts +8 -10
  29. package/lib/chat/chat-view/chat-view.component.d.ts +7 -4
  30. package/lib/chat/live-chat-message.component.d.ts +2 -2
  31. package/lib/chat-backend-base.d.ts +22 -0
  32. package/lib/chat-backend.d.ts +21 -0
  33. package/lib/chat-source-base.d.ts +31 -0
  34. package/lib/chat-source.d.ts +38 -0
  35. package/lib/comments/banta-comments/banta-comments.component.d.ts +65 -60
  36. package/lib/comments/comment/comment.component.d.ts +25 -5
  37. package/lib/comments/comment-field/comment-field.component.d.ts +7 -3
  38. package/lib/comments/comment-view/comment-view.component.d.ts +26 -8
  39. package/lib/comments/live-comment.component.d.ts +2 -2
  40. package/lib/common/index.d.ts +0 -2
  41. package/lib/index.d.ts +5 -0
  42. package/lib/sdk-options.d.ts +4 -0
  43. package/package.json +1 -1
  44. package/esm2015/lib/common/banta.service.js +0 -21
  45. package/esm2015/lib/common/chat-backend.service.js +0 -7
  46. package/lib/common/banta.service.d.ts +0 -9
  47. package/lib/common/chat-backend.service.d.ts +0 -14
@@ -17,34 +17,6 @@
17
17
  return obs.pipe(operators.publish()).refCount();
18
18
  }
19
19
 
20
- var BantaService = /** @class */ (function () {
21
- function BantaService() {
22
- this._userChanged = new rxjs.BehaviorSubject(null);
23
- }
24
- Object.defineProperty(BantaService.prototype, "userChanged", {
25
- get: function () {
26
- return this._userChanged;
27
- },
28
- enumerable: false,
29
- configurable: true
30
- });
31
- Object.defineProperty(BantaService.prototype, "user", {
32
- get: function () {
33
- return this._user;
34
- },
35
- set: function (user) {
36
- this._user = user;
37
- this._userChanged.next(user);
38
- },
39
- enumerable: false,
40
- configurable: true
41
- });
42
- return BantaService;
43
- }());
44
- BantaService.decorators = [
45
- { type: core.Injectable }
46
- ];
47
-
48
20
  var TimestampComponent = /** @class */ (function () {
49
21
  function TimestampComponent() {
50
22
  this.relative = '';
@@ -149,15 +121,6 @@
149
121
  value: [{ type: core.Input }]
150
122
  };
151
123
 
152
- var ChatBackendService = /** @class */ (function () {
153
- function ChatBackendService() {
154
- }
155
- return ChatBackendService;
156
- }());
157
- ChatBackendService.decorators = [
158
- { type: core.Injectable }
159
- ];
160
-
161
124
  var COMPONENTS = [
162
125
  TimestampComponent
163
126
  ];
@@ -7220,12 +7183,36 @@
7220
7183
  },] }
7221
7184
  ];
7222
7185
 
7186
+ var ChatBackendBase = /** @class */ (function () {
7187
+ function ChatBackendBase() {
7188
+ this._userChanged = new rxjs.BehaviorSubject(null);
7189
+ }
7190
+ Object.defineProperty(ChatBackendBase.prototype, "userChanged", {
7191
+ get: function () {
7192
+ return this._userChanged;
7193
+ },
7194
+ enumerable: false,
7195
+ configurable: true
7196
+ });
7197
+ Object.defineProperty(ChatBackendBase.prototype, "user", {
7198
+ get: function () {
7199
+ return this._user;
7200
+ },
7201
+ set: function (user) {
7202
+ this._user = user;
7203
+ this._userChanged.next(user);
7204
+ },
7205
+ enumerable: false,
7206
+ configurable: true
7207
+ });
7208
+ return ChatBackendBase;
7209
+ }());
7210
+
7223
7211
  /**
7224
7212
  * Unified chat and comments component
7225
7213
  */
7226
7214
  var BantaComponent = /** @class */ (function () {
7227
- function BantaComponent(banta, backend, matDialog) {
7228
- this.banta = banta;
7215
+ function BantaComponent(backend, matDialog) {
7229
7216
  this.backend = backend;
7230
7217
  this.matDialog = matDialog;
7231
7218
  this._subs = new rxjs.Subscription();
@@ -7244,7 +7231,7 @@
7244
7231
  }
7245
7232
  BantaComponent.prototype.ngOnInit = function () {
7246
7233
  var _this = this;
7247
- this._subs.add(this.banta.userChanged.subscribe(function (user) { return _this.currentUser = user; }));
7234
+ this._subs.add(this.backend.userChanged.subscribe(function (user) { return _this.currentUser = user; }));
7248
7235
  this._subs.add(this.backend.notificationsChanged.subscribe(function (notifs) { return _this.notifications = notifs; }));
7249
7236
  this._subs.add(this.backend.newNotification.subscribe(function (notif) {
7250
7237
  _this.newNotifications = true;
@@ -7263,7 +7250,7 @@
7263
7250
  message = {
7264
7251
  user: null,
7265
7252
  sentAt: Date.now(),
7266
- upvotes: 0,
7253
+ likes: 0,
7267
7254
  message: text
7268
7255
  };
7269
7256
  _a.label = 1;
@@ -7427,19 +7414,7 @@
7427
7414
  BantaComponent.prototype.upvoteMessage = function (message) {
7428
7415
  return __awaiter(this, void 0, void 0, function () {
7429
7416
  return __generator(this, function (_a) {
7430
- switch (_a.label) {
7431
- case 0:
7432
- if (!message.parentMessageId) return [3 /*break*/, 2];
7433
- return [4 /*yield*/, this.backend.upvoteMessage(message.topicId, message.parentMessageId, message.id)];
7434
- case 1:
7435
- _a.sent();
7436
- return [3 /*break*/, 4];
7437
- case 2: return [4 /*yield*/, this.backend.upvoteMessage(message.topicId, message.id)];
7438
- case 3:
7439
- _a.sent();
7440
- _a.label = 4;
7441
- case 4: return [2 /*return*/];
7442
- }
7417
+ return [2 /*return*/];
7443
7418
  });
7444
7419
  });
7445
7420
  };
@@ -7460,13 +7435,12 @@
7460
7435
  BantaComponent.decorators = [
7461
7436
  { type: core.Component, args: [{
7462
7437
  selector: "banta",
7463
- template: "\r\n<mat-menu #userMenu=\"matMenu\">\r\n <ng-container *ngIf=\"currentUser\">\r\n <button [disabled]=\"true\" mat-menu-item>{{currentUser.displayName}} (@{{currentUser.username}})</button>\r\n <button mat-menu-item (click)=\"signOut()\">Sign Out</button>\r\n </ng-container>\r\n <ng-container *ngIf=\"!currentUser\">\r\n <button mat-menu-item>Sign In</button>\r\n </ng-container>\r\n <button mat-menu-item>Help</button>\r\n</mat-menu>\r\n\r\n<div class=\"tabs\">\r\n <div>\r\n <a mat-button (click)=\"mobileFocus = 'chat'\">{{chatLabel}}</a>\r\n <a mat-button (click)=\"mobileFocus = 'comments'\">{{commentsLabel}}</a>\r\n </div>\r\n <div class=\"spacer\"></div>\r\n <div>\r\n <ng-container *ngIf=\"currentUser\">\r\n <button mat-button [matMenuTriggerFor]=\"userMenu\">\r\n @{{currentUser.username}}\r\n </button>\r\n <button mat-icon-button (click)=\"showNotifications()\">\r\n <mat-icon>notification_important</mat-icon>\r\n </button>\r\n </ng-container>\r\n \r\n <button mat-button *ngIf=\"!currentUser\" (click)=\"showSignIn()\">\r\n Sign In\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<div class=\"firehose\" [class.focus]=\"mobileFocus === 'chat'\">\r\n <header>\r\n <div>\r\n <label (click)=\"mobileFocus = 'chat'\">{{chatLabel}}</label>\r\n <div class=\"spacer\"></div>\r\n\r\n <ng-container *ngIf=\"currentUser\">\r\n <button mat-button [matMenuTriggerFor]=\"userMenu\">\r\n @{{currentUser.username}}\r\n </button>\r\n <button mat-icon-button (click)=\"showNotifications()\">\r\n <mat-icon>notification_important</mat-icon>\r\n </button>\r\n </ng-container>\r\n \r\n <button mat-button *ngIf=\"!currentUser\" (click)=\"showSignIn()\">\r\n Sign In\r\n </button>\r\n </div>\r\n </header>\r\n <banta-chat \r\n #firehose\r\n [source]=\"firehoseSource\"\r\n (signInSelected)=\"showSignIn()\"\r\n (upvoted)=\"upvoteMessage($event)\"\r\n (userSelected)=\"showProfile($event.user)\"\r\n (reported)=\"reportMessage($event)\"\r\n ></banta-chat>\r\n</div>\r\n\r\n<div class=\"aux\" [class.focus]=\"mobileFocus === 'aux'\" [class.open]=\"auxOpen\">\r\n <header>\r\n <div>\r\n <label>{{auxTitle}}</label>\r\n <div class=\"spacer\"></div>\r\n <button mat-icon-button (click)=\"auxOpen = false\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n </header>\r\n <div class=\"aux-contents\">\r\n <ng-container *ngIf=\"auxMode === 'profile'\">\r\n <ng-container *ngIf=\"profileUser\">\r\n\r\n <div>\r\n <strong style=\"font-size: 125%;\">\r\n {{profileUser.displayName}}\r\n </strong>\r\n @{{profileUser.username}}\r\n </div>\r\n\r\n <br/>\r\n <strong>Top Messages</strong>\r\n\r\n <div>\r\n <em>Not yet available</em>\r\n </div>\r\n\r\n <br/>\r\n <strong>Recent Messages</strong>\r\n\r\n <div>\r\n <em>Not yet available</em>\r\n </div>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"auxMode === 'report'\">\r\n <p>Are you sure you want to report this message?</p>\r\n\r\n <banta-live-message [message]=\"reportedMessage\"></banta-live-message>\r\n\r\n <div style=\"text-align: center;\">\r\n <button mat-raised-button color=\"primary\" (click)=\"sendReport(reportedMessage)\">Yes, Report</button>\r\n &nbsp;\r\n <button mat-raised-button color=\"secondary\" (click)=\"auxOpen = false\">No, Cancel</button>\r\n </div>\r\n\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"auxMode === 'notifications'\">\r\n\r\n <div *ngIf=\"!notifications || notifications.length === 0\">\r\n <em>You do not have any notifications yet</em>\r\n </div>\r\n \r\n <div class=\"notifications\">\r\n <div class=\"notification\" *ngFor=\"let notif of notifications\">\r\n <div>\r\n <ng-container *ngIf=\"notif.type === 'upvote'\">\r\n @{{notif.message?.user?.username}} upvoted your post\r\n \r\n <banta-live-message\r\n [message]=\"notif.message\"\r\n (upvoted)=\"upvoteMessage(notif.message)\"\r\n (reported)=\"reportMessage(notif.message)\"\r\n (selected)=\"goToMessage(notif.message)\">\r\n </banta-live-message>\r\n\r\n </ng-container>\r\n <ng-container *ngIf=\"notif.type === 'notice'\">\r\n <div>\r\n {{notif.message}}\r\n </div>\r\n <a mat-button target=\"_blank\" href=\"{{notif.actionUrl}}\">\r\n {{notif.actionLabel}}\r\n </a>\r\n </ng-container>\r\n <ng-container *ngIf=\"notif.type === 'mention'\">\r\n You were mentioned by @{{notif.message?.user?.username}}\r\n\r\n <banta-live-message\r\n [message]=\"notif.message\"\r\n (upvoted)=\"upvoteMessage(notif.message)\"\r\n (reported)=\"reportMessage(notif.message)\"\r\n (selected)=\"goToMessage(notif.message)\">\r\n </banta-live-message>\r\n\r\n </ng-container>\r\n <ng-container *ngIf=\"notif.type === 'reply'\">\r\n @{{notif.replyMessage?.user?.username}} replied to your post\r\n \r\n <banta-live-message\r\n [message]=\"notif.replyMessage\"\r\n (upvoted)=\"upvoteMessage(notif.replyMessage)\"\r\n (reported)=\"reportMessage(notif.replyMessage)\"\r\n (selected)=\"goToMessage(notif.replyMessage)\">\r\n </banta-live-message>\r\n </ng-container>\r\n </div>\r\n\r\n <banta-timestamp [value]=\"notif.sentAt\"></banta-timestamp>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n</div>\r\n<div class=\"points\" [class.focus]=\"mobileFocus === 'points'\">\r\n <header>\r\n <div>\r\n <label>{{commentsLabel}}</label>\r\n </div>\r\n </header>\r\n <div class=\"point-focus\">\r\n <div class=\"actions\">\r\n <button mat-button (click)=\"pointUnfocus()\">\r\n <mat-icon>arrow_back</mat-icon>\r\n Back\r\n </button>\r\n\r\n <div class=\"spacer\"></div>\r\n \r\n <ng-container *ngIf=\"pointOpen\">\r\n <div class=\"counted-action\">\r\n <div class=\"count-indicator\"> \r\n {{pointOpen.upvotes}}\r\n </div>\r\n <button mat-icon-button>\r\n <mat-icon>thumb_up</mat-icon>\r\n </button>\r\n </div>\r\n\r\n </ng-container>\r\n </div>\r\n\r\n <div *ngIf=\"!pointSubChat\">\r\n Error: No subchat\r\n </div>\r\n \r\n <banta-comment-view\r\n class=\"subcomments\"\r\n *ngIf=\"pointSubChat\"\r\n [newestLast]=\"true\"\r\n [allowReplies]=\"false\"\r\n [source]=\"pointSubChat\"\r\n (upvoted)=\"upvoteMessage($event)\"\r\n (reported)=\"reportMessage($event)\"\r\n (userSelected)=\"showProfile($event.user)\"\r\n >\r\n \r\n <banta-comment\r\n class=\"focused-comment\"\r\n data-before\r\n *ngIf=\"pointOpen\"\r\n (upvoted)=\"upvoteMessage(pointOpen)\"\r\n (userSelected)=\"showProfile(pointOpen.user)\"\r\n (reported)=\"reportMessage(pointOpen)\"\r\n [showReplyAction]=\"false\"\r\n [message]=\"pointOpen\"\r\n ></banta-comment>\r\n \r\n <div class=\"message reply\">\r\n Reply:\r\n <form class=\"new-message\" (submit)=\"sendPointSubMessage()\">\r\n <textarea \r\n name=\"message\" \r\n (keydown)=\"newPointSubMessageKeyDown($event)\"\r\n [(ngModel)]=\"newPointSubMessage.message\"></textarea>\r\n \r\n <div class=\"actions\">\r\n <button [disabled]=\"!newPointSubMessage.message\" \r\n mat-raised-button color=\"primary\">Send</button>\r\n </div>\r\n </form>\r\n </div>\r\n </banta-comment-view>\r\n </div>\r\n <div class=\"points-section\">\r\n <banta-comments\r\n [source]=\"pointSource\"\r\n (signInSelected)=\"showSignIn()\"\r\n (upvoted)=\"upvoteMessage($event)\"\r\n (reported)=\"reportMessage($event)\"\r\n (selected)=\"goToMessage($event)\"\r\n (userSelected)=\"showProfile($event.user)\"\r\n ></banta-comments>\r\n </div>\r\n</div>",
7438
+ template: "\r\n<mat-menu #userMenu=\"matMenu\">\r\n <ng-container *ngIf=\"currentUser\">\r\n <button [disabled]=\"true\" mat-menu-item>{{currentUser.displayName}} (@{{currentUser.username}})</button>\r\n <button mat-menu-item (click)=\"signOut()\">Sign Out</button>\r\n </ng-container>\r\n <ng-container *ngIf=\"!currentUser\">\r\n <button mat-menu-item>Sign In</button>\r\n </ng-container>\r\n <button mat-menu-item>Help</button>\r\n</mat-menu>\r\n\r\n<div class=\"tabs\">\r\n <div>\r\n <a mat-button (click)=\"mobileFocus = 'chat'\">{{chatLabel}}</a>\r\n <a mat-button (click)=\"mobileFocus = 'comments'\">{{commentsLabel}}</a>\r\n </div>\r\n <div class=\"spacer\"></div>\r\n <div>\r\n <ng-container *ngIf=\"currentUser\">\r\n <button mat-button [matMenuTriggerFor]=\"userMenu\">\r\n @{{currentUser.username}}\r\n </button>\r\n <button mat-icon-button (click)=\"showNotifications()\">\r\n <mat-icon>notification_important</mat-icon>\r\n </button>\r\n </ng-container>\r\n \r\n <button mat-button *ngIf=\"!currentUser\" (click)=\"showSignIn()\">\r\n Sign In\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<div class=\"firehose\" [class.focus]=\"mobileFocus === 'chat'\">\r\n <header>\r\n <div>\r\n <label (click)=\"mobileFocus = 'chat'\">{{chatLabel}}</label>\r\n <div class=\"spacer\"></div>\r\n\r\n <ng-container *ngIf=\"currentUser\">\r\n <button mat-button [matMenuTriggerFor]=\"userMenu\">\r\n @{{currentUser.username}}\r\n </button>\r\n <button mat-icon-button (click)=\"showNotifications()\">\r\n <mat-icon>notification_important</mat-icon>\r\n </button>\r\n </ng-container>\r\n \r\n <button mat-button *ngIf=\"!currentUser\" (click)=\"showSignIn()\">\r\n Sign In\r\n </button>\r\n </div>\r\n </header>\r\n <banta-chat \r\n #firehose\r\n [source]=\"firehoseSource\"\r\n (signInSelected)=\"showSignIn()\"\r\n (upvoted)=\"upvoteMessage($event)\"\r\n (userSelected)=\"showProfile($event.user)\"\r\n (reported)=\"reportMessage($event)\"\r\n ></banta-chat>\r\n</div>\r\n\r\n<div class=\"aux\" [class.focus]=\"mobileFocus === 'aux'\" [class.open]=\"auxOpen\">\r\n <header>\r\n <div>\r\n <label>{{auxTitle}}</label>\r\n <div class=\"spacer\"></div>\r\n <button mat-icon-button (click)=\"auxOpen = false\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n </header>\r\n <div class=\"aux-contents\">\r\n <ng-container *ngIf=\"auxMode === 'profile'\">\r\n <ng-container *ngIf=\"profileUser\">\r\n\r\n <div>\r\n <strong style=\"font-size: 125%;\">\r\n {{profileUser.displayName}}\r\n </strong>\r\n @{{profileUser.username}}\r\n </div>\r\n\r\n <br/>\r\n <strong>Top Messages</strong>\r\n\r\n <div>\r\n <em>Not yet available</em>\r\n </div>\r\n\r\n <br/>\r\n <strong>Recent Messages</strong>\r\n\r\n <div>\r\n <em>Not yet available</em>\r\n </div>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"auxMode === 'report'\">\r\n <p>Are you sure you want to report this message?</p>\r\n\r\n <banta-live-message [message]=\"reportedMessage\"></banta-live-message>\r\n\r\n <div style=\"text-align: center;\">\r\n <button mat-raised-button color=\"primary\" (click)=\"sendReport(reportedMessage)\">Yes, Report</button>\r\n &nbsp;\r\n <button mat-raised-button color=\"secondary\" (click)=\"auxOpen = false\">No, Cancel</button>\r\n </div>\r\n\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"auxMode === 'notifications'\">\r\n\r\n <div *ngIf=\"!notifications || notifications.length === 0\">\r\n <em>You do not have any notifications yet</em>\r\n </div>\r\n \r\n <div class=\"notifications\">\r\n <div class=\"notification\" *ngFor=\"let notif of notifications\">\r\n <div>\r\n <ng-container *ngIf=\"notif.type === 'upvote'\">\r\n @{{notif.message?.user?.username}} upvoted your post\r\n \r\n <banta-live-message\r\n [message]=\"notif.message\"\r\n (upvoted)=\"upvoteMessage(notif.message)\"\r\n (reported)=\"reportMessage(notif.message)\"\r\n (selected)=\"goToMessage(notif.message)\">\r\n </banta-live-message>\r\n\r\n </ng-container>\r\n <ng-container *ngIf=\"notif.type === 'notice'\">\r\n <div>\r\n {{notif.message}}\r\n </div>\r\n <a mat-button target=\"_blank\" href=\"{{notif.actionUrl}}\">\r\n {{notif.actionLabel}}\r\n </a>\r\n </ng-container>\r\n <ng-container *ngIf=\"notif.type === 'mention'\">\r\n You were mentioned by @{{notif.message?.user?.username}}\r\n\r\n <banta-live-message\r\n [message]=\"notif.message\"\r\n (upvoted)=\"upvoteMessage(notif.message)\"\r\n (reported)=\"reportMessage(notif.message)\"\r\n (selected)=\"goToMessage(notif.message)\">\r\n </banta-live-message>\r\n\r\n </ng-container>\r\n <ng-container *ngIf=\"notif.type === 'reply'\">\r\n @{{notif.replyMessage?.user?.username}} replied to your post\r\n \r\n <banta-live-message\r\n [message]=\"notif.replyMessage\"\r\n (upvoted)=\"upvoteMessage(notif.replyMessage)\"\r\n (reported)=\"reportMessage(notif.replyMessage)\"\r\n (selected)=\"goToMessage(notif.replyMessage)\">\r\n </banta-live-message>\r\n </ng-container>\r\n </div>\r\n\r\n <banta-timestamp [value]=\"notif.sentAt\"></banta-timestamp>\r\n </div>\r\n </div>\r\n </ng-container>\r\n </div>\r\n</div>\r\n<div class=\"points\" [class.focus]=\"mobileFocus === 'points'\">\r\n <header>\r\n <div>\r\n <label>{{commentsLabel}}</label>\r\n </div>\r\n </header>\r\n <div class=\"point-focus\">\r\n <div class=\"actions\">\r\n <button mat-button (click)=\"pointUnfocus()\">\r\n <mat-icon>arrow_back</mat-icon>\r\n Back\r\n </button>\r\n\r\n <div class=\"spacer\"></div>\r\n \r\n <ng-container *ngIf=\"pointOpen\">\r\n <div class=\"counted-action\">\r\n <div class=\"count-indicator\"> \r\n {{pointOpen.likes}}\r\n </div>\r\n <button mat-icon-button>\r\n <mat-icon>thumb_up</mat-icon>\r\n </button>\r\n </div>\r\n\r\n </ng-container>\r\n </div>\r\n\r\n <div *ngIf=\"!pointSubChat\">\r\n Error: No subchat\r\n </div>\r\n \r\n <banta-comment-view\r\n class=\"subcomments\"\r\n *ngIf=\"pointSubChat\"\r\n [newestLast]=\"true\"\r\n [allowReplies]=\"false\"\r\n [source]=\"pointSubChat\"\r\n (upvoted)=\"upvoteMessage($event)\"\r\n (reported)=\"reportMessage($event)\"\r\n (userSelected)=\"showProfile($event.user)\"\r\n >\r\n \r\n <banta-comment\r\n class=\"focused-comment\"\r\n data-before\r\n *ngIf=\"pointOpen\"\r\n (upvoted)=\"upvoteMessage(pointOpen)\"\r\n (userSelected)=\"showProfile(pointOpen.user)\"\r\n (reported)=\"reportMessage(pointOpen)\"\r\n [showReplyAction]=\"false\"\r\n [message]=\"pointOpen\"\r\n ></banta-comment>\r\n \r\n <div class=\"message reply\">\r\n Reply:\r\n <form class=\"new-message\" (submit)=\"sendPointSubMessage()\">\r\n <textarea \r\n name=\"message\" \r\n (keydown)=\"newPointSubMessageKeyDown($event)\"\r\n [(ngModel)]=\"newPointSubMessage.message\"></textarea>\r\n \r\n <div class=\"actions\">\r\n <button [disabled]=\"!newPointSubMessage.message\" \r\n mat-raised-button color=\"primary\">Send</button>\r\n </div>\r\n </form>\r\n </div>\r\n </banta-comment-view>\r\n </div>\r\n <div class=\"points-section\">\r\n <banta-comments\r\n [source]=\"pointSource\"\r\n (signInSelected)=\"showSignIn()\"\r\n (upvoted)=\"upvoteMessage($event)\"\r\n (reported)=\"reportMessage($event)\"\r\n (selected)=\"goToMessage($event)\"\r\n (userSelected)=\"showProfile($event.user)\"\r\n ></banta-comments>\r\n </div>\r\n</div>",
7464
7439
  styles: [":host{display:flex;flex-direction:row;padding:.5em;height:40em;position:relative}.counted-action{display:flex;align-items:center}.count-indicator{font-size:9pt;padding:0 3px;border-radius:3px;border:1px solid #333}header{position:relative;margin-bottom:1em}header div{display:flex;align-items:center;height:30px}header button{color:#666}header label{text-transform:uppercase;z-index:1;font-size:12pt;letter-spacing:2px;font-weight:100;color:#333;margin:0 auto 0 0;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content;white-space:nowrap;overflow-x:hidden;text-overflow:ellipsis}header:after,header label{display:block;position:relative}header:after{content:\"\";border:1px solid #ccc;height:0;width:100%;z-index:0}.points{max-width:50em;display:flex;flex-direction:column}:host.point-focus .points{width:66%;max-width:50em}:host.point-focus .points .points-section{opacity:0;pointer-events:none}:host.point-focus .points .point-focus{opacity:1;pointer-events:auto}:host.point-focus .points .point-focus .actions{display:flex}banta-comments{flex-grow:1}.points{width:33%;margin-left:.5em;font-size:12pt;flex-shrink:0;max-width:30em;transition:width .2s ease-in,max-width .2s ease-in;position:relative}.points .points-section{opacity:1;z-index:2}.points .point-focus,.points .points-section{flex-grow:1;display:flex;flex-direction:column;transition:opacity .2s ease-in}.points .point-focus{position:absolute;width:100%;bottom:0;top:1.75em;right:0;left:0;padding:.5em;opacity:0}.firehose{flex-grow:1;font-size:10pt;display:flex;flex-direction:column}form{display:flex;padding:.5em 0;align-items:center}form textarea{font-size:14pt;min-height:6em}form input[type=text],form textarea{background:#000;color:#fff;border:1px solid #333;width:100%}form input[type=text]{height:1em}form .actions{margin-left:1em}form button{display:block;margin:0 0 0 auto}.subcomments ::ng-deep banta-comment{font-size:10pt}.subcomments ::ng-deep banta-comment.focused-comment{background:#001321;color:#fff;font-size:12pt}.aux{width:0;min-width:0;overflow-x:hidden;transition:width .4s ease-out,min-width .4s ease-out;display:flex;flex-direction:column}.aux.open{width:30em;min-width:18em}.aux .aux-contents{width:30em;min-width:10em;max-width:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;flex-grow:1}.notifications .notification{border-bottom:1px solid #333;padding:1em}.notifications .notification banta-timestamp{display:block;text-align:right;font-size:9pt;color:#999}.message.reply{padding:1em}.tabs{display:none}@media (max-width:1015px){:host{flex-direction:column}.tabs{display:flex;position:absolute;top:0;left:0;right:0;width:100%;z-index:10;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);background:rgba(0,0,0,.5)}.points{width:100%;max-width:100%;margin-left:0}header{display:none}.aux,:host.point-focus .points{width:100%;max-width:100%}.aux{min-width:0}.aux,.firehose,.points{position:absolute;top:2em;left:0;right:0;bottom:0;z-index:0;background:#000}.aux.focus,.firehose.focus,.points.focus{z-index:2}}:host-context(.mat-dark-theme) :host{background:#090909;color:#fff}:host-context(.mat-dark-theme) form textarea{background:#ccc;color:#333}:host-context(.mat-dark-theme) header:after{border-color:#222}:host-context(.mat-dark-theme) header label{color:#aaa}"]
7465
7440
  },] }
7466
7441
  ];
7467
7442
  BantaComponent.ctorParameters = function () { return [
7468
- { type: BantaService },
7469
- { type: ChatBackendService },
7443
+ { type: ChatBackendBase },
7470
7444
  { type: dialog.MatDialog }
7471
7445
  ]; };
7472
7446
  BantaComponent.propDecorators = {
@@ -7550,7 +7524,7 @@
7550
7524
  ChatMessageComponent.decorators = [
7551
7525
  { type: core.Component, args: [{
7552
7526
  selector: 'banta-chat-message',
7553
- template: "<div class=\"message-content\">\r\n <div class=\"user\" (click)=\"selectUser()\">\r\n <div class=\"avatar\" [style.background-image]=\"avatarForUser(message.user)\"></div>\r\n <label>{{message.user.username}}</label>\r\n </div>\r\n <div class=\"content\">\r\n <div (click)=\"select()\">\r\n {{message.message}}\r\n </div>\r\n <div class=\"status\">\r\n <div class=\"count-indicator\" *ngIf=\"message.upvotes > 0\">\r\n {{message.upvotes}} <mat-icon [inline]=\"true\">star</mat-icon>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n<div class=\"actions\">\r\n <button mat-icon-button matTooltip=\"Upvote\" matTooltipPosition=\"below\" (click)=\"upvote()\">\r\n <mat-icon [inline]=\"true\">thumb_up</mat-icon>\r\n </button>\r\n <button mat-icon-button matTooltip=\"Report\" matTooltipPosition=\"below\" (click)=\"report()\">\r\n <mat-icon [inline]=\"true\">report</mat-icon>\r\n </button>\r\n</div>",
7527
+ template: "<div class=\"message-content\">\r\n <div class=\"user\" (click)=\"selectUser()\">\r\n <div class=\"avatar\" [style.background-image]=\"avatarForUser(message.user)\"></div>\r\n <label>{{message.user.username}}</label>\r\n </div>\r\n <div class=\"content\">\r\n <div (click)=\"select()\">\r\n {{message.message}}\r\n </div>\r\n <div class=\"status\">\r\n <div class=\"count-indicator\" *ngIf=\"message.likes > 0\">\r\n {{message.likes}} <mat-icon [inline]=\"true\">star</mat-icon>\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n<div class=\"actions\">\r\n <button mat-icon-button matTooltip=\"Upvote\" matTooltipPosition=\"below\" (click)=\"upvote()\">\r\n <mat-icon [inline]=\"true\">thumb_up</mat-icon>\r\n </button>\r\n <button mat-icon-button matTooltip=\"Report\" matTooltipPosition=\"below\" (click)=\"report()\">\r\n <mat-icon [inline]=\"true\">report</mat-icon>\r\n </button>\r\n</div>",
7554
7528
  styles: [":host{display:flex;flex-direction:row;align-items:center;padding:0 1em;background-color:#fff;color:#000;transition:background-color .4s ease-out}:host .message-content .content{color:#111}:host:hover{background-color:#ddd}:host.highlight{background:#00121b}:host.highlight:hover{background:#01324d}:host:nth-child(2n){background-color:#eee}:host:nth-child(2n):hover{background:#ddd}:host:nth-child(2n) .message-content .content{color:#222}:host:nth-child(2n).highlight{background:#001a2a}:host:nth-child(2n).highlight:hover{background:#002b44}:host .message-content{display:flex;flex-direction:row;flex-grow:1;align-items:center}:host .message-content .content{display:flex;flex-direction:row;padding:5px 0}:host .message-content .content .status{display:flex;flex-direction:row;align-items:center;margin-left:1em}:host .message-content .content .status mat-icon{margin-left:.5em}:host .user{color:#999;font-weight:400;text-align:right;margin-right:.25em;flex-shrink:0;display:flex;align-items:center}:host .user .avatar{background-position:50%;background-size:cover;background-color:#333;border-radius:100%;flex-shrink:0;flex-grow:0;margin-right:1em;width:2em;height:2em}:host .user:after{content:\":\";margin-right:1em}:host .content{flex-grow:1}:host .actions{flex-shrink:0;white-space:nowrap;opacity:0;transition:opacity .4s ease-out}:host:hover .actions{opacity:1}.count-indicator{white-space:nowrap}:host-context(.mat-dark-theme){background-color:#000;color:#fff}:host-context(.mat-dark-theme) .message-content .content{color:#ddd}:host-context(.mat-dark-theme):hover{background-color:#111}:host-context(.mat-dark-theme):nth-child(2n).highlight{background:#001a2a}:host-context(.mat-dark-theme):nth-child(2n).highlight:hover{background:#002b44}:host-context(.mat-dark-theme):nth-child(2n):hover{background-color:#111}:host-context(.mat-dark-theme):nth-child(2n){background-color:#080808}:host-context(.mat-dark-theme):nth-child(2n) .message-content .content{color:#eee}label{margin:0}"]
7555
7529
  },] }
7556
7530
  ];
@@ -7631,7 +7605,7 @@
7631
7605
  },] }
7632
7606
  ];
7633
7607
  LiveChatMessageComponent.ctorParameters = function () { return [
7634
- { type: ChatBackendService }
7608
+ { type: ChatBackendBase }
7635
7609
  ]; };
7636
7610
  LiveChatMessageComponent.propDecorators = {
7637
7611
  upvoted: [{ type: core.Output }],
@@ -7641,7 +7615,8 @@
7641
7615
  };
7642
7616
 
7643
7617
  var ChatViewComponent = /** @class */ (function () {
7644
- function ChatViewComponent(elementRef) {
7618
+ function ChatViewComponent(backend, elementRef) {
7619
+ this.backend = backend;
7645
7620
  this.elementRef = elementRef;
7646
7621
  this._sourceSubs = new rxjs.Subscription();
7647
7622
  this._selected = new rxjs.Subject();
@@ -7672,10 +7647,8 @@
7672
7647
  console.dir(this.messages);
7673
7648
  this._sourceSubs.add(this._source.messageReceived.subscribe(function (msg) { return _this.messageReceived(msg); }));
7674
7649
  this._sourceSubs.add(this._source.messageSent.subscribe(function (msg) { return _this.messageSent(msg); }));
7675
- if (this._source.currentUserChanged) {
7676
- this._sourceSubs.add(this._source.currentUserChanged
7677
- .subscribe(function (user) { return _this.currentUser = user; }));
7678
- }
7650
+ this._sourceSubs.add(this.backend.userChanged
7651
+ .subscribe(function (user) { return _this.currentUser = user; }));
7679
7652
  }
7680
7653
  },
7681
7654
  enumerable: false,
@@ -7795,6 +7768,7 @@
7795
7768
  },] }
7796
7769
  ];
7797
7770
  ChatViewComponent.ctorParameters = function () { return [
7771
+ { type: ChatBackendBase },
7798
7772
  { type: core.ElementRef }
7799
7773
  ]; };
7800
7774
  ChatViewComponent.propDecorators = {
@@ -7811,10 +7785,8 @@
7811
7785
  * Chat component
7812
7786
  */
7813
7787
  var BantaChatComponent = /** @class */ (function () {
7814
- function BantaChatComponent(banta, backend, elementRef) {
7815
- this.banta = banta;
7788
+ function BantaChatComponent(backend) {
7816
7789
  this.backend = backend;
7817
- this.elementRef = elementRef;
7818
7790
  this._subs = new rxjs.Subscription();
7819
7791
  this.user = null;
7820
7792
  this.signInLabel = 'Sign In';
@@ -7831,7 +7803,7 @@
7831
7803
  }
7832
7804
  BantaChatComponent.prototype.ngOnInit = function () {
7833
7805
  var _this = this;
7834
- this._subs.add(this.banta.userChanged.subscribe(function (user) { return _this.user = user; }));
7806
+ this._subs.add(this.backend.userChanged.subscribe(function (user) { return _this.user = user; }));
7835
7807
  };
7836
7808
  BantaChatComponent.prototype.ngOnDestroy = function () {
7837
7809
  this._subs.unsubscribe();
@@ -7947,14 +7919,15 @@
7947
7919
  });
7948
7920
  Object.defineProperty(BantaChatComponent.prototype, "canChat", {
7949
7921
  get: function () {
7950
- var _a;
7951
7922
  if (!this.user)
7952
7923
  return false;
7953
- if (!this.user.permissions)
7954
- return true;
7955
- if (!this.user.permissions.canChat)
7956
- return true;
7957
- return (_a = this.user.permissions) === null || _a === void 0 ? void 0 : _a.canChat(this.source);
7924
+ // TODO
7925
+ // if (!this.user.permissions)
7926
+ // return true;
7927
+ // if (!this.user.permissions.canChat)
7928
+ // return true;
7929
+ // return this.user.permissions?.canChat(this.source);
7930
+ return true;
7958
7931
  },
7959
7932
  enumerable: false,
7960
7933
  configurable: true
@@ -7975,7 +7948,7 @@
7975
7948
  message = {
7976
7949
  user: null,
7977
7950
  sentAt: Date.now(),
7978
- upvotes: 0,
7951
+ likes: 0,
7979
7952
  url: location.href,
7980
7953
  message: text
7981
7954
  };
@@ -8011,9 +7984,7 @@
8011
7984
  },] }
8012
7985
  ];
8013
7986
  BantaChatComponent.ctorParameters = function () { return [
8014
- { type: BantaService },
8015
- { type: ChatBackendService },
8016
- { type: core.ElementRef }
7987
+ { type: ChatBackendBase }
8017
7988
  ]; };
8018
7989
  BantaChatComponent.propDecorators = {
8019
7990
  shouldInterceptMessageSend: [{ type: core.Input }],
@@ -8131,7 +8102,8 @@
8131
8102
  function CommentComponent() {
8132
8103
  this._reported = new rxjs.Subject();
8133
8104
  this._selected = new rxjs.Subject();
8134
- this._upvoted = new rxjs.Subject();
8105
+ this._liked = new rxjs.Subject();
8106
+ this._unliked = new rxjs.Subject();
8135
8107
  this._shared = new rxjs.Subject();
8136
8108
  this._userSelected = new rxjs.Subject();
8137
8109
  this._avatarSelected = new rxjs.Subject();
@@ -8139,6 +8111,12 @@
8139
8111
  this.isNew = false;
8140
8112
  this.visible = false;
8141
8113
  this.showReplyAction = true;
8114
+ this.mine = false;
8115
+ this.editing = false;
8116
+ this._editStarted = new rxjs.Subject();
8117
+ this._deleted = new rxjs.Subject();
8118
+ this._editEnded = new rxjs.Subject();
8119
+ this._edited = new rxjs.Subject();
8142
8120
  }
8143
8121
  CommentComponent.prototype.ngOnInit = function () {
8144
8122
  var _this = this;
@@ -8151,6 +8129,14 @@
8151
8129
  setTimeout(function () { return _this.isNew = false; }, 1000);
8152
8130
  }, randomTime);
8153
8131
  };
8132
+ Object.defineProperty(CommentComponent.prototype, "isHighlighted", {
8133
+ get: function () {
8134
+ var _a, _b, _c;
8135
+ 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;
8136
+ },
8137
+ enumerable: false,
8138
+ configurable: true
8139
+ });
8154
8140
  Object.defineProperty(CommentComponent.prototype, "userSelected", {
8155
8141
  get: function () {
8156
8142
  return this._userSelected.asObservable();
@@ -8179,9 +8165,29 @@
8179
8165
  enumerable: false,
8180
8166
  configurable: true
8181
8167
  });
8182
- Object.defineProperty(CommentComponent.prototype, "upvoted", {
8168
+ CommentComponent.prototype.saveEdit = function () {
8169
+ this._edited.next(this.editedMessage);
8170
+ };
8171
+ CommentComponent.prototype.endEditing = function () {
8172
+ this._editEnded.next();
8173
+ };
8174
+ CommentComponent.prototype.startEdit = function () {
8175
+ this._editStarted.next();
8176
+ this.editedMessage = this.message.message;
8177
+ };
8178
+ CommentComponent.prototype.delete = function () {
8179
+ this._deleted.next();
8180
+ };
8181
+ Object.defineProperty(CommentComponent.prototype, "liked", {
8182
+ get: function () {
8183
+ return this._liked.asObservable();
8184
+ },
8185
+ enumerable: false,
8186
+ configurable: true
8187
+ });
8188
+ Object.defineProperty(CommentComponent.prototype, "unliked", {
8183
8189
  get: function () {
8184
- return this._upvoted.asObservable();
8190
+ return this._unliked.asObservable();
8185
8191
  },
8186
8192
  enumerable: false,
8187
8193
  configurable: true
@@ -8193,26 +8199,44 @@
8193
8199
  enumerable: false,
8194
8200
  configurable: true
8195
8201
  });
8196
- Object.defineProperty(CommentComponent.prototype, "commentId", {
8197
- get: function () {
8198
- var _a;
8199
- return (_a = this.message) === null || _a === void 0 ? void 0 : _a.id;
8200
- },
8202
+ Object.defineProperty(CommentComponent.prototype, "edited", {
8203
+ get: function () { return this._edited.asObservable(); },
8204
+ enumerable: false,
8205
+ configurable: true
8206
+ });
8207
+ Object.defineProperty(CommentComponent.prototype, "deleted", {
8208
+ get: function () { return this._deleted.asObservable(); },
8209
+ enumerable: false,
8210
+ configurable: true
8211
+ });
8212
+ Object.defineProperty(CommentComponent.prototype, "editStarted", {
8213
+ get: function () { return this._editStarted.asObservable(); },
8214
+ enumerable: false,
8215
+ configurable: true
8216
+ });
8217
+ Object.defineProperty(CommentComponent.prototype, "editEnded", {
8218
+ get: function () { return this._editEnded.asObservable(); },
8201
8219
  enumerable: false,
8202
8220
  configurable: true
8203
8221
  });
8204
8222
  Object.defineProperty(CommentComponent.prototype, "shared", {
8205
- get: function () {
8206
- return this._shared.asObservable();
8207
- },
8223
+ get: function () { return this._shared.asObservable(); },
8224
+ enumerable: false,
8225
+ configurable: true
8226
+ });
8227
+ Object.defineProperty(CommentComponent.prototype, "commentId", {
8228
+ get: function () { var _a; return (_a = this.message) === null || _a === void 0 ? void 0 : _a.id; },
8208
8229
  enumerable: false,
8209
8230
  configurable: true
8210
8231
  });
8211
8232
  CommentComponent.prototype.report = function () {
8212
8233
  this._reported.next();
8213
8234
  };
8214
- CommentComponent.prototype.upvote = function () {
8215
- this._upvoted.next();
8235
+ CommentComponent.prototype.like = function () {
8236
+ this._liked.next();
8237
+ };
8238
+ CommentComponent.prototype.unlike = function () {
8239
+ this._unliked.next();
8216
8240
  };
8217
8241
  CommentComponent.prototype.share = function () {
8218
8242
  this._shared.next(this.message);
@@ -8243,12 +8267,13 @@
8243
8267
  CommentComponent.decorators = [
8244
8268
  { type: core.Component, args: [{
8245
8269
  selector: 'banta-comment',
8246
- template: "\r\n<mat-menu #pointItemMenu=\"matMenu\">\r\n <button mat-menu-item (click)=\"report()\">Report</button>\r\n <button mat-menu-item>Help</button>\r\n</mat-menu>\r\n\r\n<div class=\"message-content\">\r\n <div class=\"user\">\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 <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 class=\"content\">\r\n {{message.message}}\r\n </div>\r\n\r\n <div class=\"actions\">\r\n <banta-timestamp [value]=\"message.sentAt\"></banta-timestamp>\r\n <div class=\"spacer\"></div>\r\n <div class=\"counted-action\" *ngIf=\"showReplyAction\">\r\n <div class=\"count-indicator\">\r\n {{message.submessages?.length || message.submessageCount || 0}}\r\n </div>\r\n <button mat-icon-button matTooltip=\"Comment\" matTooltipPosition=\"below\" (click)=\"select()\">\r\n <mat-icon [inline]=\"true\">comment</mat-icon>\r\n </button>\r\n </div>\r\n <div class=\"counted-action\">\r\n <div class=\"count-indicator\">\r\n {{message.upvotes}}\r\n </div>\r\n <button mat-icon-button matTooltip=\"Like\" matTooltipPosition=\"below\" (click)=\"upvote()\">\r\n <mat-icon [inline]=\"true\">thumb_up</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"counted-action\">\r\n <button mat-icon-button matTooltip=\"Share this comment\" matTooltipPosition=\"below\" (click)=\"share()\">\r\n <mat-icon [inline]=\"true\" >share</mat-icon>\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",
8247
- 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{-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.new,:host.visible{visibility:visible}:host:hover{background:#eee}:host .message-content .content{margin-left:60px;margin-right:.5em}:host.abbreviated .message-content .content{max-height:8.5em;text-overflow:ellipsis;overflow-y:hidden}:host .actions{display:flex;padding-right:10px;margin-left:60px;align-items:center}:host .actions button{color:#666}:host .actions banta-timestamp{color:#666;font-size:10pt}.user{position:relative;margin:1em 0 0;display:flex;align-items:center}.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}.user .display-name.username,.user .username.username{color:#666;flex-shrink:0;flex-grow:1}.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}.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}:host-context(.mat-dark-theme) .user .display-name,:host-context(.mat-dark-theme) .user .username{color:#fff}@media (max-width:400px){.avatar{height:32px;width:32px}:host .actions{margin-left:44px}:host .message-content .content{margin-left:44px;margin-right:.5em}}"]
8270
+ template: "\r\n<mat-menu #pointItemMenu=\"matMenu\">\r\n <button *ngIf=\"!mine\" mat-menu-item (click)=\"report()\">Report</button>\r\n <button *ngIf=\"mine\" [disabled]=\"!permissions?.canEdit\" mat-menu-item (click)=\"startEdit()\">Edit</button>\r\n <button *ngIf=\"mine\" [disabled]=\"!permissions?.canDelete\" mat-menu-item (click)=\"delete()\">Delete</button>\r\n</mat-menu>\r\n\r\n<div class=\"message-content\">\r\n <div class=\"user\">\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 <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 <span class=\"user-tag\" *ngIf=\"message.user.tag\">{{message.user.tag}}</span>\r\n <span class=\"spacer\"></span>\r\n </div>\r\n <div class=\"content\" *ngIf=\"!editing\">\r\n {{message.message}}\r\n </div>\r\n <div class=\"content\" *ngIf=\"editing\" style=\"padding-bottom: 2em;\">\r\n <div>\r\n <mat-form-field floatLabel=\"always\" appearance=\"outline\" style=\"width: 100%;\">\r\n <mat-label>Edit Message</mat-label>\r\n <textarea matInput [(ngModel)]=\"editedMessage\"></textarea>\r\n </mat-form-field>\r\n </div>\r\n <button mat-raised-button (click)=\"saveEdit()\">Save</button> &nbsp;\r\n <button mat-button (click)=\"endEditing()\">Cancel</button>\r\n </div>\r\n\r\n <div class=\"actions\">\r\n <banta-timestamp [value]=\"message.sentAt\"></banta-timestamp>\r\n <ul class=\"message-facts\">\r\n <li *ngIf=\"message.edits?.length > 0\">Edited</li>\r\n </ul>\r\n <div class=\"spacer\"></div>\r\n <div class=\"counted-action\" *ngIf=\"showReplyAction\">\r\n <div class=\"count-indicator\">\r\n {{message.submessages?.length || message.submessageCount || 0}}\r\n </div>\r\n <button mat-icon-button matTooltip=\"Comment\" matTooltipPosition=\"below\" (click)=\"select()\">\r\n <mat-icon [inline]=\"true\">comment</mat-icon>\r\n </button>\r\n </div>\r\n <div class=\"counted-action\" [class.active]=\"message.userState?.liked\">\r\n <div class=\"count-indicator\">\r\n {{message.likes}}\r\n </div>\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-icon-button \r\n [disabled]=\"!permissions?.canLike\" \r\n [matTooltip]=\"upvoting ? 'Please wait...' : 'Like'\" \r\n matTooltipPosition=\"below\" \r\n (click)=\"message.userState?.liked ? unlike() : like()\" \r\n >\r\n <mat-icon [inline]=\"true\">thumb_up</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"counted-action\">\r\n <button mat-icon-button matTooltip=\"Share this comment\" matTooltipPosition=\"below\" (click)=\"share()\">\r\n <mat-icon [inline]=\"true\" >share</mat-icon>\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",
8271
+ 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.abbreviated .message-content .content{max-height:8.5em;text-overflow:ellipsis;overflow-y:hidden}:host .actions{display:flex;padding-right:10px;margin-left:60px;align-items:center}:host .actions button{color:#666}:host .actions banta-timestamp{color:#666;font-size:10pt}.user{position:relative;margin:1em 0 0;display:flex;align-items:center}.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}.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}.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}:host-context(.mat-dark-theme) .user .display-name,:host-context(.mat-dark-theme) .user .username{color:#fff}@media (max-width:400px){.avatar{height:32px;width:32px}:host .actions{margin-left:44px}:host .message-content .content{margin-left:44px;margin-right:.5em}}.user-tag{text-transform:uppercase;font-size:12px;border:1px solid #b27373;background:#7a412b;color:#fff;padding:3px 5px;margin:0 .5em 0 1em;border-radius:3px}.spacer{flex-shrink:1;flex-grow:1}ul.message-facts{margin:0;padding:0;color:#666}ul.message-facts li{list-style-type:none;border-left:1px solid #666;font-size:10pt;padding-left:.5em;margin-left:.5em}"]
8248
8272
  },] }
8249
8273
  ];
8250
8274
  CommentComponent.propDecorators = {
8251
8275
  isNew: [{ type: core.HostBinding, args: ['class.new',] }],
8276
+ isHighlighted: [{ type: core.HostBinding, args: ['class.highlighted',] }],
8252
8277
  visible: [{ type: core.HostBinding, args: ['class.visible',] }],
8253
8278
  message: [{ type: core.Input }],
8254
8279
  showReplyAction: [{ type: core.Input }],
@@ -8256,10 +8281,18 @@
8256
8281
  usernameSelected: [{ type: core.Output }],
8257
8282
  avatarSelected: [{ type: core.Output }],
8258
8283
  reported: [{ type: core.Output }],
8259
- upvoted: [{ type: core.Output }],
8284
+ permissions: [{ type: core.Input }],
8285
+ mine: [{ type: core.Input }],
8286
+ editing: [{ type: core.Input }],
8287
+ liked: [{ type: core.Output }],
8288
+ unliked: [{ type: core.Output }],
8260
8289
  selected: [{ type: core.Output }],
8261
- commentId: [{ type: core.HostBinding, args: ['attr.data-comment-id',] }],
8262
- shared: [{ type: core.Output }]
8290
+ edited: [{ type: core.Output }],
8291
+ deleted: [{ type: core.Output }],
8292
+ editStarted: [{ type: core.Output }],
8293
+ editEnded: [{ type: core.Output }],
8294
+ shared: [{ type: core.Output }],
8295
+ commentId: [{ type: core.HostBinding, args: ['attr.data-comment-id',] }]
8263
8296
  };
8264
8297
 
8265
8298
  var CommentViewComponent = /** @class */ (function () {
@@ -8267,16 +8300,20 @@
8267
8300
  this.backend = backend;
8268
8301
  this._sourceSubs = new rxjs.Subscription();
8269
8302
  this._selected = new rxjs.Subject();
8270
- this._upvoted = new rxjs.Subject();
8303
+ this._liked = new rxjs.Subject();
8304
+ this._unliked = new rxjs.Subject();
8271
8305
  this._reported = new rxjs.Subject();
8272
8306
  this._userSelected = new rxjs.Subject();
8273
8307
  this._usernameSelected = new rxjs.Subject();
8274
8308
  this._avatarSelected = new rxjs.Subject();
8275
8309
  this._shared = new rxjs.Subject();
8310
+ this._deleted = new rxjs.Subject();
8311
+ this._messageEdited = new rxjs.Subject();
8276
8312
  this.showEmptyState = true;
8277
8313
  this.allowReplies = true;
8278
8314
  this.menuMessage = null;
8279
8315
  this.messages = [];
8316
+ this.customSortEnabled = false;
8280
8317
  this.maxMessages = 2000;
8281
8318
  this.maxVisibleMessages = 200;
8282
8319
  this.newestLast = false;
@@ -8285,6 +8322,7 @@
8285
8322
  this.hasMore = false;
8286
8323
  this.newMessages = [];
8287
8324
  this.olderMessages = [];
8325
+ this.sortOrderChanged = new rxjs.Subject();
8288
8326
  }
8289
8327
  Object.defineProperty(CommentViewComponent.prototype, "selected", {
8290
8328
  get: function () {
@@ -8293,45 +8331,53 @@
8293
8331
  enumerable: false,
8294
8332
  configurable: true
8295
8333
  });
8296
- Object.defineProperty(CommentViewComponent.prototype, "userSelected", {
8334
+ Object.defineProperty(CommentViewComponent.prototype, "messageEdited", {
8297
8335
  get: function () {
8298
- return this._userSelected;
8336
+ return this._messageEdited.asObservable();
8299
8337
  },
8300
8338
  enumerable: false,
8301
8339
  configurable: true
8302
8340
  });
8341
+ CommentViewComponent.prototype.saveEdit = function (message, newMessage) {
8342
+ this._messageEdited.next({ message: message, newMessage: newMessage });
8343
+ };
8344
+ Object.defineProperty(CommentViewComponent.prototype, "userSelected", {
8345
+ get: function () { return this._userSelected; },
8346
+ enumerable: false,
8347
+ configurable: true
8348
+ });
8303
8349
  Object.defineProperty(CommentViewComponent.prototype, "reported", {
8304
- get: function () {
8305
- return this._reported;
8306
- },
8350
+ get: function () { return this._reported; },
8307
8351
  enumerable: false,
8308
8352
  configurable: true
8309
8353
  });
8310
- Object.defineProperty(CommentViewComponent.prototype, "upvoted", {
8311
- get: function () {
8312
- return this._upvoted;
8313
- },
8354
+ Object.defineProperty(CommentViewComponent.prototype, "liked", {
8355
+ get: function () { return this._liked; },
8356
+ enumerable: false,
8357
+ configurable: true
8358
+ });
8359
+ Object.defineProperty(CommentViewComponent.prototype, "unliked", {
8360
+ get: function () { return this._unliked; },
8314
8361
  enumerable: false,
8315
8362
  configurable: true
8316
8363
  });
8317
8364
  Object.defineProperty(CommentViewComponent.prototype, "usernameSelected", {
8318
- get: function () {
8319
- return this._usernameSelected;
8320
- },
8365
+ get: function () { return this._usernameSelected; },
8321
8366
  enumerable: false,
8322
8367
  configurable: true
8323
8368
  });
8324
8369
  Object.defineProperty(CommentViewComponent.prototype, "avatarSelected", {
8325
- get: function () {
8326
- return this._avatarSelected;
8327
- },
8370
+ get: function () { return this._avatarSelected; },
8328
8371
  enumerable: false,
8329
8372
  configurable: true
8330
8373
  });
8331
8374
  Object.defineProperty(CommentViewComponent.prototype, "shared", {
8332
- get: function () {
8333
- return this._shared;
8334
- },
8375
+ get: function () { return this._shared; },
8376
+ enumerable: false,
8377
+ configurable: true
8378
+ });
8379
+ Object.defineProperty(CommentViewComponent.prototype, "deleted", {
8380
+ get: function () { return this._deleted; },
8335
8381
  enumerable: false,
8336
8382
  configurable: true
8337
8383
  });
@@ -8341,30 +8387,35 @@
8341
8387
  },
8342
8388
  set: function (value) {
8343
8389
  var _this = this;
8390
+ this.customSortEnabled = (value === null || value === void 0 ? void 0 : value.sortOrder) !== common$1.CommentsOrder.NEWEST;
8391
+ this.newMessages = [];
8392
+ this.olderMessages = [];
8393
+ window.bantaSourceDebug = value;
8344
8394
  if (this._sourceSubs) {
8345
8395
  this._sourceSubs.unsubscribe();
8346
8396
  this._sourceSubs = null;
8347
8397
  }
8348
8398
  this._source = value;
8349
8399
  if (value) {
8350
- console.log("[banta-comment-view] Subscribing to source...");
8351
8400
  var messages = (value.messages || []).slice();
8352
8401
  this.messages = messages;
8353
8402
  this.olderMessages = messages.splice(this.maxVisibleMessages, messages.length);
8354
- this.hasMore = this.olderMessages.length > 0;
8403
+ this.hasMore = true; //this.olderMessages.length > 0;
8355
8404
  this._sourceSubs = new rxjs.Subscription();
8356
8405
  this._sourceSubs.add(this._source.messageReceived.subscribe(function (msg) { return _this.messageReceived(msg); }));
8357
8406
  this._sourceSubs.add(this._source.messageSent.subscribe(function (msg) { return _this.messageSent(msg); }));
8358
- if (this._source.currentUserChanged) {
8359
- this._sourceSubs.add(this._source.currentUserChanged.subscribe(function (user) { return _this.currentUser = user; }));
8360
- }
8407
+ this._sourceSubs.add(this.backend.userChanged.subscribe(function (user) { return _this.currentUser = user; }));
8408
+ this.getInitialMessages();
8361
8409
  }
8362
8410
  },
8363
8411
  enumerable: false,
8364
8412
  configurable: true
8365
8413
  });
8366
- CommentViewComponent.prototype.upvoteMessage = function (message) {
8367
- this._upvoted.next(message);
8414
+ CommentViewComponent.prototype.likeMessage = function (message) {
8415
+ this._liked.next(message);
8416
+ };
8417
+ CommentViewComponent.prototype.unlikeMessage = function (message) {
8418
+ this._unliked.next(message);
8368
8419
  };
8369
8420
  CommentViewComponent.prototype.reportMessage = function (message) {
8370
8421
  this._reported.next(message);
@@ -8384,13 +8435,39 @@
8384
8435
  CommentViewComponent.prototype.sharedMessage = function (message) {
8385
8436
  this._shared.next(message);
8386
8437
  };
8438
+ CommentViewComponent.prototype.startEditing = function (message) {
8439
+ this.messages.forEach(function (m) { return m.transientState.editing = false; });
8440
+ message.transientState.editing = true;
8441
+ };
8442
+ CommentViewComponent.prototype.deleteMessage = function (message) {
8443
+ this._deleted.next(message);
8444
+ };
8445
+ CommentViewComponent.prototype.getInitialMessages = function () {
8446
+ return __awaiter(this, void 0, void 0, function () {
8447
+ var messages;
8448
+ return __generator(this, function (_b) {
8449
+ switch (_b.label) {
8450
+ case 0: return [4 /*yield*/, this._source.getExistingMessages()];
8451
+ case 1:
8452
+ messages = (_b.sent());
8453
+ messages.forEach(function (m) { var _a; return (_a = m.transientState) !== null && _a !== void 0 ? _a : (m.transientState = {}); });
8454
+ this.messages = messages;
8455
+ return [2 /*return*/];
8456
+ }
8457
+ });
8458
+ });
8459
+ };
8387
8460
  CommentViewComponent.prototype.messageIdentity = function (index, chatMessage) {
8388
8461
  return chatMessage.id;
8389
8462
  };
8390
8463
  CommentViewComponent.prototype.showNew = function () {
8391
8464
  return __awaiter(this, void 0, void 0, function () {
8392
8465
  var overflow;
8393
- return __generator(this, function (_a) {
8466
+ return __generator(this, function (_b) {
8467
+ if (this.source && this.source.sortOrder !== common$1.CommentsOrder.NEWEST) {
8468
+ this.sortOrderChanged.next(common$1.CommentsOrder.NEWEST);
8469
+ return [2 /*return*/];
8470
+ }
8394
8471
  this.isViewingMore = false;
8395
8472
  this.messages = this.newMessages.splice(0, this.newMessages.length).concat(this.messages);
8396
8473
  overflow = this.messages.splice(this.maxVisibleMessages, this.messages.length);
@@ -8402,43 +8479,53 @@
8402
8479
  };
8403
8480
  CommentViewComponent.prototype.showMore = function () {
8404
8481
  return __awaiter(this, void 0, void 0, function () {
8405
- var lastMessage, messages;
8406
- return __generator(this, function (_a) {
8407
- switch (_a.label) {
8482
+ var nextPageSize, lastMessage, messages;
8483
+ return __generator(this, function (_b) {
8484
+ switch (_b.label) {
8408
8485
  case 0:
8409
8486
  this.isViewingMore = true;
8410
8487
  if (!(this.olderMessages.length > 0)) return [3 /*break*/, 1];
8411
8488
  this.isLoadingMore = false;
8412
8489
  this.messages = this.messages.concat(this.olderMessages.splice(0, 50));
8413
- return [3 /*break*/, 4];
8490
+ return [3 /*break*/, 3];
8414
8491
  case 1:
8415
- if (!this.source.loadAfter) return [3 /*break*/, 3];
8416
8492
  this.isLoadingMore = true;
8493
+ nextPageSize = 20;
8494
+ lastMessage = void 0;
8417
8495
  lastMessage = this.messages[this.messages.length - 1];
8418
- return [4 /*yield*/, this.source.loadAfter(lastMessage, 100)];
8496
+ if (!lastMessage) {
8497
+ this.isLoadingMore = false;
8498
+ this.hasMore = false;
8499
+ return [2 /*return*/];
8500
+ }
8501
+ return [4 /*yield*/, this.source.loadAfter(lastMessage, nextPageSize)];
8419
8502
  case 2:
8420
- messages = _a.sent();
8503
+ messages = _b.sent();
8504
+ messages.forEach(function (m) { var _a; return (_a = m.transientState) !== null && _a !== void 0 ? _a : (m.transientState = {}); });
8421
8505
  this.messages = this.messages.concat(messages);
8422
8506
  this.isLoadingMore = false;
8423
- if (messages.length === 0)
8507
+ if (messages.length === 0) {
8508
+ console.log("Reached the end of the list.");
8424
8509
  this.hasMore = false;
8425
- return [3 /*break*/, 4];
8426
- case 3:
8427
- this.hasMore = false;
8428
- _a.label = 4;
8429
- case 4: return [2 /*return*/];
8510
+ }
8511
+ _b.label = 3;
8512
+ case 3: return [2 /*return*/];
8430
8513
  }
8431
8514
  });
8432
8515
  });
8433
8516
  };
8434
8517
  CommentViewComponent.prototype.addMessage = function (message) {
8518
+ var _a;
8519
+ if (!message.transientState)
8520
+ (_a = message.transientState) !== null && _a !== void 0 ? _a : (message.transientState = {});
8435
8521
  var destination = this.messages;
8436
8522
  var bucket = this.olderMessages;
8437
8523
  if (this.isViewingMore) {
8438
8524
  destination = this.newMessages;
8439
8525
  bucket = null;
8440
8526
  }
8441
- if (this.newestLast) {
8527
+ var newestLast = this.newestLast;
8528
+ if (newestLast) {
8442
8529
  destination.push(message);
8443
8530
  var overflow = destination.splice(this.maxVisibleMessages, destination.length);
8444
8531
  bucket === null || bucket === void 0 ? void 0 : bucket.push.apply(bucket, __spread(overflow));
@@ -8495,41 +8582,63 @@
8495
8582
  CommentViewComponent.decorators = [
8496
8583
  { type: core.Component, args: [{
8497
8584
  selector: 'banta-comment-view',
8498
- template: "<div class=\"message-container\">\r\n <ng-content select=\"[data-before]\"></ng-content>\r\n\r\n <a mat-button class=\"nav\" [class.visible]=\"isViewingMore\" href=\"javascript:;\" (click)=\"showNew()\">\r\n <mat-icon>file_upload</mat-icon>\r\n New\r\n <ng-container *ngIf=\"newMessages.length >= 1\">\r\n ({{newMessages.length}})\r\n </ng-container>\r\n </a>\r\n\r\n <ng-container *ngIf=\"messages.length === 0\">\r\n <div class=\"empty-state\" *ngIf=\"showEmptyState\">\r\n Be the first to comment!\r\n </div>\r\n </ng-container>\r\n <ng-container *ngFor=\"let message of messages; trackBy: messageIdentity\">\r\n <banta-comment\r\n *ngIf=\"!message.hidden\"\r\n class=\"abbreviated\"\r\n [message]=\"message\"\r\n (click)=\"isViewingMore = true\"\r\n [showReplyAction]=\"allowReplies\"\r\n (userSelected)=\"selectMessageUser(message)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (upvoted)=\"upvoteMessage(message)\"\r\n (reported)=\"reportMessage(message)\"\r\n (selected)=\"selectMessage(message)\"\r\n (shared)=\"sharedMessage($event)\"\r\n ></banta-comment>\r\n </ng-container>\r\n\r\n <a mat-button class=\"nav\" [class.visible]=\"hasMore && !isLoadingMore\" href=\"javascript:;\" (click)=\"showMore()\">Show more</a>\r\n\r\n <div class=\"loading-more\" *ngIf=\"isLoadingMore\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n\r\n <!-- <div style=\"color: #666\">\r\n n={{newMessages.length}}, m={{messages.length}}, o={{olderMessages.length}},\r\n v={{maxVisibleMessages}}, M={{maxMessages}}\r\n </div> -->\r\n\r\n <ng-content select=\":not([data-before])\"></ng-content>\r\n</div>\r\n",
8585
+ template: "<div class=\"message-container\">\r\n <ng-content select=\"[data-before]\"></ng-content>\r\n\r\n <a mat-button class=\"nav\" [class.visible]=\"isViewingMore || customSortEnabled\" href=\"javascript:;\" (click)=\"showNew()\">\r\n <mat-icon>file_upload</mat-icon>\r\n New\r\n <ng-container *ngIf=\"newMessages.length >= 1\">\r\n ({{newMessages.length}})\r\n </ng-container>\r\n </a>\r\n\r\n <ng-container *ngIf=\"messages.length === 0\">\r\n <div class=\"empty-state\" *ngIf=\"showEmptyState\">\r\n Be the first to comment!\r\n </div>\r\n </ng-container>\r\n <ng-container *ngFor=\"let message of messages; trackBy: messageIdentity\">\r\n <banta-comment\r\n *ngIf=\"!message.hidden\"\r\n class=\"abbreviated\"\r\n \r\n [message]=\"message\"\r\n [mine]=\"currentUser?.id === message.user?.id\"\r\n [permissions]=\"source?.permissions\"\r\n (click)=\"isViewingMore = true\"\r\n [showReplyAction]=\"allowReplies\"\r\n [editing]=\"message.transientState.editing\"\r\n (editStarted)=\"startEditing(message)\"\r\n (deleted)=\"deleteMessage(message)\"\r\n (editEnded)=\"message.transientState.editing = false\"\r\n (edited)=\"saveEdit(message, $event)\"\r\n (userSelected)=\"selectMessageUser(message)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (liked)=\"likeMessage(message)\"\r\n (unliked)=\"unlikeMessage(message)\"\r\n (reported)=\"reportMessage(message)\"\r\n (selected)=\"selectMessage(message)\"\r\n (shared)=\"sharedMessage($event)\"\r\n ></banta-comment>\r\n </ng-container>\r\n\r\n <a mat-button class=\"nav\" [class.visible]=\"hasMore && !isLoadingMore\" href=\"javascript:;\" (click)=\"showMore()\">Show more</a>\r\n\r\n <div class=\"loading-more\" *ngIf=\"isLoadingMore\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n\r\n <!-- <div style=\"color: #666\">\r\n n={{newMessages.length}}, m={{messages.length}}, o={{olderMessages.length}},\r\n v={{maxVisibleMessages}}, M={{maxMessages}}\r\n </div> -->\r\n\r\n <ng-content select=\":not([data-before])\"></ng-content>\r\n</div>\r\n",
8499
8586
  styles: [":host{flex-grow:1;display:flex;flex-direction:column;opacity:1;transition:opacity .2s ease-in}.message-container{flex-grow:1;overflow-x:hidden;color:#111;background:#fff;padding:.5em 1em 3em .5em;opacity:1;transition:opacity .5s ease-in-out;position:relative}.message-container.no-scroll{height:auto;overflow-y:visible}.message-container.faded{opacity:.25}.message-container .overlay{position:absolute;top:0;left:0;right:0;bottom:0;z-index:10}:host.fixed-height .message-container{overflow-y:auto}:host-context(.mat-dark-theme) .message-container{color:#fff;background:#111}.empty-state{text-align:center;margin:3em;color:#666}:host-context(.mat-dark-theme) .empty-state{color:#666}a.nav{position:absolute;right:.5em;z-index:10;text-align:center;opacity:0;transition:opacity .4s ease-in-out;pointer-events:none;border-radius:2em;background:#222}a.nav.visible{opacity:1;pointer-events:auto}.loading-more{padding:2em;text-align:center;margin:0 auto;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}@media (max-width:400px){.message-container{padding:0 0 3em}}"]
8500
8587
  },] }
8501
8588
  ];
8502
8589
  CommentViewComponent.ctorParameters = function () { return [
8503
- { type: ChatBackendService }
8590
+ { type: ChatBackendBase }
8504
8591
  ]; };
8505
8592
  CommentViewComponent.propDecorators = {
8506
8593
  showEmptyState: [{ type: core.Input }],
8507
8594
  allowReplies: [{ type: core.Input }],
8508
8595
  fixedHeight: [{ type: core.Input }, { type: core.HostBinding, args: ['class.fixed-height',] }],
8509
8596
  selected: [{ type: core.Output }],
8597
+ messageEdited: [{ type: core.Output }],
8510
8598
  userSelected: [{ type: core.Output }],
8511
8599
  reported: [{ type: core.Output }],
8512
- upvoted: [{ type: core.Output }],
8600
+ liked: [{ type: core.Output }],
8601
+ unliked: [{ type: core.Output }],
8513
8602
  usernameSelected: [{ type: core.Output }],
8514
8603
  avatarSelected: [{ type: core.Output }],
8515
8604
  shared: [{ type: core.Output }],
8605
+ deleted: [{ type: core.Output }],
8516
8606
  source: [{ type: core.Input }],
8517
8607
  genericAvatarUrl: [{ type: core.Input }],
8518
8608
  messageContainer: [{ type: core.ViewChild, args: ['messageContainer',] }],
8519
8609
  maxMessages: [{ type: core.Input }],
8520
8610
  maxVisibleMessages: [{ type: core.Input }],
8521
- newestLast: [{ type: core.Input }]
8611
+ newestLast: [{ type: core.Input }],
8612
+ sortOrderChanged: [{ type: core.Output }]
8522
8613
  };
8523
8614
 
8524
8615
  /**
8525
8616
  * Comments component
8526
8617
  */
8527
8618
  var BantaCommentsComponent = /** @class */ (function () {
8528
- function BantaCommentsComponent(banta, backend, elementRef, activatedRoute) {
8529
- this.banta = banta;
8619
+ function BantaCommentsComponent(backend, elementRef, activatedRoute) {
8620
+ var _this = this;
8530
8621
  this.backend = backend;
8531
8622
  this.elementRef = elementRef;
8532
8623
  this.activatedRoute = activatedRoute;
8624
+ // Loading Screen
8625
+ this._loadingMessage = '';
8626
+ this.loadingMessageVisible = false;
8627
+ this.loading = true;
8628
+ this.showLoadingScreen = false;
8629
+ this._loadingMessageIndex = 0;
8630
+ this.loadingMessages = [
8631
+ "Just a second...",
8632
+ "We're definitely working on it.",
8633
+ "There's no need to refresh.",
8634
+ "It's definitely worth the wait!",
8635
+ "This has never happened before.",
8636
+ "We'll keep trying, but it's not looking great. \n Commenting & chat services may be down. \n If you continue to experience issues, please contact support.\n "
8637
+ ];
8638
+ // Properties
8639
+ this._signInSelected = new rxjs.Subject();
8640
+ this._permissionDeniedError = new rxjs.Subject();
8641
+ this._editAvatarSelected = new rxjs.Subject();
8533
8642
  this._upvoted = new rxjs.Subject();
8534
8643
  this._reported = new rxjs.Subject();
8535
8644
  this._selected = new rxjs.Subject();
@@ -8539,12 +8648,8 @@
8539
8648
  this._avatarSelected = new rxjs.Subject();
8540
8649
  this._subs = new rxjs.Subscription();
8541
8650
  this._sortOrder = common$1.CommentsOrder.NEWEST;
8542
- this.hashtags = [
8543
- { hashtag: 'error', description: 'Cause an error' },
8544
- { hashtag: 'timeout', description: 'Cause a slow timeout error' },
8545
- { hashtag: 'slow', description: 'Be slow when this message is posted' },
8546
- ];
8547
- this.participants = [];
8651
+ this.selectedMessageVisible = false;
8652
+ // Inputs
8548
8653
  this.signInLabel = 'Sign In';
8549
8654
  this.sendLabel = 'Send';
8550
8655
  this.replyLabel = 'Reply';
@@ -8552,97 +8657,113 @@
8552
8657
  this.permissionDeniedLabel = 'Send';
8553
8658
  this.postCommentLabel = 'Post a comment';
8554
8659
  this.postReplyLabel = 'Post a reply';
8555
- this._signInSelected = new rxjs.Subject();
8556
- this._permissionDeniedError = new rxjs.Subject();
8557
- this._editAvatarSelected = new rxjs.Subject();
8558
- this.sending = false;
8559
- this.expandError = false;
8560
- this.selectedMessageVisible = false;
8660
+ this.participants = [];
8661
+ this.hashtags = [
8662
+ { hashtag: 'error', description: 'Cause an error' },
8663
+ { hashtag: 'timeout', description: 'Cause a slow timeout error' },
8664
+ { hashtag: 'slow', description: 'Be slow when this message is posted' },
8665
+ ];
8666
+ this.sendMessage = function (message) { return __awaiter(_this, void 0, void 0, function () {
8667
+ var _a, intercept, e_1;
8668
+ return __generator(this, function (_d) {
8669
+ switch (_d.label) {
8670
+ case 0:
8671
+ _d.trys.push([0, 4, , 5]);
8672
+ return [4 /*yield*/, ((_a = this.shouldInterceptMessageSend) === null || _a === void 0 ? void 0 : _a.call(this, message, this.source))];
8673
+ case 1:
8674
+ intercept = _d.sent();
8675
+ if (!!intercept) return [3 /*break*/, 3];
8676
+ return [4 /*yield*/, this.source.send(message)];
8677
+ case 2:
8678
+ _d.sent();
8679
+ _d.label = 3;
8680
+ case 3:
8681
+ if (this.source.sortOrder !== common$1.CommentsOrder.NEWEST) {
8682
+ this.sortOrder = common$1.CommentsOrder.NEWEST;
8683
+ }
8684
+ return [2 /*return*/, true];
8685
+ case 4:
8686
+ e_1 = _d.sent();
8687
+ console.error("Failed to send message: ", message);
8688
+ console.error(e_1);
8689
+ throw new Error("Could not send: " + e_1.message);
8690
+ case 5: return [2 /*return*/];
8691
+ }
8692
+ });
8693
+ }); };
8694
+ this.sendReply = function (message) { return __awaiter(_this, void 0, void 0, function () {
8695
+ var _b, intercept, e_2;
8696
+ return __generator(this, function (_d) {
8697
+ switch (_d.label) {
8698
+ case 0:
8699
+ _d.trys.push([0, 4, , 5]);
8700
+ return [4 /*yield*/, ((_b = this.shouldInterceptMessageSend) === null || _b === void 0 ? void 0 : _b.call(this, message, this.source))];
8701
+ case 1:
8702
+ intercept = _d.sent();
8703
+ if (!!intercept) return [3 /*break*/, 3];
8704
+ return [4 /*yield*/, this.selectedMessageThread.send(message)];
8705
+ case 2:
8706
+ _d.sent();
8707
+ _d.label = 3;
8708
+ case 3: return [2 /*return*/, true];
8709
+ case 4:
8710
+ e_2 = _d.sent();
8711
+ console.error("Failed to send message: ", message);
8712
+ console.error(e_2);
8713
+ throw new Error("Could not send reply: " + e_2.message);
8714
+ case 5: return [2 /*return*/];
8715
+ }
8716
+ });
8717
+ }); };
8561
8718
  }
8562
- Object.defineProperty(BantaCommentsComponent.prototype, "sortOrder", {
8563
- get: function () {
8564
- return this._sortOrder;
8565
- },
8566
- set: function (value) {
8567
- var _this = this;
8568
- if (this._sortOrder !== value) {
8569
- this._sortOrder = value;
8570
- setTimeout(function () {
8571
- _this.setSourceFromTopicID(_this.topicID);
8572
- });
8573
- }
8574
- },
8575
- enumerable: false,
8576
- configurable: true
8577
- });
8719
+ // Lifecycle Events / Initialization
8578
8720
  BantaCommentsComponent.prototype.ngOnInit = function () {
8579
8721
  var _this = this;
8580
- this._subs.add(this.banta.userChanged.subscribe(function (user) { return _this.user = user; }));
8581
- };
8582
- BantaCommentsComponent.prototype.ngAfterViewInit = function () {
8583
- if (typeof window !== 'undefined')
8584
- this.checkForSharedComment();
8585
- };
8586
- BantaCommentsComponent.prototype.scrollToComment = function (commentId) {
8587
- setTimeout(function () {
8588
- var comment = document.querySelectorAll("[data-comment-id=\"" + commentId + "\"]");
8589
- console.log(comment);
8590
- if (comment.length > 0) {
8591
- // comment.item(0).scroll({behavior: 'smooth'});
8592
- comment.item(0).scrollIntoView();
8722
+ this._subs.add(this.backend.userChanged.subscribe(function (user) { return _this.user = user; }));
8723
+ this.startLoading();
8724
+ console.log("Checking...");
8725
+ if (typeof window !== 'undefined') {
8726
+ var queryString = window.location.search.substring(1);
8727
+ var query = queryString.split('&')
8728
+ .map(function (s) { return s.split('='); })
8729
+ .reduce(function (o, _d) {
8730
+ var _e = __read(_d, 2), k = _e[0], v = _e[1];
8731
+ return (o[k] = v, o);
8732
+ }, {});
8733
+ console.log('here:');
8734
+ console.dir(query);
8735
+ var commentID = query['comment'];
8736
+ if (commentID) {
8737
+ this.sharedCommentID = commentID;
8593
8738
  }
8594
- }, 1000);
8595
- };
8596
- BantaCommentsComponent.prototype.checkForSharedComment = function () {
8597
- var commentID = this.activatedRoute.snapshot.queryParamMap.get('comment');
8598
- if (commentID)
8599
- this.scrollToComment(commentID);
8739
+ }
8600
8740
  };
8601
8741
  BantaCommentsComponent.prototype.ngOnDestroy = function () {
8602
8742
  this._subs.unsubscribe();
8603
8743
  };
8604
- Object.defineProperty(BantaCommentsComponent.prototype, "source", {
8605
- get: function () {
8606
- return this._source;
8607
- },
8608
- set: function (value) {
8609
- this._source = value;
8610
- },
8611
- enumerable: false,
8612
- configurable: true
8613
- });
8614
- Object.defineProperty(BantaCommentsComponent.prototype, "topicID", {
8615
- get: function () {
8616
- return this._topicID;
8617
- },
8618
- set: function (value) {
8619
- var _this = this;
8620
- if (this._topicID !== value) {
8621
- this._topicID = value;
8622
- setTimeout(function () { return _this.setSourceFromTopicID(value); });
8623
- }
8624
- },
8625
- enumerable: false,
8626
- configurable: true
8627
- });
8628
8744
  BantaCommentsComponent.prototype.setSourceFromTopicID = function (topicID) {
8629
- var _a, _b;
8630
8745
  return __awaiter(this, void 0, void 0, function () {
8631
8746
  var _this = this;
8632
- return __generator(this, function (_c) {
8633
- (_b = (_a = this._source) === null || _a === void 0 ? void 0 : _a.close) === null || _b === void 0 ? void 0 : _b.call(_a);
8634
- this._source = null;
8747
+ return __generator(this, function (_d) {
8748
+ if (this._source) {
8749
+ this._source.close();
8750
+ this._source = null;
8751
+ }
8635
8752
  setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
8636
- var _c;
8753
+ var _d;
8637
8754
  var _this = this;
8638
- return __generator(this, function (_d) {
8639
- switch (_d.label) {
8755
+ return __generator(this, function (_e) {
8756
+ switch (_e.label) {
8640
8757
  case 0:
8641
- _c = this;
8758
+ console.log("[banta-comments] Subscribing to topic source '" + topicID + "'");
8759
+ _d = this;
8642
8760
  return [4 /*yield*/, this.backend.getSourceForTopic(topicID, { sortOrder: this.sortOrder })];
8643
8761
  case 1:
8644
- _c._source = _d.sent();
8645
- console.log("[banta-comments] Subscribing to source for topic '" + topicID + "'");
8762
+ _d._source = _e.sent();
8763
+ if (this.sharedCommentID) {
8764
+ this.navigateToSharedComment(this.sharedCommentID);
8765
+ this.sharedCommentID = null;
8766
+ }
8646
8767
  this._source.messageReceived.subscribe(function (m) { return _this.addParticipant(m); });
8647
8768
  this._source.messageSent.subscribe(function (m) { return _this.addParticipant(m); });
8648
8769
  this._source.messages.forEach(function (m) { return _this.addParticipant(m); });
@@ -8654,162 +8775,331 @@
8654
8775
  });
8655
8776
  });
8656
8777
  };
8657
- BantaCommentsComponent.prototype.addParticipant = function (message) {
8658
- if (!message || !message.user || !message.user.id)
8659
- return;
8660
- var existing = this.participants.find(function (x) { return x.id === message.user.id; });
8661
- if (existing)
8662
- return;
8663
- this.participants.push(message.user);
8664
- };
8665
- BantaCommentsComponent.prototype.showSignIn = function () {
8666
- this._signInSelected.next();
8667
- };
8668
- BantaCommentsComponent.prototype.showEditAvatar = function () {
8669
- this._editAvatarSelected.next();
8670
- };
8671
- Object.defineProperty(BantaCommentsComponent.prototype, "newMessageText", {
8778
+ Object.defineProperty(BantaCommentsComponent.prototype, "loadingMessage", {
8672
8779
  get: function () {
8673
- return this._newMessageText;
8780
+ return this._loadingMessage;
8674
8781
  },
8675
8782
  set: function (value) {
8676
8783
  var _this = this;
8677
- this._newMessageText = value;
8678
- if (this._newMessageText === '' && this.sendError)
8679
- setTimeout(function () { return _this.sendError = null; });
8784
+ this.loadingMessageVisible = false;
8785
+ setTimeout(function () {
8786
+ _this._loadingMessage = value;
8787
+ _this._loadingMessage = value;
8788
+ setTimeout(function () {
8789
+ _this.loadingMessageVisible = true;
8790
+ });
8791
+ }, 500);
8680
8792
  },
8681
8793
  enumerable: false,
8682
8794
  configurable: true
8683
8795
  });
8684
- Object.defineProperty(BantaCommentsComponent.prototype, "signInSelected", {
8685
- get: function () {
8686
- return this._signInSelected;
8796
+ BantaCommentsComponent.prototype.startLoading = function () {
8797
+ return __awaiter(this, void 0, void 0, function () {
8798
+ var _this = this;
8799
+ return __generator(this, function (_d) {
8800
+ switch (_d.label) {
8801
+ case 0:
8802
+ this.loadingStartedAt = this.messageChangedAt = Date.now();
8803
+ if (this.updateLoading())
8804
+ return [2 /*return*/];
8805
+ return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(function () { return resolve(); }, 100); })];
8806
+ case 1:
8807
+ _d.sent();
8808
+ if (this.updateLoading())
8809
+ return [2 /*return*/];
8810
+ return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(function () { return resolve(); }, 250); })];
8811
+ case 2:
8812
+ _d.sent();
8813
+ if (this.updateLoading())
8814
+ return [2 /*return*/];
8815
+ return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(function () { return resolve(); }, 500); })];
8816
+ case 3:
8817
+ _d.sent();
8818
+ if (this.updateLoading())
8819
+ return [2 /*return*/];
8820
+ console.log("[Banta] Loading is taking a long time! Showing loading screen.");
8821
+ this.showLoadingScreen = true;
8822
+ if (typeof window !== 'undefined')
8823
+ this._loadingTimer = setInterval(function () { return _this.updateLoading(); }, 1000);
8824
+ return [2 /*return*/];
8825
+ }
8826
+ });
8827
+ });
8828
+ };
8829
+ BantaCommentsComponent.prototype.updateLoading = function () {
8830
+ var _this = this;
8831
+ var _a, _b, _c;
8832
+ if (((_a = this.source) === null || _a === void 0 ? void 0 : _a.state) && ((_b = this.source) === null || _b === void 0 ? void 0 : _b.state) !== 'connecting') {
8833
+ clearInterval(this._loadingTimer);
8834
+ this.loadingMessage = "Here we go!";
8835
+ setTimeout(function () {
8836
+ _this.loading = false;
8837
+ }, 750);
8838
+ return true;
8839
+ }
8840
+ console.log("[Banta] Status check: " + (((_c = this.source) === null || _c === void 0 ? void 0 : _c.state) || 'connecting'));
8841
+ var messageSwitchTime = 5 * 1000;
8842
+ if (this.messageChangedAt + messageSwitchTime < Date.now()) {
8843
+ if (this.loadingMessages[this._loadingMessageIndex]) {
8844
+ this.loadingMessage = this.loadingMessages[this._loadingMessageIndex++];
8845
+ this.messageChangedAt = Date.now();
8846
+ }
8847
+ }
8848
+ return false;
8849
+ };
8850
+ Object.defineProperty(BantaCommentsComponent.prototype, "source", {
8851
+ get: function () { return this._source; },
8852
+ set: function (value) {
8853
+ this._source = value;
8854
+ if (value && this.sharedCommentID) {
8855
+ this.navigateToSharedComment(this.sharedCommentID);
8856
+ this.sharedCommentID = null;
8857
+ }
8687
8858
  },
8688
8859
  enumerable: false,
8689
8860
  configurable: true
8690
8861
  });
8691
- Object.defineProperty(BantaCommentsComponent.prototype, "editAvatarSelected", {
8692
- get: function () {
8693
- return this._editAvatarSelected;
8862
+ Object.defineProperty(BantaCommentsComponent.prototype, "topicID", {
8863
+ get: function () { return this._topicID; },
8864
+ set: function (value) {
8865
+ var _this = this;
8866
+ if (this._topicID !== value) {
8867
+ this._topicID = value;
8868
+ setTimeout(function () { return _this.setSourceFromTopicID(value); });
8869
+ }
8694
8870
  },
8695
8871
  enumerable: false,
8696
8872
  configurable: true
8697
8873
  });
8698
- Object.defineProperty(BantaCommentsComponent.prototype, "permissionDeniedError", {
8699
- get: function () {
8700
- return this._permissionDeniedError;
8701
- },
8874
+ Object.defineProperty(BantaCommentsComponent.prototype, "signInSelected", {
8875
+ // Outputs
8876
+ get: function () { return this._signInSelected; },
8702
8877
  enumerable: false,
8703
8878
  configurable: true
8704
8879
  });
8705
- BantaCommentsComponent.prototype.showPermissionDenied = function () {
8706
- this._permissionDeniedError.next();
8707
- };
8708
- Object.defineProperty(BantaCommentsComponent.prototype, "canComment", {
8709
- get: function () {
8710
- var _a;
8711
- if (!this.user)
8712
- return false;
8713
- if (!this.user.permissions)
8714
- return true;
8715
- if (!this.user.permissions.canComment)
8716
- return true;
8717
- return (_a = this.user.permissions) === null || _a === void 0 ? void 0 : _a.canComment(this.source);
8718
- },
8880
+ Object.defineProperty(BantaCommentsComponent.prototype, "editAvatarSelected", {
8881
+ get: function () { return this._editAvatarSelected; },
8882
+ enumerable: false,
8883
+ configurable: true
8884
+ });
8885
+ Object.defineProperty(BantaCommentsComponent.prototype, "permissionDeniedError", {
8886
+ get: function () { return this._permissionDeniedError; },
8719
8887
  enumerable: false,
8720
8888
  configurable: true
8721
8889
  });
8722
8890
  Object.defineProperty(BantaCommentsComponent.prototype, "upvoted", {
8723
- get: function () {
8724
- return this._upvoted.asObservable();
8725
- },
8891
+ get: function () { return this._upvoted.asObservable(); },
8726
8892
  enumerable: false,
8727
8893
  configurable: true
8728
8894
  });
8729
8895
  Object.defineProperty(BantaCommentsComponent.prototype, "reported", {
8730
- get: function () {
8731
- return this._reported.asObservable();
8732
- },
8896
+ get: function () { return this._reported.asObservable(); },
8733
8897
  enumerable: false,
8734
8898
  configurable: true
8735
8899
  });
8736
8900
  Object.defineProperty(BantaCommentsComponent.prototype, "selected", {
8737
- get: function () {
8738
- return this._selected.asObservable();
8739
- },
8901
+ get: function () { return this._selected.asObservable(); },
8740
8902
  enumerable: false,
8741
8903
  configurable: true
8742
8904
  });
8743
8905
  Object.defineProperty(BantaCommentsComponent.prototype, "userSelected", {
8744
- get: function () {
8745
- return this._userSelected.asObservable();
8746
- },
8906
+ get: function () { return this._userSelected.asObservable(); },
8747
8907
  enumerable: false,
8748
8908
  configurable: true
8749
8909
  });
8750
8910
  Object.defineProperty(BantaCommentsComponent.prototype, "usernameSelected", {
8751
- get: function () {
8752
- return this._usernameSelected.asObservable();
8753
- },
8911
+ get: function () { return this._usernameSelected.asObservable(); },
8754
8912
  enumerable: false,
8755
8913
  configurable: true
8756
8914
  });
8757
8915
  Object.defineProperty(BantaCommentsComponent.prototype, "avatarSelected", {
8758
- get: function () {
8759
- return this._avatarSelected.asObservable();
8760
- },
8916
+ get: function () { return this._avatarSelected.asObservable(); },
8761
8917
  enumerable: false,
8762
8918
  configurable: true
8763
8919
  });
8764
8920
  Object.defineProperty(BantaCommentsComponent.prototype, "shared", {
8765
- get: function () {
8766
- return this._shared.asObservable();
8921
+ get: function () { return this._shared.asObservable(); },
8922
+ enumerable: false,
8923
+ configurable: true
8924
+ });
8925
+ Object.defineProperty(BantaCommentsComponent.prototype, "sortOrder", {
8926
+ get: function () { return this._sortOrder; },
8927
+ set: function (value) {
8928
+ var _this = this;
8929
+ if (this._sortOrder !== value) {
8930
+ this._sortOrder = value;
8931
+ setTimeout(function () {
8932
+ _this.setSourceFromTopicID(_this.topicID);
8933
+ });
8934
+ }
8767
8935
  },
8768
8936
  enumerable: false,
8769
8937
  configurable: true
8770
8938
  });
8771
- BantaCommentsComponent.prototype.onKeyDown = function (event) {
8939
+ // UI Interactions
8940
+ BantaCommentsComponent.prototype.scrollToComment = function (commentId) {
8941
+ setTimeout(function () {
8942
+ var comment = document.querySelectorAll("[data-comment-id=\"" + commentId + "\"]");
8943
+ console.dir(comment);
8944
+ if (comment.length > 0) {
8945
+ // comment.item(0).scroll({behavior: 'smooth'});
8946
+ comment.item(0).scrollIntoView();
8947
+ }
8948
+ }, 1000);
8949
+ };
8950
+ BantaCommentsComponent.prototype.navigateToSharedComment = function (id) {
8951
+ var _a, _b, _c;
8952
+ return __awaiter(this, void 0, void 0, function () {
8953
+ var source, message, e_3, parentMessage, thread;
8954
+ return __generator(this, function (_d) {
8955
+ switch (_d.label) {
8956
+ case 0:
8957
+ source = this.source;
8958
+ return [4 /*yield*/, source.ready];
8959
+ case 1:
8960
+ _d.sent();
8961
+ console.log("Navigating to shared comment with ID '" + id + "'...");
8962
+ _d.label = 2;
8963
+ case 2:
8964
+ _d.trys.push([2, 4, , 5]);
8965
+ return [4 /*yield*/, this.source.get(id)];
8966
+ case 3:
8967
+ message = _d.sent();
8968
+ return [3 /*break*/, 5];
8969
+ case 4:
8970
+ e_3 = _d.sent();
8971
+ console.error("Failed to find comment from URL: " + e_3.message);
8972
+ return [2 /*return*/];
8973
+ case 5:
8974
+ (_a = message.transientState) !== null && _a !== void 0 ? _a : (message.transientState = {});
8975
+ if (!message.parentMessageId) return [3 /*break*/, 11];
8976
+ return [4 /*yield*/, this.source.get(message.parentMessageId)];
8977
+ case 6:
8978
+ parentMessage = _d.sent();
8979
+ (_b = parentMessage.transientState) !== null && _b !== void 0 ? _b : (parentMessage.transientState = {});
8980
+ return [4 /*yield*/, this.selectMessage(parentMessage)];
8981
+ case 7:
8982
+ thread = _d.sent();
8983
+ // Need to re-retrieve the message within the new chat source to affect its
8984
+ // transient state.
8985
+ return [4 /*yield*/, thread.ready];
8986
+ case 8:
8987
+ // Need to re-retrieve the message within the new chat source to affect its
8988
+ // transient state.
8989
+ _d.sent();
8990
+ return [4 /*yield*/, thread.get(message.id)];
8991
+ case 9:
8992
+ message = _d.sent();
8993
+ (_c = message.transientState) !== null && _c !== void 0 ? _c : (message.transientState = {});
8994
+ message.transientState.highlighted = true;
8995
+ console.dir(message);
8996
+ return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(function () { return resolve(); }, 500); })];
8997
+ case 10:
8998
+ _d.sent();
8999
+ return [3 /*break*/, 12];
9000
+ case 11:
9001
+ this.selectMessage(message);
9002
+ _d.label = 12;
9003
+ case 12:
9004
+ this.scrollToComment(id);
9005
+ return [2 /*return*/];
9006
+ }
9007
+ });
9008
+ });
8772
9009
  };
8773
- BantaCommentsComponent.prototype.insertEmoji = function (text) {
8774
- this.newMessageText += text;
9010
+ BantaCommentsComponent.prototype.showPermissionDenied = function () {
9011
+ this._permissionDeniedError.next();
8775
9012
  };
8776
- BantaCommentsComponent.prototype.onReplyKeyDown = function (event) {
9013
+ BantaCommentsComponent.prototype.scrollToMessage = function (message) {
9014
+ var el = this.elementRef.nativeElement.querySelector("[data-comment-id=\"" + message.id + "\"]");
9015
+ if (!el)
9016
+ return;
9017
+ el.scrollIntoView({ block: 'center', inline: 'start' });
8777
9018
  };
8778
- BantaCommentsComponent.prototype.insertReplyEmoji = function (text) {
8779
- this.replyMessage += text;
9019
+ BantaCommentsComponent.prototype.addParticipant = function (message) {
9020
+ if (!message || !message.user || !message.user.id)
9021
+ return;
9022
+ var existing = this.participants.find(function (x) { return x.id === message.user.id; });
9023
+ if (existing)
9024
+ return;
9025
+ this.participants.push(message.user);
8780
9026
  };
8781
- BantaCommentsComponent.prototype.indicateError = function (message) {
8782
- var _this = this;
8783
- this.sendError = new Error(message);
8784
- setTimeout(function () {
8785
- _this.expandError = true;
8786
- setTimeout(function () {
8787
- _this.expandError = false;
8788
- }, 5 * 1000);
9027
+ // Actions
9028
+ BantaCommentsComponent.prototype.likeMessage = function (source, message) {
9029
+ var _a;
9030
+ return __awaiter(this, void 0, void 0, function () {
9031
+ var e_4;
9032
+ return __generator(this, function (_d) {
9033
+ switch (_d.label) {
9034
+ case 0:
9035
+ this._upvoted.next(message);
9036
+ message.transientState.liking = true;
9037
+ if (!((_a = message.userState) === null || _a === void 0 ? void 0 : _a.liked))
9038
+ message.likes = (message.likes || 0) + 1;
9039
+ _d.label = 1;
9040
+ case 1:
9041
+ _d.trys.push([1, 3, , 4]);
9042
+ return [4 /*yield*/, source.likeMessage(message.id)];
9043
+ case 2:
9044
+ _d.sent();
9045
+ return [3 /*break*/, 4];
9046
+ case 3:
9047
+ e_4 = _d.sent();
9048
+ alert("Could not like this message: " + e_4.message);
9049
+ return [2 /*return*/];
9050
+ case 4: return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(function () { return resolve(); }, 250); })];
9051
+ case 5:
9052
+ _d.sent();
9053
+ message.transientState.liking = false;
9054
+ return [2 /*return*/];
9055
+ }
9056
+ });
8789
9057
  });
8790
9058
  };
8791
- BantaCommentsComponent.prototype.upvoteMessage = function (message) {
9059
+ BantaCommentsComponent.prototype.unlikeMessage = function (source, message) {
9060
+ var _a;
8792
9061
  return __awaiter(this, void 0, void 0, function () {
8793
- return __generator(this, function (_c) {
8794
- switch (_c.label) {
9062
+ var e_5;
9063
+ return __generator(this, function (_d) {
9064
+ switch (_d.label) {
8795
9065
  case 0:
8796
9066
  this._upvoted.next(message);
8797
- return [4 /*yield*/, this.backend.upvoteMessage(message.topicId, message.parentMessageId ? message.parentMessageId : message.id, message.parentMessageId ? message.id : undefined)];
9067
+ message.transientState.liking = true;
9068
+ if ((_a = message.userState) === null || _a === void 0 ? void 0 : _a.liked)
9069
+ message.likes = (message.likes || 0) - 1;
9070
+ _d.label = 1;
8798
9071
  case 1:
8799
- _c.sent();
9072
+ _d.trys.push([1, 3, , 4]);
9073
+ return [4 /*yield*/, source.unlikeMessage(message.id)];
9074
+ case 2:
9075
+ _d.sent();
9076
+ return [3 /*break*/, 4];
9077
+ case 3:
9078
+ e_5 = _d.sent();
9079
+ alert("Failed to unlike message: " + e_5.message);
9080
+ return [3 /*break*/, 4];
9081
+ case 4: return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(function () { return resolve(); }, 250); })];
9082
+ case 5:
9083
+ _d.sent();
9084
+ message.transientState.liking = false;
8800
9085
  return [2 /*return*/];
8801
9086
  }
8802
9087
  });
8803
9088
  });
8804
9089
  };
8805
9090
  BantaCommentsComponent.prototype.reportMessage = function (message) {
8806
- this._reported.next(message);
9091
+ return __awaiter(this, void 0, void 0, function () {
9092
+ return __generator(this, function (_d) {
9093
+ this._reported.next(message);
9094
+ return [2 /*return*/];
9095
+ });
9096
+ });
8807
9097
  };
8808
9098
  BantaCommentsComponent.prototype.unselectMessage = function () {
8809
9099
  return __awaiter(this, void 0, void 0, function () {
8810
9100
  var message;
8811
9101
  var _this = this;
8812
- return __generator(this, function (_c) {
9102
+ return __generator(this, function (_d) {
8813
9103
  message = this.selectedMessage;
8814
9104
  this._selected.next(null);
8815
9105
  this.selectedMessage = null;
@@ -8826,94 +9116,155 @@
8826
9116
  };
8827
9117
  BantaCommentsComponent.prototype.selectMessage = function (message) {
8828
9118
  return __awaiter(this, void 0, void 0, function () {
9119
+ var selectedMessageThread;
8829
9120
  var _this = this;
8830
- return __generator(this, function (_c) {
8831
- this._selected.next(message);
8832
- this.selectedMessage = message;
8833
- setTimeout(function () { return _this.selectedMessageVisible = true; });
8834
- setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
8835
- var _c;
8836
- return __generator(this, function (_d) {
8837
- switch (_d.label) {
8838
- case 0:
8839
- _c = this;
8840
- return [4 /*yield*/, this.backend.getSourceForThread(this.topicID, message.id)];
8841
- case 1:
8842
- _c.selectedMessageThread = _d.sent();
9121
+ return __generator(this, function (_d) {
9122
+ switch (_d.label) {
9123
+ case 0:
9124
+ this._selected.next(message);
9125
+ this.selectedMessage = message;
9126
+ return [4 /*yield*/, this.backend.getSourceForThread(this.topicID, message.id)];
9127
+ case 1:
9128
+ selectedMessageThread = _d.sent();
9129
+ setTimeout(function () { return _this.selectedMessageVisible = true; });
9130
+ setTimeout(function () { return __awaiter(_this, void 0, void 0, function () {
9131
+ return __generator(this, function (_d) {
9132
+ this.selectedMessageThread = selectedMessageThread;
8843
9133
  return [2 /*return*/];
8844
- }
8845
- });
8846
- }); }, 250);
9134
+ });
9135
+ }); }, 250);
9136
+ return [2 /*return*/, selectedMessageThread];
9137
+ }
9138
+ });
9139
+ });
9140
+ };
9141
+ BantaCommentsComponent.prototype.showSignIn = function () {
9142
+ return __awaiter(this, void 0, void 0, function () {
9143
+ return __generator(this, function (_d) {
9144
+ this._signInSelected.next();
9145
+ return [2 /*return*/];
9146
+ });
9147
+ });
9148
+ };
9149
+ BantaCommentsComponent.prototype.showEditAvatar = function () {
9150
+ return __awaiter(this, void 0, void 0, function () {
9151
+ return __generator(this, function (_d) {
9152
+ this._editAvatarSelected.next();
8847
9153
  return [2 /*return*/];
8848
9154
  });
8849
9155
  });
8850
9156
  };
8851
9157
  BantaCommentsComponent.prototype.selectMessageUser = function (message) {
8852
- this._userSelected.next(message);
9158
+ return __awaiter(this, void 0, void 0, function () {
9159
+ return __generator(this, function (_d) {
9160
+ this._userSelected.next(message);
9161
+ return [2 /*return*/];
9162
+ });
9163
+ });
8853
9164
  };
8854
9165
  BantaCommentsComponent.prototype.selectUsername = function (user) {
8855
- this._usernameSelected.next(user);
9166
+ return __awaiter(this, void 0, void 0, function () {
9167
+ return __generator(this, function (_d) {
9168
+ this._usernameSelected.next(user);
9169
+ return [2 /*return*/];
9170
+ });
9171
+ });
8856
9172
  };
8857
9173
  BantaCommentsComponent.prototype.selectAvatar = function (user) {
8858
- this._avatarSelected.next(user);
9174
+ return __awaiter(this, void 0, void 0, function () {
9175
+ return __generator(this, function (_d) {
9176
+ this._avatarSelected.next(user);
9177
+ return [2 /*return*/];
9178
+ });
9179
+ });
8859
9180
  };
8860
9181
  BantaCommentsComponent.prototype.shareMessage = function (message) {
8861
- this._shared.next(message);
9182
+ return __awaiter(this, void 0, void 0, function () {
9183
+ return __generator(this, function (_d) {
9184
+ this._shared.next(message);
9185
+ return [2 /*return*/];
9186
+ });
9187
+ });
8862
9188
  };
8863
- BantaCommentsComponent.prototype.sendReply = function () {
9189
+ BantaCommentsComponent.prototype.deleteMessage = function (message) {
8864
9190
  return __awaiter(this, void 0, void 0, function () {
8865
- return __generator(this, function (_c) {
8866
- switch (_c.label) {
8867
- case 0: return [4 /*yield*/, this.selectedMessageThread.send({
8868
- message: this.replyMessage,
8869
- parentMessageId: this.selectedMessage.id,
8870
- upvotes: 0,
8871
- user: this.user,
8872
- submessages: [],
8873
- submessageCount: 0,
8874
- topicId: this.topicID,
8875
- sentAt: Date.now(),
8876
- updatedAt: Date.now()
8877
- })];
9191
+ return __generator(this, function (_d) {
9192
+ if (!confirm("Are you sure you want to delete this comment? You cannot undo this action."))
9193
+ return [2 /*return*/];
9194
+ this.source.deleteMessage(message.id);
9195
+ return [2 /*return*/];
9196
+ });
9197
+ });
9198
+ };
9199
+ BantaCommentsComponent.prototype.editMessage = function (source, message, newText) {
9200
+ return __awaiter(this, void 0, void 0, function () {
9201
+ var e_6;
9202
+ return __generator(this, function (_d) {
9203
+ switch (_d.label) {
9204
+ case 0:
9205
+ _d.trys.push([0, 2, , 3]);
9206
+ return [4 /*yield*/, source.editMessage(message.id, newText)];
8878
9207
  case 1:
8879
- _c.sent();
8880
- this.replyMessage = '';
9208
+ _d.sent();
9209
+ return [3 /*break*/, 3];
9210
+ case 2:
9211
+ e_6 = _d.sent();
9212
+ alert(e_6.message);
9213
+ return [2 /*return*/];
9214
+ case 3:
9215
+ message.message = newText;
9216
+ message.transientState.editing = false;
8881
9217
  return [2 /*return*/];
8882
9218
  }
8883
9219
  });
8884
9220
  });
8885
9221
  };
8886
- BantaCommentsComponent.prototype.scrollToMessage = function (message) {
8887
- var el = this.elementRef.nativeElement.querySelector("[data-comment-id=\"" + message.id + "\"]");
8888
- if (!el)
8889
- return;
8890
- el.scrollIntoView({ block: 'center', inline: 'start' });
9222
+ BantaCommentsComponent.prototype.startEditing = function (message) {
9223
+ return __awaiter(this, void 0, void 0, function () {
9224
+ return __generator(this, function (_d) {
9225
+ this.selectedMessage.transientState.editing = false;
9226
+ message.transientState.editing = true;
9227
+ return [2 /*return*/];
9228
+ });
9229
+ });
9230
+ };
9231
+ BantaCommentsComponent.prototype.saveEdit = function (message, text) {
9232
+ return __awaiter(this, void 0, void 0, function () {
9233
+ var e_7;
9234
+ return __generator(this, function (_d) {
9235
+ switch (_d.label) {
9236
+ case 0:
9237
+ _d.trys.push([0, 2, , 3]);
9238
+ return [4 /*yield*/, this.source.editMessage(message.id, text)];
9239
+ case 1:
9240
+ _d.sent();
9241
+ message.transientState.editing = false;
9242
+ return [3 /*break*/, 3];
9243
+ case 2:
9244
+ e_7 = _d.sent();
9245
+ alert("Could not edit message: " + e_7.message);
9246
+ return [3 /*break*/, 3];
9247
+ case 3: return [2 /*return*/];
9248
+ }
9249
+ });
9250
+ });
8891
9251
  };
8892
9252
  return BantaCommentsComponent;
8893
9253
  }());
8894
9254
  BantaCommentsComponent.decorators = [
8895
9255
  { type: core.Component, args: [{
8896
9256
  selector: 'banta-comments',
8897
- template: "\r\n<div class=\"focused\" [class.visible]=\"selectedMessageVisible\" *ngIf=\"selectedMessage\">\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 ></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 ></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 [canComment]=\"canComment\"\r\n [signInLabel]=\"signInLabel\"\r\n [permissionDeniedLabel]=\"permissionDeniedLabel\"\r\n (permissionDeniedError)=\"showPermissionDenied()\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [user]=\"user\"\r\n [label]=\"postReplyLabel\"\r\n >\r\n <ng-content select=\".reply-send-options\"></ng-content>\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\">\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]=\"canComment\"\r\n [hashtags]=\"hashtags\"\r\n [participants]=\"participants\"\r\n [label]=\"postCommentLabel\"\r\n (editAvatarSelected)=\"showEditAvatar()\"\r\n (signInSelected)=\"showSignIn()\"\r\n [permissionDeniedLabel]=\"permissionDeniedLabel\"\r\n (permissionDeniedError)=\"showPermissionDenied()\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\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\"\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 (selected)=\"selectMessage($event)\"\r\n (upvoted)=\"upvoteMessage($event)\"\r\n (reported)=\"reportMessage($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (shared)=\"shareMessage($event)\"\r\n ></banta-comment-view>\r\n</div>\r\n",
8898
- 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:4em}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}@media (max-width:500px){.focused .replies{margin-left:0}}"]
9257
+ 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\">\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 (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 (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 [canComment]=\"source?.permissions?.canPost\"\r\n [signInLabel]=\"signInLabel\"\r\n [permissionDeniedLabel]=\"permissionDeniedLabel\"\r\n (permissionDeniedError)=\"showPermissionDenied()\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [user]=\"user\"\r\n [label]=\"postReplyLabel\"\r\n [submit]=\"sendReply\"\r\n >\r\n <ng-content select=\".reply-send-options\"></ng-content>\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\">\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 (editAvatarSelected)=\"showEditAvatar()\"\r\n (signInSelected)=\"showSignIn()\"\r\n [permissionDeniedLabel]=\"permissionDeniedLabel\"\r\n (permissionDeniedError)=\"showPermissionDenied()\"\r\n [shouldInterceptMessageSend]=\"shouldInterceptMessageSend\"\r\n [submit]=\"sendMessage\"\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\"\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 (deleted)=\"deleteMessage($event)\"\r\n ></banta-comment-view>\r\n </div>\r\n</ng-container>",
9258
+ 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:4em}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}@media (max-width:500px){.focused .replies{margin-left:0}}.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}"]
8899
9259
  },] }
8900
9260
  ];
8901
9261
  BantaCommentsComponent.ctorParameters = function () { return [
8902
- { type: BantaService },
8903
- { type: ChatBackendService },
9262
+ { type: ChatBackendBase },
8904
9263
  { type: core.ElementRef },
8905
9264
  { type: router.ActivatedRoute }
8906
9265
  ]; };
8907
9266
  BantaCommentsComponent.propDecorators = {
8908
- hashtags: [{ type: core.Input }],
8909
- participants: [{ type: core.Input }],
8910
- source: [{ type: core.Input }],
8911
- fixedHeight: [{ type: core.Input }],
8912
- maxMessages: [{ type: core.Input }],
8913
- maxVisibleMessages: [{ type: core.Input }],
8914
- genericAvatarUrl: [{ type: core.Input }],
8915
- shouldInterceptMessageSend: [{ type: core.Input }],
8916
- topicID: [{ type: core.Input }],
9267
+ loadingMessages: [{ type: core.Input }],
8917
9268
  signInLabel: [{ type: core.Input }],
8918
9269
  sendLabel: [{ type: core.Input }],
8919
9270
  replyLabel: [{ type: core.Input }],
@@ -8921,6 +9272,15 @@
8921
9272
  permissionDeniedLabel: [{ type: core.Input }],
8922
9273
  postCommentLabel: [{ type: core.Input }],
8923
9274
  postReplyLabel: [{ type: core.Input }],
9275
+ fixedHeight: [{ type: core.Input }],
9276
+ maxMessages: [{ type: core.Input }],
9277
+ maxVisibleMessages: [{ type: core.Input }],
9278
+ genericAvatarUrl: [{ type: core.Input }],
9279
+ shouldInterceptMessageSend: [{ type: core.Input }],
9280
+ participants: [{ type: core.Input }],
9281
+ source: [{ type: core.Input }],
9282
+ hashtags: [{ type: core.Input }],
9283
+ topicID: [{ type: core.Input }],
8924
9284
  signInSelected: [{ type: core.Output }],
8925
9285
  editAvatarSelected: [{ type: core.Output }],
8926
9286
  permissionDeniedError: [{ type: core.Output }],
@@ -9002,7 +9362,7 @@
9002
9362
  },] }
9003
9363
  ];
9004
9364
  LiveCommentComponent.ctorParameters = function () { return [
9005
- { type: ChatBackendService }
9365
+ { type: ChatBackendBase }
9006
9366
  ]; };
9007
9367
  LiveCommentComponent.propDecorators = {
9008
9368
  upvoted: [{ type: core.Output }],
@@ -9025,6 +9385,7 @@
9025
9385
  this.permissionDeniedLabel = 'Unavailable';
9026
9386
  this.signInLabel = 'Sign In';
9027
9387
  this.placeholder = '';
9388
+ this.textChanged = new rxjs.Subject();
9028
9389
  this.participants = [];
9029
9390
  this._permissionDeniedError = new rxjs.Subject();
9030
9391
  this.autocompleteVisible = false;
@@ -9067,17 +9428,19 @@
9067
9428
  CommentFieldComponent.prototype.indicateError = function (message) {
9068
9429
  var _this = this;
9069
9430
  this.sendError = new Error(message);
9070
- setTimeout(function () {
9431
+ this.expandError = false;
9432
+ clearTimeout(this.errorTimeout);
9433
+ this.errorTimeout = setTimeout(function () {
9071
9434
  _this.expandError = true;
9072
- setTimeout(function () {
9435
+ _this.errorTimeout = setTimeout(function () {
9073
9436
  _this.expandError = false;
9074
9437
  }, 5 * 1000);
9075
- });
9438
+ }, 100);
9076
9439
  };
9077
9440
  CommentFieldComponent.prototype.autocomplete = function (replacement) {
9078
9441
  return __awaiter(this, void 0, void 0, function () {
9079
9442
  var el;
9080
- return __generator(this, function (_b) {
9443
+ return __generator(this, function (_a) {
9081
9444
  el = this.textareaEl.nativeElement;
9082
9445
  this.text = this.text.slice(0, el.selectionStart - this.completionPrefix.length) + replacement + this.text.slice(el.selectionStart);
9083
9446
  return [2 /*return*/];
@@ -9087,7 +9450,7 @@
9087
9450
  CommentFieldComponent.prototype.insert = function (str) {
9088
9451
  return __awaiter(this, void 0, void 0, function () {
9089
9452
  var el;
9090
- return __generator(this, function (_b) {
9453
+ return __generator(this, function (_a) {
9091
9454
  el = this.textareaEl.nativeElement;
9092
9455
  this.text = this.text.slice(0, el.selectionStart) + str + this.text.slice(el.selectionStart);
9093
9456
  return [2 /*return*/];
@@ -9097,8 +9460,8 @@
9097
9460
  CommentFieldComponent.prototype.onKeyDown = function (event) {
9098
9461
  return __awaiter(this, void 0, void 0, function () {
9099
9462
  var _this = this;
9100
- return __generator(this, function (_b) {
9101
- switch (_b.label) {
9463
+ return __generator(this, function (_a) {
9464
+ switch (_a.label) {
9102
9465
  case 0:
9103
9466
  if (this.autocompleteVisible) {
9104
9467
  if (event.key === 'Escape') {
@@ -9133,7 +9496,7 @@
9133
9496
  if (!(event.key === 'Enter' && event.ctrlKey)) return [3 /*break*/, 2];
9134
9497
  return [4 /*yield*/, this.sendMessage()];
9135
9498
  case 1:
9136
- _b.sent();
9499
+ _a.sent();
9137
9500
  return [2 /*return*/];
9138
9501
  case 2:
9139
9502
  if (this.completionFunc) {
@@ -9216,19 +9579,18 @@
9216
9579
  this.editAvatarSelected.next();
9217
9580
  };
9218
9581
  CommentFieldComponent.prototype.sendMessage = function () {
9219
- var _a;
9220
9582
  return __awaiter(this, void 0, void 0, function () {
9221
- var text, message, intercept, e_1;
9222
- return __generator(this, function (_b) {
9223
- switch (_b.label) {
9583
+ var text, message, e_1;
9584
+ return __generator(this, function (_a) {
9585
+ switch (_a.label) {
9224
9586
  case 0:
9225
9587
  if (!this.source)
9226
9588
  return [2 /*return*/];
9227
9589
  this.sending = true;
9228
9590
  this.sendError = null;
9229
- _b.label = 1;
9591
+ _a.label = 1;
9230
9592
  case 1:
9231
- _b.trys.push([1, , 8, 9]);
9593
+ _a.trys.push([1, , 7, 8]);
9232
9594
  text = (this.text || '').trim();
9233
9595
  if (text === '')
9234
9596
  return [2 /*return*/];
@@ -9236,34 +9598,29 @@
9236
9598
  user: this.user,
9237
9599
  sentAt: Date.now(),
9238
9600
  url: location.href,
9239
- upvotes: 0,
9601
+ likes: 0,
9240
9602
  message: text
9241
9603
  };
9242
- _b.label = 2;
9604
+ _a.label = 2;
9243
9605
  case 2:
9244
- _b.trys.push([2, 6, , 7]);
9245
- return [4 /*yield*/, ((_a = this.shouldInterceptMessageSend) === null || _a === void 0 ? void 0 : _a.call(this, message, this.source))];
9606
+ _a.trys.push([2, 4, , 6]);
9607
+ return [4 /*yield*/, this.submit(message)];
9246
9608
  case 3:
9247
- intercept = _b.sent();
9248
- if (!!intercept) return [3 /*break*/, 5];
9249
- return [4 /*yield*/, this.source.send(message)];
9609
+ _a.sent();
9610
+ this.text = '';
9611
+ return [3 /*break*/, 6];
9250
9612
  case 4:
9251
- _b.sent();
9252
- _b.label = 5;
9613
+ e_1 = _a.sent();
9614
+ return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(function () { return resolve(); }, 1000); })];
9253
9615
  case 5:
9254
- this.text = '';
9255
- return [3 /*break*/, 7];
9256
- case 6:
9257
- e_1 = _b.sent();
9258
- this.indicateError("Could not send: " + e_1.message);
9259
- console.error("Failed to send message: ", message);
9260
- console.error(e_1);
9261
- return [3 /*break*/, 7];
9262
- case 7: return [3 /*break*/, 9];
9263
- case 8:
9616
+ _a.sent();
9617
+ this.indicateError(e_1.message);
9618
+ return [3 /*break*/, 6];
9619
+ case 6: return [3 /*break*/, 8];
9620
+ case 7:
9264
9621
  this.sending = false;
9265
9622
  return [7 /*endfinally*/];
9266
- case 9: return [2 /*return*/];
9623
+ case 8: return [2 /*return*/];
9267
9624
  }
9268
9625
  });
9269
9626
  });
@@ -9283,19 +9640,23 @@
9283
9640
  canComment: [{ type: core.Input }],
9284
9641
  signInSelected: [{ type: core.Output }],
9285
9642
  editAvatarSelected: [{ type: core.Output }],
9643
+ sendError: [{ type: core.Input }],
9644
+ expandError: [{ type: core.Input }],
9286
9645
  sendLabel: [{ type: core.Input }],
9287
9646
  sendingLabel: [{ type: core.Input }],
9288
9647
  label: [{ type: core.Input }],
9289
9648
  permissionDeniedLabel: [{ type: core.Input }],
9290
9649
  signInLabel: [{ type: core.Input }],
9291
9650
  placeholder: [{ type: core.Input }],
9651
+ textChanged: [{ type: core.Output }],
9292
9652
  shouldInterceptMessageSend: [{ type: core.Input }],
9293
9653
  autocompleteEl: [{ type: core.ViewChild, args: ['autocomplete',] }],
9294
9654
  autocompleteContainerEl: [{ type: core.ViewChild, args: ['autocompleteContainer',] }],
9295
9655
  textareaEl: [{ type: core.ViewChild, args: ['textarea',] }],
9296
9656
  hashtags: [{ type: core.Input }],
9297
9657
  participants: [{ type: core.Input }],
9298
- permissionDeniedError: [{ type: core.Output }]
9658
+ permissionDeniedError: [{ type: core.Output }],
9659
+ submit: [{ type: core.Input }]
9299
9660
  };
9300
9661
 
9301
9662
  var CommentSortComponent = /** @class */ (function () {
@@ -9374,14 +9735,373 @@
9374
9735
  },] }
9375
9736
  ];
9376
9737
 
9738
+ var ChatSource = /** @class */ (function (_super_1) {
9739
+ __extends(ChatSource, _super_1);
9740
+ function ChatSource(backend, identifier, parentIdentifier, sortOrder) {
9741
+ var _this = _super_1.call(this) || this;
9742
+ _this.backend = backend;
9743
+ _this.identifier = identifier;
9744
+ _this.parentIdentifier = parentIdentifier;
9745
+ _this.sortOrder = sortOrder;
9746
+ _this.subscription = new rxjs.Subscription();
9747
+ _this.state = 'connecting';
9748
+ _this.messageMap = new Map();
9749
+ _this._messageReceived = new rxjs.Subject();
9750
+ _this._messageSent = new rxjs.Subject();
9751
+ _this.messages = [];
9752
+ _this.ready = new Promise(function (resolve) { return _this.markReady = resolve; });
9753
+ return _this;
9754
+ }
9755
+ ChatSource.prototype.bind = function (socket) {
9756
+ var _super = Object.create(null, {
9757
+ bind: { get: function () { return _super_1.prototype.bind; } }
9758
+ });
9759
+ return __awaiter(this, void 0, void 0, function () {
9760
+ var _this = this;
9761
+ return __generator(this, function (_b) {
9762
+ switch (_b.label) {
9763
+ case 0:
9764
+ _super.bind.call(this, socket);
9765
+ this.state = 'connected';
9766
+ this.markReady();
9767
+ return [4 /*yield*/, this.subscribeToTopic()];
9768
+ case 1:
9769
+ _b.sent();
9770
+ this.subscription.add(this.backend.userChanged.subscribe(function () { return _this.authenticate(); }));
9771
+ socket.addEventListener('open', function () { return __awaiter(_this, void 0, void 0, function () {
9772
+ return __generator(this, function (_b) {
9773
+ this.state = 'connected';
9774
+ return [2 /*return*/];
9775
+ });
9776
+ }); });
9777
+ socket.addEventListener('lost', function () { return __awaiter(_this, void 0, void 0, function () {
9778
+ return __generator(this, function (_b) {
9779
+ this.state = 'lost';
9780
+ return [2 /*return*/];
9781
+ });
9782
+ }); });
9783
+ socket.addEventListener('restore', function () { return __awaiter(_this, void 0, void 0, function () {
9784
+ return __generator(this, function (_b) {
9785
+ switch (_b.label) {
9786
+ case 0:
9787
+ this.state = 'restored';
9788
+ return [4 /*yield*/, this.authenticate()];
9789
+ case 1:
9790
+ _b.sent();
9791
+ return [4 /*yield*/, this.subscribeToTopic()];
9792
+ case 2:
9793
+ _b.sent();
9794
+ return [2 /*return*/];
9795
+ }
9796
+ });
9797
+ }); });
9798
+ return [2 /*return*/, this];
9799
+ }
9800
+ });
9801
+ });
9802
+ };
9803
+ ChatSource.prototype.getExistingMessages = function () {
9804
+ return __awaiter(this, void 0, void 0, function () {
9805
+ var messages;
9806
+ var _this = this;
9807
+ return __generator(this, function (_b) {
9808
+ switch (_b.label) {
9809
+ case 0: return [4 /*yield*/, this.peer.getExistingMessages()];
9810
+ case 1:
9811
+ messages = _b.sent();
9812
+ messages = messages.map(function (message) {
9813
+ var existingMessage = _this.messageMap.get(message.id);
9814
+ if (existingMessage)
9815
+ message = Object.assign(existingMessage, message);
9816
+ else
9817
+ _this.messageMap.set(message.id, message);
9818
+ return message;
9819
+ });
9820
+ return [2 /*return*/, messages];
9821
+ }
9822
+ });
9823
+ });
9824
+ };
9825
+ ChatSource.prototype.editMessage = function (messageId, text) {
9826
+ return __awaiter(this, void 0, void 0, function () {
9827
+ return __generator(this, function (_b) {
9828
+ this.peer.editMessage(messageId, text);
9829
+ return [2 /*return*/];
9830
+ });
9831
+ });
9832
+ };
9833
+ ChatSource.prototype.subscribeToTopic = function () {
9834
+ return __awaiter(this, void 0, void 0, function () {
9835
+ return __generator(this, function (_b) {
9836
+ switch (_b.label) {
9837
+ case 0: return [4 /*yield*/, this.peer.subscribe(this.identifier, this.parentIdentifier, this.sortOrder)];
9838
+ case 1:
9839
+ _b.sent();
9840
+ return [2 /*return*/];
9841
+ }
9842
+ });
9843
+ });
9844
+ };
9845
+ ChatSource.prototype.authenticate = function () {
9846
+ var _a;
9847
+ return __awaiter(this, void 0, void 0, function () {
9848
+ return __generator(this, function (_b) {
9849
+ switch (_b.label) {
9850
+ case 0: return [4 /*yield*/, this.peer.authenticate((_a = this.backend.user) === null || _a === void 0 ? void 0 : _a.token)];
9851
+ case 1:
9852
+ _b.sent();
9853
+ return [2 /*return*/];
9854
+ }
9855
+ });
9856
+ });
9857
+ };
9858
+ ChatSource.prototype.close = function () {
9859
+ _super_1.prototype.close.call(this);
9860
+ this.subscription.unsubscribe();
9861
+ };
9862
+ ChatSource.prototype.onPermissions = function (permissions) {
9863
+ window.bantaPermissionsDebug = permissions;
9864
+ this.permissions = permissions;
9865
+ };
9866
+ ChatSource.prototype.onChatMessage = function (message) {
9867
+ if (this.messageMap.has(message.id)) {
9868
+ Object.assign(this.messageMap.get(message.id), message);
9869
+ }
9870
+ else if (!message.hidden) {
9871
+ // Only process non-hidden messages through here.
9872
+ // Hidden messages may be sent to us when they become hidden (ie moderation is occurring).
9873
+ // But if we never had the message to begin with, we should discard it.
9874
+ this.messageMap.set(message.id, message);
9875
+ this._messageReceived.next(message);
9876
+ }
9877
+ };
9878
+ Object.defineProperty(ChatSource.prototype, "messageReceived", {
9879
+ get: function () { return this._messageReceived.asObservable(); },
9880
+ enumerable: false,
9881
+ configurable: true
9882
+ });
9883
+ Object.defineProperty(ChatSource.prototype, "messageSent", {
9884
+ get: function () { return this._messageSent.asObservable(); },
9885
+ enumerable: false,
9886
+ configurable: true
9887
+ });
9888
+ ChatSource.prototype.send = function (message) {
9889
+ return __awaiter(this, void 0, void 0, function () {
9890
+ return __generator(this, function (_b) {
9891
+ switch (_b.label) {
9892
+ case 0: return [4 /*yield*/, this.peer.sendMessage(message)];
9893
+ case 1: return [2 /*return*/, _b.sent()];
9894
+ }
9895
+ });
9896
+ });
9897
+ };
9898
+ ChatSource.prototype.loadAfter = function (message, count) {
9899
+ return __awaiter(this, void 0, void 0, function () {
9900
+ return __generator(this, function (_b) {
9901
+ if (!message)
9902
+ return [2 /*return*/];
9903
+ if (!message.pagingCursor)
9904
+ return [2 /*return*/, []];
9905
+ return [2 /*return*/, this.peer.loadAfter(Number(message.pagingCursor), count)];
9906
+ });
9907
+ });
9908
+ };
9909
+ ChatSource.prototype.get = function (id) {
9910
+ return __awaiter(this, void 0, void 0, function () {
9911
+ var message;
9912
+ return __generator(this, function (_b) {
9913
+ switch (_b.label) {
9914
+ case 0:
9915
+ if (this.messageMap.has(id))
9916
+ return [2 /*return*/, this.messageMap.get(id)];
9917
+ return [4 /*yield*/, this.peer.getMessage(id)];
9918
+ case 1:
9919
+ message = _b.sent();
9920
+ this.messageMap.set(id, message);
9921
+ return [2 /*return*/, message];
9922
+ }
9923
+ });
9924
+ });
9925
+ };
9926
+ ChatSource.prototype.getCount = function () {
9927
+ return __awaiter(this, void 0, void 0, function () {
9928
+ return __generator(this, function (_b) {
9929
+ switch (_b.label) {
9930
+ case 0: return [4 /*yield*/, this.peer.getCount()];
9931
+ case 1: return [2 /*return*/, _b.sent()];
9932
+ }
9933
+ });
9934
+ });
9935
+ };
9936
+ ChatSource.prototype.likeMessage = function (messageId) {
9937
+ return __awaiter(this, void 0, void 0, function () {
9938
+ return __generator(this, function (_b) {
9939
+ switch (_b.label) {
9940
+ case 0: return [4 /*yield*/, this.peer.likeMessage(messageId)];
9941
+ case 1: return [2 /*return*/, _b.sent()];
9942
+ }
9943
+ });
9944
+ });
9945
+ };
9946
+ ChatSource.prototype.unlikeMessage = function (messageId) {
9947
+ return __awaiter(this, void 0, void 0, function () {
9948
+ return __generator(this, function (_b) {
9949
+ switch (_b.label) {
9950
+ case 0: return [4 /*yield*/, this.peer.unlikeMessage(messageId)];
9951
+ case 1: return [2 /*return*/, _b.sent()];
9952
+ }
9953
+ });
9954
+ });
9955
+ };
9956
+ ChatSource.prototype.deleteMessage = function (messageId) {
9957
+ return __awaiter(this, void 0, void 0, function () {
9958
+ return __generator(this, function (_b) {
9959
+ switch (_b.label) {
9960
+ case 0: return [4 /*yield*/, this.peer.deleteMessage(messageId)];
9961
+ case 1: return [2 /*return*/, _b.sent()];
9962
+ }
9963
+ });
9964
+ });
9965
+ };
9966
+ return ChatSource;
9967
+ }(common$1.SocketRPC));
9968
+ __decorate([
9969
+ common$1.RpcEvent(),
9970
+ __metadata("design:type", Function),
9971
+ __metadata("design:paramtypes", [Object]),
9972
+ __metadata("design:returntype", void 0)
9973
+ ], ChatSource.prototype, "onPermissions", null);
9974
+ __decorate([
9975
+ common$1.RpcEvent(),
9976
+ __metadata("design:type", Function),
9977
+ __metadata("design:paramtypes", [Object]),
9978
+ __metadata("design:returntype", void 0)
9979
+ ], ChatSource.prototype, "onChatMessage", null);
9980
+
9981
+ var BANTA_SDK_OPTIONS = 'BANTA_SDK_OPTIONS';
9982
+
9983
+ var ChatBackend = /** @class */ (function (_super) {
9984
+ __extends(ChatBackend, _super);
9985
+ function ChatBackend(options) {
9986
+ var _this = _super.call(this) || this;
9987
+ _this.options = options;
9988
+ return _this;
9989
+ }
9990
+ Object.defineProperty(ChatBackend.prototype, "serviceUrl", {
9991
+ get: function () {
9992
+ var _a, _b;
9993
+ return "" + ((_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.serviceUrl) !== null && _b !== void 0 ? _b : 'http://localhost:3422');
9994
+ },
9995
+ enumerable: false,
9996
+ configurable: true
9997
+ });
9998
+ ChatBackend.prototype.connectToService = function () {
9999
+ return __awaiter(this, void 0, void 0, function () {
10000
+ var socket;
10001
+ return __generator(this, function (_c) {
10002
+ switch (_c.label) {
10003
+ case 0:
10004
+ socket = new common$1.DurableSocket(this.serviceUrl.replace(/^http/, 'ws') + "/socket");
10005
+ return [4 /*yield*/, new Promise(function (resolve, reject) {
10006
+ socket.onopen = function () {
10007
+ resolve();
10008
+ };
10009
+ socket.onclose = function (e) {
10010
+ if (e.code === 503) {
10011
+ console.error("Failed to connect to chat service!");
10012
+ reject(e);
10013
+ }
10014
+ };
10015
+ })];
10016
+ case 1:
10017
+ _c.sent();
10018
+ socket.onerror = undefined;
10019
+ return [2 /*return*/, socket];
10020
+ }
10021
+ });
10022
+ });
10023
+ };
10024
+ ChatBackend.prototype.getSourceForTopic = function (topicId, options) {
10025
+ return __awaiter(this, void 0, void 0, function () {
10026
+ var _c, _d;
10027
+ return __generator(this, function (_e) {
10028
+ switch (_e.label) {
10029
+ case 0:
10030
+ _d = (_c = new ChatSource(this, topicId, undefined, (options === null || options === void 0 ? void 0 : options.sortOrder) || common$1.CommentsOrder.NEWEST))
10031
+ .bind;
10032
+ return [4 /*yield*/, this.connectToService()];
10033
+ case 1: return [4 /*yield*/, _d.apply(_c, [_e.sent()])];
10034
+ case 2: return [2 /*return*/, _e.sent()];
10035
+ }
10036
+ });
10037
+ });
10038
+ };
10039
+ ChatBackend.prototype.getSourceForThread = function (topicId, messageId, options) {
10040
+ return __awaiter(this, void 0, void 0, function () {
10041
+ var _c, _d;
10042
+ return __generator(this, function (_e) {
10043
+ switch (_e.label) {
10044
+ case 0:
10045
+ _d = (_c = new ChatSource(this, topicId, messageId, (options === null || options === void 0 ? void 0 : options.sortOrder) || common$1.CommentsOrder.NEWEST))
10046
+ .bind;
10047
+ return [4 /*yield*/, this.connectToService()];
10048
+ case 1: return [4 /*yield*/, _d.apply(_c, [_e.sent()])];
10049
+ case 2: return [2 /*return*/, _e.sent()];
10050
+ }
10051
+ });
10052
+ });
10053
+ };
10054
+ ChatBackend.prototype.getSourceCountForTopic = function (topicId) {
10055
+ return __awaiter(this, void 0, void 0, function () {
10056
+ var response, topic;
10057
+ return __generator(this, function (_c) {
10058
+ switch (_c.label) {
10059
+ case 0: return [4 /*yield*/, fetch(this.serviceUrl + "/topics/" + topicId)];
10060
+ case 1:
10061
+ response = _c.sent();
10062
+ if (response.status >= 400)
10063
+ return [2 /*return*/, 0];
10064
+ return [4 /*yield*/, response.json()];
10065
+ case 2:
10066
+ topic = _c.sent();
10067
+ return [2 /*return*/, topic.messageCount || 0];
10068
+ }
10069
+ });
10070
+ });
10071
+ };
10072
+ ChatBackend.prototype.refreshMessage = function (message) {
10073
+ throw new Error("Method not implemented.");
10074
+ };
10075
+ ChatBackend.prototype.getMessage = function (topicId, messageId) {
10076
+ throw new Error("Method not implemented.");
10077
+ };
10078
+ ChatBackend.prototype.getSubMessage = function (topicId, parentMessageId, messageId) {
10079
+ throw new Error("Method not implemented.");
10080
+ };
10081
+ ChatBackend.prototype.watchMessage = function (message, handler) {
10082
+ throw new Error("Method not implemented.");
10083
+ };
10084
+ return ChatBackend;
10085
+ }(ChatBackendBase));
10086
+ ChatBackend.decorators = [
10087
+ { type: core.Injectable }
10088
+ ];
10089
+ ChatBackend.ctorParameters = function () { return [
10090
+ { type: undefined, decorators: [{ type: core.Inject, args: [BANTA_SDK_OPTIONS,] }] }
10091
+ ]; };
10092
+
9377
10093
  var BantaSdkModule = /** @class */ (function () {
9378
10094
  function BantaSdkModule() {
9379
10095
  }
9380
- BantaSdkModule.forRoot = function () {
10096
+ BantaSdkModule.configure = function (options) {
9381
10097
  return {
9382
10098
  ngModule: BantaSdkModule,
9383
10099
  providers: [
9384
- BantaService
10100
+ {
10101
+ provide: BANTA_SDK_OPTIONS,
10102
+ useValue: options || {}
10103
+ },
10104
+ { provide: ChatBackendBase, useClass: ChatBackend }
9385
10105
  ]
9386
10106
  };
9387
10107
  };
@@ -9428,16 +10148,18 @@
9428
10148
  * Generated bundle index. Do not edit.
9429
10149
  */
9430
10150
 
10151
+ exports.BANTA_SDK_OPTIONS = BANTA_SDK_OPTIONS;
9431
10152
  exports.BantaChatComponent = BantaChatComponent;
9432
10153
  exports.BantaCommentsComponent = BantaCommentsComponent;
9433
10154
  exports.BantaCommonModule = BantaCommonModule;
9434
10155
  exports.BantaComponent = BantaComponent;
9435
10156
  exports.BantaLogoComponent = BantaLogoComponent;
9436
10157
  exports.BantaSdkModule = BantaSdkModule;
9437
- exports.BantaService = BantaService;
9438
- exports.ChatBackendService = ChatBackendService;
10158
+ exports.ChatBackend = ChatBackend;
10159
+ exports.ChatBackendBase = ChatBackendBase;
9439
10160
  exports.ChatMessageComponent = ChatMessageComponent;
9440
10161
  exports.ChatModule = ChatModule;
10162
+ exports.ChatSource = ChatSource;
9441
10163
  exports.ChatViewComponent = ChatViewComponent;
9442
10164
  exports.CommentComponent = CommentComponent;
9443
10165
  exports.CommentFieldComponent = CommentFieldComponent;