@banta/sdk 5.5.3 → 5.6.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.
- 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 +271 -34
- package/esm2022/lib/sdk-options.mjs +1 -1
- package/fesm2022/banta-sdk.mjs +292 -46
- package/fesm2022/banta-sdk.mjs.map +1 -1
- package/lib/banta/banta.component.d.ts +1 -1
- package/lib/banta-sdk.module.d.ts +2 -1
- 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/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,191 @@ 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
|
+
}
|
|
8014
|
+
const lastMessage = this.olderMessages[this.olderMessages.length - 1] ?? this.messages[this.messages.length - 1];
|
|
8015
|
+
if (!lastMessage)
|
|
7865
8016
|
this.hasMore = false;
|
|
8017
|
+
if (nextPageSize > 0 && !this.newestLast && lastMessage) {
|
|
8018
|
+
// Load more from backend
|
|
8019
|
+
this.isLoadingMore = true;
|
|
8020
|
+
let messages = await this.source.loadAfter(lastMessage, nextPageSize);
|
|
8021
|
+
messages.forEach(m => m.transientState ??= {});
|
|
8022
|
+
this.messages = [...this.messages, ...messages];
|
|
8023
|
+
// If we didn't receive any messages at all, there's no more to fetch.
|
|
8024
|
+
if (messages.length === 0)
|
|
8025
|
+
this.hasMore = false;
|
|
8026
|
+
this.isLoadingMore = false;
|
|
8027
|
+
}
|
|
8028
|
+
// Extract the messages that do not fit in the maxVisibleMessages buffer.
|
|
8029
|
+
if (this.messages.length > this.maxVisibleMessages) {
|
|
8030
|
+
let overflow = this.messages.splice(0, this.messages.length - this.maxVisibleMessages);
|
|
8031
|
+
// Regardless of the order (newestLast), newMessages represents the direction that is being pushed, since it's definition
|
|
8032
|
+
// depends on that order. Move overflowing messages into newMessages.
|
|
8033
|
+
this.previousMessages.push(...overflow);
|
|
8034
|
+
if (this.previousMessages.length > this.maxMessages)
|
|
8035
|
+
this.previousMessages.splice(0, this.previousMessages.length - this.maxMessages);
|
|
8036
|
+
}
|
|
8037
|
+
this.debugMessages();
|
|
8038
|
+
}
|
|
8039
|
+
/**
|
|
8040
|
+
* Show more content
|
|
8041
|
+
* - When in replies mode (newestLast), the content is added at the top
|
|
8042
|
+
* - When in normal mode, the content is added at the bottom
|
|
8043
|
+
* - The current sort order does *not* factor in here, which is why it is showMore() not showEarlier().
|
|
8044
|
+
*
|
|
8045
|
+
* @returns
|
|
8046
|
+
*/
|
|
8047
|
+
async showMore() {
|
|
8048
|
+
this.isViewingMore = true;
|
|
8049
|
+
let nextPageSize = this.pageSize;
|
|
8050
|
+
this.isLoadingMore = false;
|
|
8051
|
+
if (this.olderMessages.length > 0) {
|
|
8052
|
+
const storedMessages = this.olderMessages.splice(0, nextPageSize);
|
|
8053
|
+
this.messages = this.messages.concat(storedMessages);
|
|
8054
|
+
nextPageSize -= storedMessages.length;
|
|
8055
|
+
this.hasMore = this.olderMessages.length > 0;
|
|
8056
|
+
}
|
|
8057
|
+
if (nextPageSize > 0) {
|
|
8058
|
+
// Load more from backend
|
|
8059
|
+
this.isLoadingMore = true;
|
|
8060
|
+
let lastMessage;
|
|
8061
|
+
if (this.newestLast) {
|
|
8062
|
+
lastMessage = this.olderMessages[0] ?? this.messages[0];
|
|
8063
|
+
}
|
|
8064
|
+
else {
|
|
8065
|
+
lastMessage = this.olderMessages[this.olderMessages.length - 1] ?? this.messages[this.messages.length - 1];
|
|
8066
|
+
}
|
|
8067
|
+
if (!lastMessage) {
|
|
8068
|
+
this.isLoadingMore = false;
|
|
8069
|
+
this.hasMore = false;
|
|
8070
|
+
return;
|
|
8071
|
+
}
|
|
8072
|
+
let messages = await this.source.loadAfter(lastMessage, nextPageSize);
|
|
8073
|
+
if (this.newestLast)
|
|
8074
|
+
messages = messages.slice().reverse();
|
|
8075
|
+
messages.forEach(m => m.transientState ??= {});
|
|
8076
|
+
// In replies mode (newestLast), we want to put these new messages onto the *top* of the set of visible messages.
|
|
8077
|
+
// Otherwise we want to put them on the *bottom*.
|
|
8078
|
+
if (this.newestLast) {
|
|
8079
|
+
this.messages = messages.concat(this.messages);
|
|
8080
|
+
}
|
|
8081
|
+
else {
|
|
8082
|
+
this.messages = this.messages.concat(messages);
|
|
8083
|
+
}
|
|
8084
|
+
// If we didn't receive any messages at all, there's no more to fetch.
|
|
8085
|
+
if (messages.length === 0) {
|
|
8086
|
+
this.hasMore = false;
|
|
8087
|
+
}
|
|
8088
|
+
this.isLoadingMore = false;
|
|
7866
8089
|
}
|
|
8090
|
+
// Extract the messages that do not fit in the maxVisibleMessages buffer.
|
|
8091
|
+
let overflow;
|
|
8092
|
+
if (this.newestLast)
|
|
8093
|
+
overflow = this.messages.splice(this.maxVisibleMessages, this.messages.length);
|
|
8094
|
+
else
|
|
8095
|
+
overflow = this.messages.splice(0, this.maxVisibleMessages);
|
|
8096
|
+
// Regardless of the order (newestLast), newMessages represents the direction that is being pushed, since it's definition
|
|
8097
|
+
// depends on that order. Move overflowing messages into newMessages.
|
|
8098
|
+
this.newMessages = overflow.concat(this.newMessages);
|
|
8099
|
+
this.newMessages.splice(this.maxMessages - this.maxVisibleMessages, this.newMessages.length);
|
|
7867
8100
|
}
|
|
7868
8101
|
addMessage(message) {
|
|
7869
8102
|
if (!message.transientState)
|
|
@@ -7872,9 +8105,13 @@ class CommentViewComponent {
|
|
|
7872
8105
|
let bucket = this.olderMessages;
|
|
7873
8106
|
let newestLast = this.newestLast;
|
|
7874
8107
|
if (this.shouldHoldNewMessages) {
|
|
8108
|
+
this.heldMessages.push(message);
|
|
7875
8109
|
destination = this.newMessages;
|
|
7876
8110
|
bucket = null;
|
|
7877
8111
|
}
|
|
8112
|
+
// If we aren't on the newest sort order, new messages shouldn't be added at all
|
|
8113
|
+
if (this.sourceSortOrder !== CommentsOrder.NEWEST)
|
|
8114
|
+
return;
|
|
7878
8115
|
if (newestLast) {
|
|
7879
8116
|
destination.push(message);
|
|
7880
8117
|
let overflow = destination.splice(this.maxVisibleMessages, destination.length);
|
|
@@ -7980,11 +8217,11 @@ class CommentViewComponent {
|
|
|
7980
8217
|
return false;
|
|
7981
8218
|
}
|
|
7982
8219
|
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: "
|
|
8220
|
+
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
8221
|
}
|
|
7985
8222
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: CommentViewComponent, decorators: [{
|
|
7986
8223
|
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
|
|
8224
|
+
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
8225
|
}], ctorParameters: () => [{ type: ChatBackendBase }, { type: i0.ElementRef }], propDecorators: { source: [{
|
|
7989
8226
|
type: Input
|
|
7990
8227
|
}], maxMessages: [{
|
|
@@ -8292,7 +8529,7 @@ class CommentFieldComponent {
|
|
|
8292
8529
|
return false;
|
|
8293
8530
|
if (this.signInState === 'signing-in')
|
|
8294
8531
|
return false;
|
|
8295
|
-
if (!['connected', 'restored'].includes(this.source
|
|
8532
|
+
if (!['connected', 'restored'].includes(this.source?.state ?? 'connected'))
|
|
8296
8533
|
return false;
|
|
8297
8534
|
if (!this.canComment) {
|
|
8298
8535
|
// In this case, we want to enable the button because we want to be able to
|
|
@@ -8873,8 +9110,13 @@ class BantaCommentsComponent {
|
|
|
8873
9110
|
await this.threadViewQuery.changes.pipe(take(1)).toPromise();
|
|
8874
9111
|
return this.threadView;
|
|
8875
9112
|
}
|
|
9113
|
+
get sourceState() {
|
|
9114
|
+
if (!this.source)
|
|
9115
|
+
return 'no-source';
|
|
9116
|
+
return this.source.state ?? 'connected';
|
|
9117
|
+
}
|
|
8876
9118
|
updateLoading() {
|
|
8877
|
-
if (this.
|
|
9119
|
+
if (this.sourceState && !['connecting', 'lost'].includes(this.sourceState)) {
|
|
8878
9120
|
clearInterval(this._loadingTimer);
|
|
8879
9121
|
this.loadingMessage = `Here we go!`;
|
|
8880
9122
|
setTimeout(() => {
|
|
@@ -8883,7 +9125,7 @@ class BantaCommentsComponent {
|
|
|
8883
9125
|
}, 750);
|
|
8884
9126
|
return true;
|
|
8885
9127
|
}
|
|
8886
|
-
console.log(`[Banta/Loader] State=${this.
|
|
9128
|
+
console.log(`[Banta/Loader] State=${this.sourceState}`);
|
|
8887
9129
|
let messageSwitchTime = 5 * 1000;
|
|
8888
9130
|
if (this.messageChangedAt + messageSwitchTime < Date.now()) {
|
|
8889
9131
|
if (this.loadingMessages[this._loadingMessageIndex]) {
|
|
@@ -8911,7 +9153,10 @@ class BantaCommentsComponent {
|
|
|
8911
9153
|
this.sharedCommentID = null;
|
|
8912
9154
|
}
|
|
8913
9155
|
this._source.messages.forEach(m => this.addParticipant(m));
|
|
8914
|
-
|
|
9156
|
+
if (this._source.connectionStateChanged)
|
|
9157
|
+
this._sourceSubscription.add(this._source.connectionStateChanged.subscribe(state => this.connectionState = state));
|
|
9158
|
+
else
|
|
9159
|
+
this.connectionState = 'connected';
|
|
8915
9160
|
this._sourceSubscription.add(this._source.messageReceived.subscribe(m => this.addParticipant(m)));
|
|
8916
9161
|
this._sourceSubscription.add(this._source.messageSent.subscribe(m => this.addParticipant(m)));
|
|
8917
9162
|
this._sourceSubscription.add(this._source.messageObserved.subscribe(m => this.addParticipant(m)));
|
|
@@ -10916,12 +11161,13 @@ class TweetAttachmentResolver {
|
|
|
10916
11161
|
}
|
|
10917
11162
|
|
|
10918
11163
|
class BantaSdkModule {
|
|
10919
|
-
constructor(
|
|
10920
|
-
chatBackend
|
|
10921
|
-
chatBackend.
|
|
10922
|
-
chatBackend.registerAttachmentResolver(new
|
|
10923
|
-
chatBackend.registerAttachmentResolver(new
|
|
10924
|
-
chatBackend.registerAttachmentResolver(new
|
|
11164
|
+
constructor() {
|
|
11165
|
+
this.chatBackend = inject(ChatBackendBase);
|
|
11166
|
+
this.chatBackend.registerAttachmentScraper(new UrlAttachmentScraper());
|
|
11167
|
+
this.chatBackend.registerAttachmentResolver(new GiphyAttachmentResolver());
|
|
11168
|
+
this.chatBackend.registerAttachmentResolver(new YouTubeAttachmentResolver());
|
|
11169
|
+
this.chatBackend.registerAttachmentResolver(new TweetAttachmentResolver());
|
|
11170
|
+
this.chatBackend.registerAttachmentResolver(new UrlAttachmentResolver(this.chatBackend));
|
|
10925
11171
|
}
|
|
10926
11172
|
static configure(options) {
|
|
10927
11173
|
return {
|
|
@@ -10931,11 +11177,11 @@ class BantaSdkModule {
|
|
|
10931
11177
|
provide: BANTA_SDK_OPTIONS,
|
|
10932
11178
|
useValue: options || {}
|
|
10933
11179
|
},
|
|
10934
|
-
{ provide: ChatBackendBase, useClass: ChatBackend }
|
|
11180
|
+
{ provide: ChatBackendBase, useClass: options?.backendClass ?? ChatBackend }
|
|
10935
11181
|
]
|
|
10936
11182
|
};
|
|
10937
11183
|
}
|
|
10938
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: BantaSdkModule, deps: [
|
|
11184
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: BantaSdkModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
10939
11185
|
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.3.9", ngImport: i0, type: BantaSdkModule, declarations: [BantaComponent,
|
|
10940
11186
|
BantaLogoComponent,
|
|
10941
11187
|
LiveMessageComponent], imports: [CommonModule,
|
|
@@ -11017,7 +11263,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImpor
|
|
|
11017
11263
|
EmojiModule
|
|
11018
11264
|
]
|
|
11019
11265
|
}]
|
|
11020
|
-
}], ctorParameters: () => [
|
|
11266
|
+
}], ctorParameters: () => [] });
|
|
11021
11267
|
|
|
11022
11268
|
/*
|
|
11023
11269
|
* Public API Surface of sdk
|