@banta/sdk 5.5.3 → 5.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/lib/banta-sdk.module.mjs +14 -14
- package/esm2022/lib/comments/banta-comments/banta-comments.component.mjs +12 -4
- package/esm2022/lib/comments/comment-field/comment-field.component.mjs +2 -2
- package/esm2022/lib/comments/comment-view/comment-view.component.mjs +272 -34
- package/esm2022/lib/sdk-options.mjs +1 -1
- package/fesm2022/banta-sdk.mjs +293 -46
- package/fesm2022/banta-sdk.mjs.map +1 -1
- package/lib/banta-sdk.module.d.ts +2 -1
- package/lib/chat-source.d.ts +3 -3
- package/lib/comments/banta-comments/banta-comments.component.d.ts +1 -0
- package/lib/comments/comment-view/comment-view.component.d.ts +64 -1
- package/lib/sdk-options.d.ts +3 -1
- package/lib/static-chat-source.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { InjectionToken } from "@angular/core";
|
|
2
2
|
export const BANTA_SDK_OPTIONS = new InjectionToken('BANTA_SDK_OPTIONS');
|
|
3
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2RrLW9wdGlvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9zZGsvc3JjL2xpYi9zZGstb3B0aW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsY0FBYyxFQUFRLE1BQU0sZUFBZSxDQUFDO0FBU3JELE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLElBQUksY0FBYyxDQUFhLG1CQUFtQixDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3Rpb25Ub2tlbiwgVHlwZSB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XHJcbmltcG9ydCB7IENoYXRCYWNrZW5kQmFzZSB9IGZyb20gXCIuL2NoYXQtYmFja2VuZC1iYXNlXCI7XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIFNka09wdGlvbnMge1xyXG4gICAgc2VydmljZVVybD86IHN0cmluZztcclxuICAgIGVtb2ppVXJsPzogc3RyaW5nO1xyXG4gICAgYmFja2VuZENsYXNzPzogVHlwZTxDaGF0QmFja2VuZEJhc2U+XHJcbn1cclxuXHJcbmV4cG9ydCBjb25zdCBCQU5UQV9TREtfT1BUSU9OUyA9IG5ldyBJbmplY3Rpb25Ub2tlbjxTZGtPcHRpb25zPignQkFOVEFfU0RLX09QVElPTlMnKTsiXX0=
|
package/fesm2022/banta-sdk.mjs
CHANGED
|
@@ -7601,7 +7601,27 @@ class CommentViewComponent {
|
|
|
7601
7601
|
this.isViewingMore = false;
|
|
7602
7602
|
this.isLoadingMore = false;
|
|
7603
7603
|
this.hasMore = false;
|
|
7604
|
+
/**
|
|
7605
|
+
* While this is called "new" messages, it really represents the messages that would be visible *at the beginning
|
|
7606
|
+
* of the sort order*, which can be flipped by the newestLast feature (used for replies mode).
|
|
7607
|
+
*
|
|
7608
|
+
* So, when newestLast is false, regardless of the current sortOrder, newMessages are conceptually
|
|
7609
|
+
* *above* the visible set of messages.
|
|
7610
|
+
*
|
|
7611
|
+
* When newestLast is true (as in replies mode), regardless of the current sortOrder, newMessages are conceptually
|
|
7612
|
+
* *below* the visible set of messages.
|
|
7613
|
+
*/
|
|
7604
7614
|
this.newMessages = [];
|
|
7615
|
+
/**
|
|
7616
|
+
* While this is called "older" messages, it really represents the messages that would be visible *at the end of the
|
|
7617
|
+
* sort order*, which can be flipped by the newestLast feature (useds for replies mode).
|
|
7618
|
+
*
|
|
7619
|
+
* So, when newestLast is false, regardless of the current sortOrder, olderMessages are conceptually *below*
|
|
7620
|
+
* the visible set of messages.
|
|
7621
|
+
*
|
|
7622
|
+
* When newestLast is true (as in replies mode), regardless of the current sortOrder, olderMessages are conceptually
|
|
7623
|
+
* *above* the visible set of messages.
|
|
7624
|
+
*/
|
|
7605
7625
|
this.olderMessages = [];
|
|
7606
7626
|
//#endregion
|
|
7607
7627
|
//#region Inputs
|
|
@@ -7640,9 +7660,12 @@ class CommentViewComponent {
|
|
|
7640
7660
|
this.messageEdited = this._messageEdited.asObservable();
|
|
7641
7661
|
this.sortOrderChanged = this._sortOrderChanged.asObservable();
|
|
7642
7662
|
this.filterModeChanged = this._filterModeChanged.asObservable();
|
|
7663
|
+
this.heldMessages = [];
|
|
7643
7664
|
}
|
|
7644
7665
|
get source() { return this._source; }
|
|
7645
7666
|
set source(value) { this.setSource(value); }
|
|
7667
|
+
get previousMessages() { return this.newestLast ? this.olderMessages : this.newMessages; }
|
|
7668
|
+
get nextMessages() { return this.newestLast ? this.newMessages : this.olderMessages; }
|
|
7646
7669
|
get comments() { return Array.from(this.commentsQuery); }
|
|
7647
7670
|
//#endregion
|
|
7648
7671
|
/**
|
|
@@ -7681,10 +7704,12 @@ class CommentViewComponent {
|
|
|
7681
7704
|
get shouldShowNewMessageIndicator() {
|
|
7682
7705
|
return this.isViewingMore
|
|
7683
7706
|
|| this.customSortEnabled
|
|
7684
|
-
|| this.
|
|
7685
|
-
|| this.
|
|
7707
|
+
|| this.sourceFilterMode !== FilterMode.ALL
|
|
7708
|
+
|| this.heldMessages.length > 0;
|
|
7686
7709
|
}
|
|
7687
7710
|
get shouldHoldNewMessages() {
|
|
7711
|
+
if (this.customSortEnabled)
|
|
7712
|
+
return true;
|
|
7688
7713
|
if (this.holdNewMessages || this.isViewingMore) {
|
|
7689
7714
|
console.log(`holding due to settings`);
|
|
7690
7715
|
return true;
|
|
@@ -7772,7 +7797,7 @@ class CommentViewComponent {
|
|
|
7772
7797
|
this._deleted.next(message);
|
|
7773
7798
|
}
|
|
7774
7799
|
setSource(value) {
|
|
7775
|
-
this.customSortEnabled = value?.sortOrder !== CommentsOrder.NEWEST;
|
|
7800
|
+
this.customSortEnabled = (value?.sortOrder ?? CommentsOrder.NEWEST) !== CommentsOrder.NEWEST;
|
|
7776
7801
|
this.newMessages = [];
|
|
7777
7802
|
this.olderMessages = [];
|
|
7778
7803
|
window.bantaSourceDebug = value;
|
|
@@ -7797,23 +7822,78 @@ class CommentViewComponent {
|
|
|
7797
7822
|
let messages = (await this._source.getExistingMessages());
|
|
7798
7823
|
messages.forEach(m => m.transientState ??= {});
|
|
7799
7824
|
this.messages = this.newestLast ? messages.slice().reverse() : messages;
|
|
7825
|
+
if (this.messages.length > this.maxVisibleMessages) {
|
|
7826
|
+
if (this.newestLast) {
|
|
7827
|
+
this.previousMessages.push(...this.messages.splice(0, this.messages.length - this.maxVisibleMessages));
|
|
7828
|
+
}
|
|
7829
|
+
else {
|
|
7830
|
+
this.nextMessages.unshift(...this.messages.splice(this.maxVisibleMessages, this.messages.length));
|
|
7831
|
+
}
|
|
7832
|
+
}
|
|
7833
|
+
this.debugMessages();
|
|
7800
7834
|
this.sortMessages();
|
|
7801
7835
|
if (this.markSourceLoaded)
|
|
7802
7836
|
this.markSourceLoaded();
|
|
7803
7837
|
}
|
|
7838
|
+
debugMessages() {
|
|
7839
|
+
console.log([
|
|
7840
|
+
...this.previousMessages.map(x => x.message),
|
|
7841
|
+
'[[',
|
|
7842
|
+
...this.messages.map(x => x.message),
|
|
7843
|
+
']]',
|
|
7844
|
+
...this.nextMessages.map(x => x.message)
|
|
7845
|
+
].map(x => /\d+/.test(x) ? this.zeroPad(x, 2) : x).join(" "));
|
|
7846
|
+
}
|
|
7847
|
+
zeroPad(number, count = 2) {
|
|
7848
|
+
let str;
|
|
7849
|
+
if (typeof number === 'number')
|
|
7850
|
+
str = String(number);
|
|
7851
|
+
else
|
|
7852
|
+
str = number;
|
|
7853
|
+
while (str.length < count)
|
|
7854
|
+
str = '0' + str;
|
|
7855
|
+
return str;
|
|
7856
|
+
}
|
|
7857
|
+
leftPad(str, count = 2) {
|
|
7858
|
+
while (str.length < count)
|
|
7859
|
+
str = ' ' + str;
|
|
7860
|
+
return str;
|
|
7861
|
+
}
|
|
7804
7862
|
messageIdentity(index, chatMessage) {
|
|
7805
7863
|
return chatMessage.id;
|
|
7806
7864
|
}
|
|
7807
|
-
|
|
7865
|
+
get sourceSortOrder() {
|
|
7866
|
+
return this.source?.sortOrder ?? CommentsOrder.NEWEST;
|
|
7867
|
+
}
|
|
7868
|
+
get sourceFilterMode() {
|
|
7869
|
+
return this.source?.filterMode ?? FilterMode.ALL;
|
|
7870
|
+
}
|
|
7871
|
+
/**
|
|
7872
|
+
* Show the newest content.
|
|
7873
|
+
* - If an unnatural sort order is active (ie Oldest or Likes), it will be changed to Newest.
|
|
7874
|
+
* - The new content will be placed where new content goes based on newestLast (replies mode), so if it is true, the content is
|
|
7875
|
+
* placed at the end, otherwise it is placed at the beginning.
|
|
7876
|
+
*
|
|
7877
|
+
* @param event
|
|
7878
|
+
* @returns
|
|
7879
|
+
*/
|
|
7880
|
+
async showNewest(event) {
|
|
7881
|
+
// Regardless of how we handle this, clear out our held messages
|
|
7882
|
+
this.heldMessages = [];
|
|
7883
|
+
// If the sort order is not already Newest, switch to Newest and stop.
|
|
7884
|
+
// The act of changing the sort order will cause the newest content to be loaded.
|
|
7808
7885
|
let naturalOrder = CommentsOrder.NEWEST;
|
|
7809
|
-
if (this.
|
|
7810
|
-
if (this.
|
|
7886
|
+
if (this.sourceSortOrder !== naturalOrder || this.sourceFilterMode !== FilterMode.ALL) {
|
|
7887
|
+
if (this.sourceSortOrder !== naturalOrder)
|
|
7811
7888
|
this._sortOrderChanged.next(naturalOrder);
|
|
7812
|
-
if (this.
|
|
7889
|
+
if (this.sourceFilterMode !== FilterMode.ALL)
|
|
7813
7890
|
this._filterModeChanged.next(FilterMode.ALL);
|
|
7814
7891
|
return;
|
|
7815
7892
|
}
|
|
7893
|
+
// On this path, we are already on Newest, but there is newer content available (such as when new content is
|
|
7894
|
+
// being buffered due to user engagement on a comment)
|
|
7816
7895
|
this.isViewingMore = false;
|
|
7896
|
+
// Move all newerMessages into messages, respecting the newestLast direction (normal or replies mode)
|
|
7817
7897
|
if (this.newestLast)
|
|
7818
7898
|
this.messages = this.messages.concat(this.newMessages.splice(0, this.newMessages.length));
|
|
7819
7899
|
else
|
|
@@ -7822,6 +7902,7 @@ class CommentViewComponent {
|
|
|
7822
7902
|
this.olderMessages = overflow.concat(this.olderMessages);
|
|
7823
7903
|
this.olderMessages.splice(this.maxMessages - this.maxVisibleMessages, this.olderMessages.length);
|
|
7824
7904
|
this.hasMore = this.olderMessages.length > 0;
|
|
7905
|
+
// Scroll to the newest comment.
|
|
7825
7906
|
if (this.messages.length > 0) {
|
|
7826
7907
|
if (this.newestLast) {
|
|
7827
7908
|
this.scrollToComment(this.messages[this.messages.length - 1].id);
|
|
@@ -7831,39 +7912,192 @@ class CommentViewComponent {
|
|
|
7831
7912
|
}
|
|
7832
7913
|
}
|
|
7833
7914
|
}
|
|
7834
|
-
|
|
7915
|
+
get showDebug() {
|
|
7916
|
+
if (typeof window === 'undefined')
|
|
7917
|
+
return false;
|
|
7918
|
+
return localStorage['banta:debug'] === '1';
|
|
7919
|
+
}
|
|
7920
|
+
get shouldShowNext() {
|
|
7921
|
+
if (!this.newestLast) {
|
|
7922
|
+
return this.hasMore || this.nextMessages.length > 0;
|
|
7923
|
+
}
|
|
7924
|
+
return this.nextMessages.length > 0;
|
|
7925
|
+
}
|
|
7926
|
+
get shouldShowPrevious() {
|
|
7927
|
+
if (this.newestLast) {
|
|
7928
|
+
return this.hasMore || this.previousMessages.length > 0;
|
|
7929
|
+
}
|
|
7930
|
+
return this.previousMessages.length > 0;
|
|
7931
|
+
}
|
|
7932
|
+
get pageSize() {
|
|
7933
|
+
return Math.min(20, this.maxVisibleMessages);
|
|
7934
|
+
}
|
|
7935
|
+
async showPrevious() {
|
|
7835
7936
|
this.isViewingMore = true;
|
|
7836
|
-
|
|
7937
|
+
let nextPageSize = this.pageSize;
|
|
7938
|
+
this.isLoadingMore = false;
|
|
7939
|
+
if (this.previousMessages.length > 0) {
|
|
7940
|
+
const storedMessages = this.previousMessages.splice(Math.max(0, this.previousMessages.length - nextPageSize), nextPageSize);
|
|
7941
|
+
this.messages = [...storedMessages, ...this.messages];
|
|
7942
|
+
nextPageSize -= storedMessages.length;
|
|
7943
|
+
}
|
|
7944
|
+
// Load more from backend if needed
|
|
7945
|
+
// Note: Backend only supports fetching more content in one direction.
|
|
7946
|
+
let lastMessage = this.previousMessages[0] ?? this.messages[0];
|
|
7947
|
+
if (!lastMessage)
|
|
7948
|
+
this.hasMore = false;
|
|
7949
|
+
if (nextPageSize > 0 && this.newestLast && lastMessage) {
|
|
7950
|
+
this.isLoadingMore = true;
|
|
7951
|
+
let messages = await this.source.loadAfter(lastMessage, nextPageSize);
|
|
7952
|
+
messages = messages.slice().reverse(); // because newestLast === true
|
|
7953
|
+
messages.forEach(m => m.transientState ??= {});
|
|
7954
|
+
// In replies mode (newestLast), we want to put these new messages onto the *top* of the set of visible messages.
|
|
7955
|
+
// Otherwise we want to put them on the *bottom*.
|
|
7956
|
+
this.messages = [...messages, ...this.messages];
|
|
7957
|
+
// If we didn't receive any messages at all, there's no more to fetch.
|
|
7958
|
+
if (messages.length === 0)
|
|
7959
|
+
this.hasMore = false;
|
|
7837
7960
|
this.isLoadingMore = false;
|
|
7838
|
-
this.messages = this.messages.concat(this.olderMessages.splice(0, 50));
|
|
7839
7961
|
}
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
|
|
7962
|
+
// Extract the messages that do not fit in the maxVisibleMessages buffer.
|
|
7963
|
+
if (this.messages.length > this.maxVisibleMessages) {
|
|
7964
|
+
let overflow = this.messages.splice(this.maxVisibleMessages, this.messages.length);
|
|
7965
|
+
this.nextMessages.unshift(...overflow);
|
|
7966
|
+
if (this.nextMessages.length > this.maxMessages)
|
|
7967
|
+
this.nextMessages.splice(this.maxMessages, this.nextMessages.length);
|
|
7845
7968
|
}
|
|
7846
|
-
|
|
7847
|
-
|
|
7969
|
+
this.debugMessages();
|
|
7970
|
+
}
|
|
7971
|
+
get sortNextLabel() {
|
|
7972
|
+
if (this.sourceSortOrder === 'newest') {
|
|
7973
|
+
return 'Older';
|
|
7848
7974
|
}
|
|
7849
|
-
if (
|
|
7850
|
-
|
|
7851
|
-
this.hasMore = false;
|
|
7852
|
-
return;
|
|
7975
|
+
else if (this.sourceSortOrder === 'oldest') {
|
|
7976
|
+
return 'Newer';
|
|
7853
7977
|
}
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
7978
|
+
else if (this.sourceSortOrder === 'likes') {
|
|
7979
|
+
return 'Less Likes';
|
|
7980
|
+
}
|
|
7981
|
+
return 'More';
|
|
7982
|
+
}
|
|
7983
|
+
get sortPreviousLabel() {
|
|
7984
|
+
if (this.sourceSortOrder === 'newest') {
|
|
7985
|
+
return 'Newer';
|
|
7986
|
+
}
|
|
7987
|
+
else if (this.sourceSortOrder === 'oldest') {
|
|
7988
|
+
return 'Older';
|
|
7989
|
+
}
|
|
7990
|
+
else if (this.sourceSortOrder === 'likes') {
|
|
7991
|
+
return 'More Likes';
|
|
7992
|
+
}
|
|
7993
|
+
return 'More';
|
|
7994
|
+
}
|
|
7995
|
+
get nextLabel() { return this.newestLast ? this.sortPreviousLabel : this.sortNextLabel; }
|
|
7996
|
+
get previousLabel() { return this.newestLast ? this.sortNextLabel : this.sortPreviousLabel; }
|
|
7997
|
+
/**
|
|
7998
|
+
* Show more content
|
|
7999
|
+
* - When in replies mode (newestLast), the content is added at the top
|
|
8000
|
+
* - When in normal mode, the content is added at the bottom
|
|
8001
|
+
* - The current sort order does *not* factor in here, which is why it is showMore() not showEarlier().
|
|
8002
|
+
*
|
|
8003
|
+
* @returns
|
|
8004
|
+
*/
|
|
8005
|
+
async showNext() {
|
|
8006
|
+
this.isViewingMore = true;
|
|
8007
|
+
let nextPageSize = this.pageSize;
|
|
7862
8008
|
this.isLoadingMore = false;
|
|
7863
|
-
if (
|
|
7864
|
-
|
|
8009
|
+
if (this.nextMessages.length > 0) {
|
|
8010
|
+
const storedMessages = this.nextMessages.splice(0, nextPageSize);
|
|
8011
|
+
this.messages = [...this.messages, ...storedMessages];
|
|
8012
|
+
nextPageSize -= storedMessages.length;
|
|
8013
|
+
this.hasMore = this.nextMessages.length > 0;
|
|
8014
|
+
}
|
|
8015
|
+
const lastMessage = this.olderMessages[this.olderMessages.length - 1] ?? this.messages[this.messages.length - 1];
|
|
8016
|
+
if (!lastMessage)
|
|
7865
8017
|
this.hasMore = false;
|
|
8018
|
+
if (nextPageSize > 0 && !this.newestLast && lastMessage) {
|
|
8019
|
+
// Load more from backend
|
|
8020
|
+
this.isLoadingMore = true;
|
|
8021
|
+
let messages = await this.source.loadAfter(lastMessage, nextPageSize);
|
|
8022
|
+
messages.forEach(m => m.transientState ??= {});
|
|
8023
|
+
this.messages = [...this.messages, ...messages];
|
|
8024
|
+
// If we didn't receive any messages at all, there's no more to fetch.
|
|
8025
|
+
if (messages.length === 0)
|
|
8026
|
+
this.hasMore = false;
|
|
8027
|
+
this.isLoadingMore = false;
|
|
8028
|
+
}
|
|
8029
|
+
// Extract the messages that do not fit in the maxVisibleMessages buffer.
|
|
8030
|
+
if (this.messages.length > this.maxVisibleMessages) {
|
|
8031
|
+
let overflow = this.messages.splice(0, this.messages.length - this.maxVisibleMessages);
|
|
8032
|
+
// Regardless of the order (newestLast), newMessages represents the direction that is being pushed, since it's definition
|
|
8033
|
+
// depends on that order. Move overflowing messages into newMessages.
|
|
8034
|
+
this.previousMessages.push(...overflow);
|
|
8035
|
+
if (this.previousMessages.length > this.maxMessages)
|
|
8036
|
+
this.previousMessages.splice(0, this.previousMessages.length - this.maxMessages);
|
|
7866
8037
|
}
|
|
8038
|
+
this.debugMessages();
|
|
8039
|
+
}
|
|
8040
|
+
/**
|
|
8041
|
+
* Show more content
|
|
8042
|
+
* - When in replies mode (newestLast), the content is added at the top
|
|
8043
|
+
* - When in normal mode, the content is added at the bottom
|
|
8044
|
+
* - The current sort order does *not* factor in here, which is why it is showMore() not showEarlier().
|
|
8045
|
+
*
|
|
8046
|
+
* @returns
|
|
8047
|
+
*/
|
|
8048
|
+
async showMore() {
|
|
8049
|
+
this.isViewingMore = true;
|
|
8050
|
+
let nextPageSize = this.pageSize;
|
|
8051
|
+
this.isLoadingMore = false;
|
|
8052
|
+
if (this.olderMessages.length > 0) {
|
|
8053
|
+
const storedMessages = this.olderMessages.splice(0, nextPageSize);
|
|
8054
|
+
this.messages = this.messages.concat(storedMessages);
|
|
8055
|
+
nextPageSize -= storedMessages.length;
|
|
8056
|
+
this.hasMore = this.olderMessages.length > 0;
|
|
8057
|
+
}
|
|
8058
|
+
if (nextPageSize > 0) {
|
|
8059
|
+
// Load more from backend
|
|
8060
|
+
this.isLoadingMore = true;
|
|
8061
|
+
let lastMessage;
|
|
8062
|
+
if (this.newestLast) {
|
|
8063
|
+
lastMessage = this.olderMessages[0] ?? this.messages[0];
|
|
8064
|
+
}
|
|
8065
|
+
else {
|
|
8066
|
+
lastMessage = this.olderMessages[this.olderMessages.length - 1] ?? this.messages[this.messages.length - 1];
|
|
8067
|
+
}
|
|
8068
|
+
if (!lastMessage) {
|
|
8069
|
+
this.isLoadingMore = false;
|
|
8070
|
+
this.hasMore = false;
|
|
8071
|
+
return;
|
|
8072
|
+
}
|
|
8073
|
+
let messages = await this.source.loadAfter(lastMessage, nextPageSize);
|
|
8074
|
+
if (this.newestLast)
|
|
8075
|
+
messages = messages.slice().reverse();
|
|
8076
|
+
messages.forEach(m => m.transientState ??= {});
|
|
8077
|
+
// In replies mode (newestLast), we want to put these new messages onto the *top* of the set of visible messages.
|
|
8078
|
+
// Otherwise we want to put them on the *bottom*.
|
|
8079
|
+
if (this.newestLast) {
|
|
8080
|
+
this.messages = messages.concat(this.messages);
|
|
8081
|
+
}
|
|
8082
|
+
else {
|
|
8083
|
+
this.messages = this.messages.concat(messages);
|
|
8084
|
+
}
|
|
8085
|
+
// If we didn't receive any messages at all, there's no more to fetch.
|
|
8086
|
+
if (messages.length === 0) {
|
|
8087
|
+
this.hasMore = false;
|
|
8088
|
+
}
|
|
8089
|
+
this.isLoadingMore = false;
|
|
8090
|
+
}
|
|
8091
|
+
// Extract the messages that do not fit in the maxVisibleMessages buffer.
|
|
8092
|
+
let overflow;
|
|
8093
|
+
if (this.newestLast)
|
|
8094
|
+
overflow = this.messages.splice(this.maxVisibleMessages, this.messages.length);
|
|
8095
|
+
else
|
|
8096
|
+
overflow = this.messages.splice(0, this.maxVisibleMessages);
|
|
8097
|
+
// Regardless of the order (newestLast), newMessages represents the direction that is being pushed, since it's definition
|
|
8098
|
+
// depends on that order. Move overflowing messages into newMessages.
|
|
8099
|
+
this.newMessages = overflow.concat(this.newMessages);
|
|
8100
|
+
this.newMessages.splice(this.maxMessages - this.maxVisibleMessages, this.newMessages.length);
|
|
7867
8101
|
}
|
|
7868
8102
|
addMessage(message) {
|
|
7869
8103
|
if (!message.transientState)
|
|
@@ -7872,9 +8106,13 @@ class CommentViewComponent {
|
|
|
7872
8106
|
let bucket = this.olderMessages;
|
|
7873
8107
|
let newestLast = this.newestLast;
|
|
7874
8108
|
if (this.shouldHoldNewMessages) {
|
|
8109
|
+
this.heldMessages.push(message);
|
|
7875
8110
|
destination = this.newMessages;
|
|
7876
8111
|
bucket = null;
|
|
7877
8112
|
}
|
|
8113
|
+
// If we aren't on the newest sort order, new messages shouldn't be added at all
|
|
8114
|
+
if (this.sourceSortOrder !== CommentsOrder.NEWEST)
|
|
8115
|
+
return;
|
|
7878
8116
|
if (newestLast) {
|
|
7879
8117
|
destination.push(message);
|
|
7880
8118
|
let overflow = destination.splice(this.maxVisibleMessages, destination.length);
|
|
@@ -7980,11 +8218,11 @@ class CommentViewComponent {
|
|
|
7980
8218
|
return false;
|
|
7981
8219
|
}
|
|
7982
8220
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: CommentViewComponent, deps: [{ token: ChatBackendBase }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7983
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
8221
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.9", type: CommentViewComponent, selector: "banta-comment-view", inputs: { source: "source", maxMessages: "maxMessages", maxVisibleMessages: "maxVisibleMessages", newestLast: "newestLast", holdNewMessages: "holdNewMessages", showEmptyState: "showEmptyState", allowReplies: "allowReplies", enableHoldOnClick: "enableHoldOnClick", enableHoldOnScroll: "enableHoldOnScroll", customMenuItems: "customMenuItems", fixedHeight: "fixedHeight", selectedMessage: "selectedMessage", genericAvatarUrl: "genericAvatarUrl" }, outputs: { userSelected: "userSelected", reported: "reported", liked: "liked", unliked: "unliked", usernameSelected: "usernameSelected", avatarSelected: "avatarSelected", shared: "shared", deleted: "deleted", selected: "selected", messageEdited: "messageEdited", sortOrderChanged: "sortOrderChanged", filterModeChanged: "filterModeChanged" }, host: { properties: { "class.fixed-height": "this.fixedHeight" } }, viewQueries: [{ propertyName: "messageContainer", first: true, predicate: ["messageContainer"], descendants: true }, { propertyName: "commentsQuery", predicate: CommentComponent, descendants: true }], ngImport: i0, template: "<div class=\"banta-message-container\" #messageContainer>\r\n <ng-content select=\"[data-before]\"></ng-content>\r\n\r\n <div class=\"banta-top-sticky\">\r\n @if (!newestLast) {\r\n <button \r\n mat-button \r\n class=\"banta-nav\" \r\n [class.visible]=\"shouldShowNewMessageIndicator\" \r\n href=\"javascript:;\" \r\n (click)=\"showNewest($event)\"\r\n >\r\n <mat-icon>file_upload</mat-icon>\r\n Newest\r\n @if (heldMessages.length > 0) {\r\n <span class=\"count\">{{ heldMessages.length | number }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n\r\n <button mat-button class=\"pager\" (click)=\"showPrevious()\" [class.visible]=\"shouldShowPrevious\" [disabled]=\"isLoadingMore\">\r\n <mat-icon>expand_less</mat-icon>\r\n {{ previousLabel }}\r\n </button>\r\n\r\n @for (message of messages; track message.id) {\r\n @if (!message.hidden) {\r\n <banta-comment\r\n class=\"abbreviated\"\r\n \r\n [customMenuItems]=\"customMenuItems\"\r\n [message]=\"message\"\r\n [mine]=\"currentUser?.id === message.user?.id\"\r\n [permissions]=\"source?.permissions\"\r\n [showReplyAction]=\"allowReplies\"\r\n [editing]=\"message.transientState.editing\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n [readonly]=\"source?.readonly\"\r\n (click)=\"enableHoldOnClick ? (holdNewMessages = true) : undefined\"\r\n (editStarted)=\"startEditing(message)\"\r\n (deleted)=\"deleteMessage(message)\"\r\n (editEnded)=\"message.transientState.editing = false\"\r\n (edited)=\"saveEdit(message, $event)\"\r\n (userSelected)=\"selectMessageUser(message)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (liked)=\"likeMessage(message)\"\r\n (unliked)=\"unlikeMessage(message)\"\r\n (reported)=\"reportMessage(message)\"\r\n (selected)=\"selectMessage(message)\"\r\n (shared)=\"sharedMessage($event)\"\r\n />\r\n <div class=\"banta-inline-replies-container\" *ngIf=\"selectedMessage === message\">\r\n <ng-content select=\".inline-replies\"></ng-content>\r\n </div>\r\n }\r\n } @empty {\r\n <div class=\"banta-empty-state\" *ngIf=\"showEmptyState\">\r\n Be the first to comment!\r\n </div>\r\n }\r\n\r\n <button mat-button class=\"pager\" (click)=\"showNext()\" [class.visible]=\"shouldShowNext\" [disabled]=\"isLoadingMore\">\r\n <mat-icon>expand_more</mat-icon>\r\n {{ nextLabel }}\r\n </button>\r\n\r\n <div class=\"banta-nav-point banta-bottom-sticky\">\r\n @if (newestLast) {\r\n <button \r\n [matBadge]=\"10\" matBadgeOverlap=\"false\"\r\n matBadgePosition=\"after\" matBadgeSize=\"large\" \r\n mat-button \r\n class=\"banta-nav\" \r\n [class.visible]=\"shouldShowNewMessageIndicator\" \r\n href=\"javascript:;\" \r\n (click)=\"showNewest($event)\"\r\n >\r\n <mat-icon>file_download</mat-icon>\r\n Newest\r\n @if (heldMessages.length > 0) {\r\n <span class=\"count\">{{ heldMessages.length | number }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n\r\n <div class=\"banta-loading-more\" *ngIf=\"isLoadingMore\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n\r\n @if (showDebug) {\r\n <div style=\"color: #666\">\r\n ({{ previousMessages.length }} .. {{ messages.length }} .. {{ nextMessages.length }})\r\n\r\n dir={{newestLast ? '-1' : '1'}}\r\n v={{maxVisibleMessages}}, M={{maxMessages}}\r\n </div>\r\n }\r\n\r\n <ng-content select=\":not([data-before]):not(.inline-replies)\"></ng-content>\r\n</div>\r\n", styles: [":host{flex-grow:1;display:flex;flex-direction:column;opacity:1;transition:.2s opacity ease-in}.banta-message-container{flex-grow:1;color:#111;background:#fff;padding:.5em 1em 3em .5em;opacity:1;transition:.5s opacity ease-in-out;position:relative}.banta-message-container.no-scroll{height:auto;overflow-y:visible}.banta-message-container.faded{opacity:.25}.banta-message-container .overlay{position:absolute;inset:0;z-index:10}:host.fixed-height .banta-message-container{overflow-y:auto}:host-context(.mat-dark-theme) .banta-message-container{color:#fff;background:#111}.banta-empty-state{text-align:center;margin:3em;color:#666}:host-context(.mat-dark-theme) .empty-state{color:#666}button.banta-nav{position:absolute;right:.5em;z-index:10;text-align:center;opacity:0;transition:.4s opacity ease-in-out;pointer-events:none;border-radius:2em;background-color:#ddd}:host-context(.mat-dark-theme) button.banta-nav{background-color:#222;color:#fff}button.banta-nav span.count{background-color:#a93535;color:#fff;padding:4px 10px;border-radius:.5em;margin-left:.25em;font-size:90%}button.banta-nav.visible{opacity:1;pointer-events:initial}button.pager{appearance:none;border:none;width:100%;opacity:0;pointer-events:none;transition:.4s opacity ease-in-out}button.pager.visible{opacity:1;pointer-events:initial}.banta-top-sticky{position:sticky;top:.5em;z-index:10}.banta-bottom-sticky{position:sticky;bottom:3em;z-index:10}.banta-loading-more{padding:2em;text-align:center;margin:0 auto;width:fit-content}@media (max-width: 400px){.banta-message-container{padding:0 0 3em}}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i8.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: CommentComponent, selector: "banta-comment", inputs: ["message", "customMenuItems", "showReplyAction", "maxLength", "permissions", "mine", "editing", "genericAvatarUrl", "readonly"], outputs: ["liked", "unliked", "selected", "edited", "deleted", "editStarted", "editEnded", "shared", "userSelected", "usernameSelected", "avatarSelected", "reported", "loaded"] }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }] }); }
|
|
7984
8222
|
}
|
|
7985
8223
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: CommentViewComponent, decorators: [{
|
|
7986
8224
|
type: Component,
|
|
7987
|
-
args: [{ selector: 'banta-comment-view', template: "<div class=\"banta-message-container\" #messageContainer>\r\n <ng-content select=\"[data-before]\"></ng-content>\r\n\r\n <div class=\"banta-top-sticky\">\r\n
|
|
8225
|
+
args: [{ selector: 'banta-comment-view', template: "<div class=\"banta-message-container\" #messageContainer>\r\n <ng-content select=\"[data-before]\"></ng-content>\r\n\r\n <div class=\"banta-top-sticky\">\r\n @if (!newestLast) {\r\n <button \r\n mat-button \r\n class=\"banta-nav\" \r\n [class.visible]=\"shouldShowNewMessageIndicator\" \r\n href=\"javascript:;\" \r\n (click)=\"showNewest($event)\"\r\n >\r\n <mat-icon>file_upload</mat-icon>\r\n Newest\r\n @if (heldMessages.length > 0) {\r\n <span class=\"count\">{{ heldMessages.length | number }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n\r\n <button mat-button class=\"pager\" (click)=\"showPrevious()\" [class.visible]=\"shouldShowPrevious\" [disabled]=\"isLoadingMore\">\r\n <mat-icon>expand_less</mat-icon>\r\n {{ previousLabel }}\r\n </button>\r\n\r\n @for (message of messages; track message.id) {\r\n @if (!message.hidden) {\r\n <banta-comment\r\n class=\"abbreviated\"\r\n \r\n [customMenuItems]=\"customMenuItems\"\r\n [message]=\"message\"\r\n [mine]=\"currentUser?.id === message.user?.id\"\r\n [permissions]=\"source?.permissions\"\r\n [showReplyAction]=\"allowReplies\"\r\n [editing]=\"message.transientState.editing\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n [readonly]=\"source?.readonly\"\r\n (click)=\"enableHoldOnClick ? (holdNewMessages = true) : undefined\"\r\n (editStarted)=\"startEditing(message)\"\r\n (deleted)=\"deleteMessage(message)\"\r\n (editEnded)=\"message.transientState.editing = false\"\r\n (edited)=\"saveEdit(message, $event)\"\r\n (userSelected)=\"selectMessageUser(message)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (liked)=\"likeMessage(message)\"\r\n (unliked)=\"unlikeMessage(message)\"\r\n (reported)=\"reportMessage(message)\"\r\n (selected)=\"selectMessage(message)\"\r\n (shared)=\"sharedMessage($event)\"\r\n />\r\n <div class=\"banta-inline-replies-container\" *ngIf=\"selectedMessage === message\">\r\n <ng-content select=\".inline-replies\"></ng-content>\r\n </div>\r\n }\r\n } @empty {\r\n <div class=\"banta-empty-state\" *ngIf=\"showEmptyState\">\r\n Be the first to comment!\r\n </div>\r\n }\r\n\r\n <button mat-button class=\"pager\" (click)=\"showNext()\" [class.visible]=\"shouldShowNext\" [disabled]=\"isLoadingMore\">\r\n <mat-icon>expand_more</mat-icon>\r\n {{ nextLabel }}\r\n </button>\r\n\r\n <div class=\"banta-nav-point banta-bottom-sticky\">\r\n @if (newestLast) {\r\n <button \r\n [matBadge]=\"10\" matBadgeOverlap=\"false\"\r\n matBadgePosition=\"after\" matBadgeSize=\"large\" \r\n mat-button \r\n class=\"banta-nav\" \r\n [class.visible]=\"shouldShowNewMessageIndicator\" \r\n href=\"javascript:;\" \r\n (click)=\"showNewest($event)\"\r\n >\r\n <mat-icon>file_download</mat-icon>\r\n Newest\r\n @if (heldMessages.length > 0) {\r\n <span class=\"count\">{{ heldMessages.length | number }}</span>\r\n }\r\n </button>\r\n }\r\n </div>\r\n\r\n <div class=\"banta-loading-more\" *ngIf=\"isLoadingMore\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n\r\n @if (showDebug) {\r\n <div style=\"color: #666\">\r\n ({{ previousMessages.length }} .. {{ messages.length }} .. {{ nextMessages.length }})\r\n\r\n dir={{newestLast ? '-1' : '1'}}\r\n v={{maxVisibleMessages}}, M={{maxMessages}}\r\n </div>\r\n }\r\n\r\n <ng-content select=\":not([data-before]):not(.inline-replies)\"></ng-content>\r\n</div>\r\n", styles: [":host{flex-grow:1;display:flex;flex-direction:column;opacity:1;transition:.2s opacity ease-in}.banta-message-container{flex-grow:1;color:#111;background:#fff;padding:.5em 1em 3em .5em;opacity:1;transition:.5s opacity ease-in-out;position:relative}.banta-message-container.no-scroll{height:auto;overflow-y:visible}.banta-message-container.faded{opacity:.25}.banta-message-container .overlay{position:absolute;inset:0;z-index:10}:host.fixed-height .banta-message-container{overflow-y:auto}:host-context(.mat-dark-theme) .banta-message-container{color:#fff;background:#111}.banta-empty-state{text-align:center;margin:3em;color:#666}:host-context(.mat-dark-theme) .empty-state{color:#666}button.banta-nav{position:absolute;right:.5em;z-index:10;text-align:center;opacity:0;transition:.4s opacity ease-in-out;pointer-events:none;border-radius:2em;background-color:#ddd}:host-context(.mat-dark-theme) button.banta-nav{background-color:#222;color:#fff}button.banta-nav span.count{background-color:#a93535;color:#fff;padding:4px 10px;border-radius:.5em;margin-left:.25em;font-size:90%}button.banta-nav.visible{opacity:1;pointer-events:initial}button.pager{appearance:none;border:none;width:100%;opacity:0;pointer-events:none;transition:.4s opacity ease-in-out}button.pager.visible{opacity:1;pointer-events:initial}.banta-top-sticky{position:sticky;top:.5em;z-index:10}.banta-bottom-sticky{position:sticky;bottom:3em;z-index:10}.banta-loading-more{padding:2em;text-align:center;margin:0 auto;width:fit-content}@media (max-width: 400px){.banta-message-container{padding:0 0 3em}}\n"] }]
|
|
7988
8226
|
}], ctorParameters: () => [{ type: ChatBackendBase }, { type: i0.ElementRef }], propDecorators: { source: [{
|
|
7989
8227
|
type: Input
|
|
7990
8228
|
}], maxMessages: [{
|
|
@@ -8292,7 +8530,7 @@ class CommentFieldComponent {
|
|
|
8292
8530
|
return false;
|
|
8293
8531
|
if (this.signInState === 'signing-in')
|
|
8294
8532
|
return false;
|
|
8295
|
-
if (!['connected', 'restored'].includes(this.source
|
|
8533
|
+
if (!['connected', 'restored'].includes(this.source?.state ?? 'connected'))
|
|
8296
8534
|
return false;
|
|
8297
8535
|
if (!this.canComment) {
|
|
8298
8536
|
// In this case, we want to enable the button because we want to be able to
|
|
@@ -8873,8 +9111,13 @@ class BantaCommentsComponent {
|
|
|
8873
9111
|
await this.threadViewQuery.changes.pipe(take(1)).toPromise();
|
|
8874
9112
|
return this.threadView;
|
|
8875
9113
|
}
|
|
9114
|
+
get sourceState() {
|
|
9115
|
+
if (!this.source)
|
|
9116
|
+
return 'no-source';
|
|
9117
|
+
return this.source.state ?? 'connected';
|
|
9118
|
+
}
|
|
8876
9119
|
updateLoading() {
|
|
8877
|
-
if (this.
|
|
9120
|
+
if (this.sourceState && !['connecting', 'lost'].includes(this.sourceState)) {
|
|
8878
9121
|
clearInterval(this._loadingTimer);
|
|
8879
9122
|
this.loadingMessage = `Here we go!`;
|
|
8880
9123
|
setTimeout(() => {
|
|
@@ -8883,7 +9126,7 @@ class BantaCommentsComponent {
|
|
|
8883
9126
|
}, 750);
|
|
8884
9127
|
return true;
|
|
8885
9128
|
}
|
|
8886
|
-
console.log(`[Banta/Loader] State=${this.
|
|
9129
|
+
console.log(`[Banta/Loader] State=${this.sourceState}`);
|
|
8887
9130
|
let messageSwitchTime = 5 * 1000;
|
|
8888
9131
|
if (this.messageChangedAt + messageSwitchTime < Date.now()) {
|
|
8889
9132
|
if (this.loadingMessages[this._loadingMessageIndex]) {
|
|
@@ -8911,7 +9154,10 @@ class BantaCommentsComponent {
|
|
|
8911
9154
|
this.sharedCommentID = null;
|
|
8912
9155
|
}
|
|
8913
9156
|
this._source.messages.forEach(m => this.addParticipant(m));
|
|
8914
|
-
|
|
9157
|
+
if (this._source.connectionStateChanged)
|
|
9158
|
+
this._sourceSubscription.add(this._source.connectionStateChanged.subscribe(state => this.connectionState = state));
|
|
9159
|
+
else
|
|
9160
|
+
this.connectionState = 'connected';
|
|
8915
9161
|
this._sourceSubscription.add(this._source.messageReceived.subscribe(m => this.addParticipant(m)));
|
|
8916
9162
|
this._sourceSubscription.add(this._source.messageSent.subscribe(m => this.addParticipant(m)));
|
|
8917
9163
|
this._sourceSubscription.add(this._source.messageObserved.subscribe(m => this.addParticipant(m)));
|
|
@@ -10916,12 +11162,13 @@ class TweetAttachmentResolver {
|
|
|
10916
11162
|
}
|
|
10917
11163
|
|
|
10918
11164
|
class BantaSdkModule {
|
|
10919
|
-
constructor(
|
|
10920
|
-
chatBackend
|
|
10921
|
-
chatBackend.
|
|
10922
|
-
chatBackend.registerAttachmentResolver(new
|
|
10923
|
-
chatBackend.registerAttachmentResolver(new
|
|
10924
|
-
chatBackend.registerAttachmentResolver(new
|
|
11165
|
+
constructor() {
|
|
11166
|
+
this.chatBackend = inject(ChatBackendBase);
|
|
11167
|
+
this.chatBackend.registerAttachmentScraper(new UrlAttachmentScraper());
|
|
11168
|
+
this.chatBackend.registerAttachmentResolver(new GiphyAttachmentResolver());
|
|
11169
|
+
this.chatBackend.registerAttachmentResolver(new YouTubeAttachmentResolver());
|
|
11170
|
+
this.chatBackend.registerAttachmentResolver(new TweetAttachmentResolver());
|
|
11171
|
+
this.chatBackend.registerAttachmentResolver(new UrlAttachmentResolver(this.chatBackend));
|
|
10925
11172
|
}
|
|
10926
11173
|
static configure(options) {
|
|
10927
11174
|
return {
|
|
@@ -10931,11 +11178,11 @@ class BantaSdkModule {
|
|
|
10931
11178
|
provide: BANTA_SDK_OPTIONS,
|
|
10932
11179
|
useValue: options || {}
|
|
10933
11180
|
},
|
|
10934
|
-
{ provide: ChatBackendBase, useClass: ChatBackend }
|
|
11181
|
+
{ provide: ChatBackendBase, useClass: options?.backendClass ?? ChatBackend }
|
|
10935
11182
|
]
|
|
10936
11183
|
};
|
|
10937
11184
|
}
|
|
10938
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: BantaSdkModule, deps: [
|
|
11185
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: BantaSdkModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
10939
11186
|
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.9", ngImport: i0, type: BantaSdkModule, declarations: [BantaComponent,
|
|
10940
11187
|
BantaLogoComponent,
|
|
10941
11188
|
LiveMessageComponent], imports: [CommonModule,
|
|
@@ -11017,7 +11264,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImpor
|
|
|
11017
11264
|
EmojiModule
|
|
11018
11265
|
]
|
|
11019
11266
|
}]
|
|
11020
|
-
}], ctorParameters: () => [
|
|
11267
|
+
}], ctorParameters: () => [] });
|
|
11021
11268
|
|
|
11022
11269
|
/*
|
|
11023
11270
|
* Public API Surface of sdk
|