@bitsocial/bitsocial-react-hooks 0.1.5 → 0.1.7
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/CHANGELOG.md +21 -0
- package/README.md +8 -7
- package/dist/hooks/comments.d.ts +1 -0
- package/dist/hooks/comments.d.ts.map +1 -1
- package/dist/hooks/comments.js +58 -7
- package/dist/hooks/comments.js.map +1 -1
- package/dist/lib/test-utils.d.ts +12 -3
- package/dist/lib/test-utils.d.ts.map +1 -1
- package/dist/lib/test-utils.js +5 -5
- package/dist/lib/test-utils.js.map +1 -1
- package/dist/stores/comments/comments-store.d.ts.map +1 -1
- package/dist/stores/comments/comments-store.js +21 -12
- package/dist/stores/comments/comments-store.js.map +1 -1
- package/dist/stores/replies/replies-store.d.ts.map +1 -1
- package/dist/stores/replies/replies-store.js +13 -2
- package/dist/stores/replies/replies-store.js.map +1 -1
- package/dist/stores/replies/utils.d.ts +5 -0
- package/dist/stores/replies/utils.d.ts.map +1 -1
- package/dist/stores/replies/utils.js +11 -4
- package/dist/stores/replies/utils.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +7 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
## [0.1.7](https://github.com/bitsocialnet/bitsocial-react-hooks/compare/v0.1.6...v0.1.7) (2026-05-06)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **comments:** pass community identity to pkc comments ([8db8b8c](https://github.com/bitsocialnet/bitsocial-react-hooks/commit/8db8b8c033e3d4c39e5a17e069405560014826fa))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
## [0.1.6](https://github.com/bitsocialnet/bitsocial-react-hooks/compare/v0.1.5...v0.1.6) (2026-05-05)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **deps:** resolve axios dependabot alerts ([f05eac0](https://github.com/bitsocialnet/bitsocial-react-hooks/commit/f05eac02887067fe1413d39aa7fbe21b593c01aa))
|
|
16
|
+
* **deps:** resolve dependabot alerts ([805ac34](https://github.com/bitsocialnet/bitsocial-react-hooks/commit/805ac34b43cbf139c2ff8d479450a45338070ec9))
|
|
17
|
+
* **replies:** keep newly published account replies visible ([96ab074](https://github.com/bitsocialnet/bitsocial-react-hooks/commit/96ab074a85222b838cc71c8c091aae2ece6039da))
|
|
18
|
+
* **tests:** stop account hook suite OOM ([1e217d6](https://github.com/bitsocialnet/bitsocial-react-hooks/commit/1e217d6a11008cdd25b83ed0ef2d3e7d5c95e537))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
1
22
|
## [0.1.5](https://github.com/bitsocialnet/bitsocial-react-hooks/compare/v0.1.4...v0.1.5) (2026-05-02)
|
|
2
23
|
|
|
3
24
|
|
package/README.md
CHANGED
|
@@ -119,7 +119,7 @@ useNotifications(): {notifications: Notification[], markAsRead: Function}
|
|
|
119
119
|
#### Comments Hooks
|
|
120
120
|
|
|
121
121
|
```
|
|
122
|
-
useComment({commentCid: string, onlyIfCached?: boolean, autoUpdate?: boolean}): Comment & {refresh: Function}
|
|
122
|
+
useComment({commentCid: string, community?: CommunityIdentifier, onlyIfCached?: boolean, autoUpdate?: boolean}): Comment & {refresh: Function}
|
|
123
123
|
useReplies({comment: Comment, onlyIfCached?: boolean, sortType?: string, flat?: boolean, repliesPerPage?: number, filter?: CommentsFilter, accountComments?: {newerThan: number, append?: boolean}}): {replies: Comment[], hasMore: boolean, loadMore: function, reset: function, updatedReplies: Comment[], bufferedReplies: Comment[]}
|
|
124
124
|
useComments({commentCids: string[], onlyIfCached?: boolean, autoUpdate?: boolean}): {comments: Comment[], refresh: Function}
|
|
125
125
|
useEditedComment({comment: Comment}): {editedComment: Comment | undefined}
|
|
@@ -256,7 +256,7 @@ await publishComment();
|
|
|
256
256
|
#### Get a post
|
|
257
257
|
|
|
258
258
|
```jsx
|
|
259
|
-
const post = useComment({ commentCid });
|
|
259
|
+
const post = useComment({ commentCid, community: { name: communityAddress, publicKey: communityPublicKey } });
|
|
260
260
|
|
|
261
261
|
// manual refresh is always available
|
|
262
262
|
await post.refresh();
|
|
@@ -290,7 +290,7 @@ if (valid === false) {
|
|
|
290
290
|
#### Get a comment
|
|
291
291
|
|
|
292
292
|
```jsx
|
|
293
|
-
const comment = useComment({ commentCid });
|
|
293
|
+
const comment = useComment({ commentCid, community: { name: communityAddress, publicKey: communityPublicKey } });
|
|
294
294
|
const { comments, refresh } = useComments({ commentCids: [commentCid1, commentCid2, commentCid3] });
|
|
295
295
|
await refresh();
|
|
296
296
|
|
|
@@ -1019,8 +1019,8 @@ const { replies } = useReplies({
|
|
|
1019
1019
|
|
|
1020
1020
|
// pending local account comments are reconciled with their approved network version
|
|
1021
1021
|
// so the same post or reply is not shown twice after moderation approval
|
|
1022
|
-
// published account replies are
|
|
1023
|
-
//
|
|
1022
|
+
// published account replies are kept in useReplies until the canonical replies
|
|
1023
|
+
// feed refreshes past the reply timestamp; after that exhausted feed, account-only
|
|
1024
1024
|
// published replies are hidden unless the canonical feed includes their cid
|
|
1025
1025
|
```
|
|
1026
1026
|
|
|
@@ -1302,8 +1302,9 @@ const useRepliesOptions = {
|
|
|
1302
1302
|
accountComments: { newerThan: Infinity, append: false },
|
|
1303
1303
|
};
|
|
1304
1304
|
|
|
1305
|
-
// accountComments keeps pending local replies visible, but
|
|
1306
|
-
// replies must resolve through the canonical replies feed
|
|
1305
|
+
// accountComments keeps pending and just-published local replies visible, but
|
|
1306
|
+
// published account replies must resolve through the canonical replies feed
|
|
1307
|
+
// after that feed refreshes past them and is exhausted
|
|
1307
1308
|
|
|
1308
1309
|
const Reply = ({ reply, updatedReply }) => {
|
|
1309
1310
|
const { replies, updatedReplies, bufferedReplies, hasMore, loadMore } = useReplies({
|
package/dist/hooks/comments.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export declare function getCommentFreshness(comment: Comment | undefined): numbe
|
|
|
3
3
|
export declare function preferFresher(current: Comment | undefined, candidate: Comment | undefined): Comment | undefined;
|
|
4
4
|
/**
|
|
5
5
|
* @param commentCid - The IPFS CID of the comment to get
|
|
6
|
+
* @param community - The community identifier, e.g. {name: 'memes.eth', publicKey: '12D3KooW...'}.
|
|
6
7
|
* @param acountName - The nickname of the account, e.g. 'Account 1'. If no accountName is provided, use
|
|
7
8
|
* the active account.
|
|
8
9
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comments.d.ts","sourceRoot":"","sources":["../../src/hooks/comments.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,OAAO,EACP,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,yBAAyB,EACzB,wBAAwB,EACzB,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"comments.d.ts","sourceRoot":"","sources":["../../src/hooks/comments.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,OAAO,EACP,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,yBAAyB,EACzB,wBAAwB,EACzB,MAAM,UAAU,CAAC;AAalB,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAGxE;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,OAAO,GAAG,SAAS,EAC5B,SAAS,EAAE,OAAO,GAAG,SAAS,GAC7B,OAAO,GAAG,SAAS,CAIrB;AA0ED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,gBAAgB,CAuMxE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,CA0K3E;AAED,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,yBAAyB,GAAG,wBAAwB,CAmDhG"}
|
package/dist/hooks/comments.js
CHANGED
|
@@ -20,6 +20,7 @@ import { addCommentModeration, addCommentModerationToComments, } from "../lib/ut
|
|
|
20
20
|
import useCommunitiesPagesStore from "../stores/communities-pages/index.js";
|
|
21
21
|
import useRepliesPagesStore from "../stores/replies-pages/index.js";
|
|
22
22
|
import shallow from "zustand/shallow";
|
|
23
|
+
import { assertCommunityRef } from "../lib/community-ref.js";
|
|
23
24
|
export function getCommentFreshness(comment) {
|
|
24
25
|
var _a, _b;
|
|
25
26
|
if (!comment)
|
|
@@ -60,14 +61,47 @@ const getCommentsState = (comments) => comments.every((comment) => getCommentSta
|
|
|
60
61
|
: "fetching-ipfs";
|
|
61
62
|
let commentAutoUpdateSubscriptionCount = 0;
|
|
62
63
|
let commentsAutoUpdateSubscriptionCount = 0;
|
|
64
|
+
const getCommentCreateCommentData = (commentCid, community, ...comments) => {
|
|
65
|
+
if (!commentCid) {
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
const createCommentData = { cid: commentCid };
|
|
69
|
+
let hasCommunityData = false;
|
|
70
|
+
for (const comment of comments) {
|
|
71
|
+
if (!comment) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (!createCommentData.communityPublicKey && comment.communityPublicKey) {
|
|
75
|
+
createCommentData.communityPublicKey = comment.communityPublicKey;
|
|
76
|
+
hasCommunityData = true;
|
|
77
|
+
}
|
|
78
|
+
if (!createCommentData.communityName && comment.communityName) {
|
|
79
|
+
createCommentData.communityName = comment.communityName;
|
|
80
|
+
hasCommunityData = true;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (community === null || community === void 0 ? void 0 : community.publicKey) {
|
|
84
|
+
createCommentData.communityPublicKey = community.publicKey;
|
|
85
|
+
hasCommunityData = true;
|
|
86
|
+
}
|
|
87
|
+
if (community === null || community === void 0 ? void 0 : community.name) {
|
|
88
|
+
createCommentData.communityName = community.name;
|
|
89
|
+
hasCommunityData = true;
|
|
90
|
+
}
|
|
91
|
+
return hasCommunityData ? createCommentData : undefined;
|
|
92
|
+
};
|
|
63
93
|
/**
|
|
64
94
|
* @param commentCid - The IPFS CID of the comment to get
|
|
95
|
+
* @param community - The community identifier, e.g. {name: 'memes.eth', publicKey: '12D3KooW...'}.
|
|
65
96
|
* @param acountName - The nickname of the account, e.g. 'Account 1'. If no accountName is provided, use
|
|
66
97
|
* the active account.
|
|
67
98
|
*/
|
|
68
99
|
export function useComment(options) {
|
|
69
100
|
assert(!options || typeof options === "object", `useComment options argument '${options}' not an object`);
|
|
70
|
-
const { commentCid, accountName, onlyIfCached, autoUpdate = true } = options !== null && options !== void 0 ? options : {};
|
|
101
|
+
const { commentCid, community, accountName, onlyIfCached, autoUpdate = true } = options !== null && options !== void 0 ? options : {};
|
|
102
|
+
if (community !== undefined) {
|
|
103
|
+
assertCommunityRef(community, "useComment community");
|
|
104
|
+
}
|
|
71
105
|
const account = useAccount({ accountName });
|
|
72
106
|
const commentFromStore = useCommentsStore((state) => state.comments[commentCid || ""]);
|
|
73
107
|
const addCommentToStore = useCommentsStore((state) => state.addCommentToStore);
|
|
@@ -83,6 +117,15 @@ export function useComment(options) {
|
|
|
83
117
|
var _a;
|
|
84
118
|
return (_a = state.accountsComments[(accountCommentInfo === null || accountCommentInfo === void 0 ? void 0 : accountCommentInfo.accountId) || ""]) === null || _a === void 0 ? void 0 : _a[Number(accountCommentInfo === null || accountCommentInfo === void 0 ? void 0 : accountCommentInfo.accountCommentIndex)];
|
|
85
119
|
});
|
|
120
|
+
const createCommentData = useMemo(() => getCommentCreateCommentData(commentCid, community, communitiesPagesComment, repliesPagesComment), [
|
|
121
|
+
commentCid,
|
|
122
|
+
community === null || community === void 0 ? void 0 : community.name,
|
|
123
|
+
community === null || community === void 0 ? void 0 : community.publicKey,
|
|
124
|
+
communitiesPagesComment === null || communitiesPagesComment === void 0 ? void 0 : communitiesPagesComment.communityName,
|
|
125
|
+
communitiesPagesComment === null || communitiesPagesComment === void 0 ? void 0 : communitiesPagesComment.communityPublicKey,
|
|
126
|
+
repliesPagesComment === null || repliesPagesComment === void 0 ? void 0 : repliesPagesComment.communityName,
|
|
127
|
+
repliesPagesComment === null || repliesPagesComment === void 0 ? void 0 : repliesPagesComment.communityPublicKey,
|
|
128
|
+
]);
|
|
86
129
|
const autoUpdateSubscriptionId = useRef(`useComment-${++commentAutoUpdateSubscriptionCount}`);
|
|
87
130
|
const currentCommentCidRef = useRef(commentCid);
|
|
88
131
|
currentCommentCidRef.current = commentCid;
|
|
@@ -95,18 +138,24 @@ export function useComment(options) {
|
|
|
95
138
|
validator.validateUseCommentArguments(commentCid, account);
|
|
96
139
|
if (!commentFromStore && !onlyIfCached) {
|
|
97
140
|
// if comment isn't already in store, add it
|
|
98
|
-
|
|
141
|
+
const addCommentPromise = createCommentData
|
|
142
|
+
? addCommentToStore(commentCid, account, createCommentData)
|
|
143
|
+
: addCommentToStore(commentCid, account);
|
|
144
|
+
addCommentPromise.catch((error) => log.error("useComment addCommentToStore error", { commentCid, error }));
|
|
99
145
|
}
|
|
100
|
-
}, [commentCid, account === null || account === void 0 ? void 0 : account.id, onlyIfCached]);
|
|
146
|
+
}, [commentCid, account === null || account === void 0 ? void 0 : account.id, onlyIfCached, createCommentData]);
|
|
101
147
|
useEffect(() => {
|
|
102
148
|
if (!commentCid || !account || onlyIfCached || !autoUpdate) {
|
|
103
149
|
return;
|
|
104
150
|
}
|
|
105
|
-
|
|
151
|
+
const startAutoUpdatePromise = createCommentData
|
|
152
|
+
? startCommentAutoUpdate(commentCid, autoUpdateSubscriptionId.current, account, createCommentData)
|
|
153
|
+
: startCommentAutoUpdate(commentCid, autoUpdateSubscriptionId.current, account);
|
|
154
|
+
startAutoUpdatePromise.catch((error) => log.error("useComment startCommentAutoUpdate error", { commentCid, error }));
|
|
106
155
|
return () => {
|
|
107
156
|
stopCommentAutoUpdate(commentCid, autoUpdateSubscriptionId.current).catch((error) => log.error("useComment stopCommentAutoUpdate error", { commentCid, error }));
|
|
108
157
|
};
|
|
109
|
-
}, [commentCid, account === null || account === void 0 ? void 0 : account.id, onlyIfCached, autoUpdate]);
|
|
158
|
+
}, [commentCid, account === null || account === void 0 ? void 0 : account.id, onlyIfCached, autoUpdate, createCommentData]);
|
|
110
159
|
let selectedComment = commentFromStore;
|
|
111
160
|
if (commentCid && communitiesPagesComment) {
|
|
112
161
|
selectedComment = preferFresher(selectedComment, communitiesPagesComment);
|
|
@@ -177,12 +226,14 @@ export function useComment(options) {
|
|
|
177
226
|
throw Error("useComment cannot refresh comment not initialized yet");
|
|
178
227
|
}
|
|
179
228
|
const refreshCommentCid = commentCid;
|
|
180
|
-
const refreshedComment =
|
|
229
|
+
const refreshedComment = createCommentData
|
|
230
|
+
? yield refreshCommentInStore(refreshCommentCid, account, createCommentData)
|
|
231
|
+
: yield refreshCommentInStore(refreshCommentCid, account);
|
|
181
232
|
if (!autoUpdate && refreshedComment && currentCommentCidRef.current === refreshCommentCid) {
|
|
182
233
|
setFrozenComment(refreshedComment);
|
|
183
234
|
setFreezeSettledCid(refreshCommentCid);
|
|
184
235
|
}
|
|
185
|
-
}), [account, autoUpdate, commentCid, refreshCommentInStore]);
|
|
236
|
+
}), [account, autoUpdate, commentCid, createCommentData, refreshCommentInStore]);
|
|
186
237
|
return useMemo(() => (Object.assign(Object.assign({}, comment), { replyCount,
|
|
187
238
|
state,
|
|
188
239
|
refresh, error: errors === null || errors === void 0 ? void 0 : errors[errors.length - 1], errors: errors || [] })), [comment, commentCid, errors, refresh, state, replyCount]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comments.js","sourceRoot":"","sources":["../../src/hooks/comments.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useAccount } from \"./accounts\";\nimport validator from \"../lib/validator\";\nimport Logger from \"@pkcprotocol/pkc-logger\";\nconst log = Logger(\"bitsocial-react-hooks:comments:hooks\");\nimport assert from \"assert\";\nimport {\n Comment,\n UseCommentsOptions,\n UseCommentsResult,\n UseCommentOptions,\n UseCommentResult,\n UseValidateCommentOptions,\n UseValidateCommentResult,\n} from \"../types\";\nimport useCommentsStore from \"../stores/comments\";\nimport useAccountsStore from \"../stores/accounts\";\nimport { commentIsValid } from \"../lib/utils\";\nimport {\n addCommentModeration,\n addCommentModerationToComments,\n} from \"../lib/utils/comment-moderation\";\nimport useCommunitiesPagesStore from \"../stores/communities-pages\";\nimport useRepliesPagesStore from \"../stores/replies-pages\";\nimport shallow from \"zustand/shallow\";\n\nexport function getCommentFreshness(comment: Comment | undefined): number {\n if (!comment) return 0;\n return Math.max(comment.updatedAt ?? 0, comment.timestamp ?? 0, 0);\n}\n\nexport function preferFresher(\n current: Comment | undefined,\n candidate: Comment | undefined,\n): Comment | undefined {\n if (!candidate) return current;\n if (!current) return candidate;\n return getCommentFreshness(candidate) > getCommentFreshness(current) ? candidate : current;\n}\n\nconst getCommentStateAndReplyCount = (comment: Comment | undefined) => {\n let state = comment?.updatingState || \"initializing\";\n // force 'fetching-ipns' even if could be something else, so the frontend can use\n // the correct loading skeleton\n if (comment?.timestamp) {\n state = \"fetching-update-ipns\";\n }\n // force succeeded even if the comment is fecthing a new update\n if (comment?.updatedAt) {\n state = \"succeeded\";\n }\n\n // force succeeded if the comment is newer than 5 minutes, no need to display loading skeleton if comment was just created\n let replyCount = comment?.replyCount;\n if (\n comment?.replyCount === undefined &&\n comment?.timestamp &&\n comment?.timestamp > Date.now() / 1000 - 5 * 60\n ) {\n state = \"succeeded\";\n // set replyCount because some frontend are likely to check if replyCount === undefined to show a loading skeleton\n replyCount = 0;\n }\n\n return { state, replyCount };\n};\n\nconst getCommentsState = (comments: (Comment | undefined)[]) =>\n comments.every((comment) => getCommentStateAndReplyCount(comment).state === \"succeeded\")\n ? \"succeeded\"\n : \"fetching-ipfs\";\n\nlet commentAutoUpdateSubscriptionCount = 0;\nlet commentsAutoUpdateSubscriptionCount = 0;\n\n/**\n * @param commentCid - The IPFS CID of the comment to get\n * @param acountName - The nickname of the account, e.g. 'Account 1'. If no accountName is provided, use\n * the active account.\n */\nexport function useComment(options?: UseCommentOptions): UseCommentResult {\n assert(\n !options || typeof options === \"object\",\n `useComment options argument '${options}' not an object`,\n );\n const { commentCid, accountName, onlyIfCached, autoUpdate = true } = options ?? {};\n const account = useAccount({ accountName });\n const commentFromStore = useCommentsStore((state: any) => state.comments[commentCid || \"\"]);\n const addCommentToStore = useCommentsStore((state: any) => state.addCommentToStore);\n const startCommentAutoUpdate = useCommentsStore((state: any) => state.startCommentAutoUpdate);\n const stopCommentAutoUpdate = useCommentsStore((state: any) => state.stopCommentAutoUpdate);\n const refreshCommentInStore = useCommentsStore((state: any) => state.refreshComment);\n const communitiesPagesComment = useCommunitiesPagesStore(\n (state: any) => state.comments[commentCid || \"\"],\n );\n const repliesPagesComment = useRepliesPagesStore(\n (state: any) => state.comments[commentCid || \"\"],\n );\n const errors = useCommentsStore((state: any) => state.errors[commentCid || \"\"]);\n\n // get account comment of the cid if any\n const accountCommentInfo = useAccountsStore(\n (state: any) => state.commentCidsToAccountsComments[commentCid || \"\"],\n );\n const accountComment = useAccountsStore(\n (state: any) =>\n state.accountsComments[accountCommentInfo?.accountId || \"\"]?.[\n Number(accountCommentInfo?.accountCommentIndex)\n ],\n );\n const autoUpdateSubscriptionId = useRef(`useComment-${++commentAutoUpdateSubscriptionCount}`);\n const currentCommentCidRef = useRef<string | undefined>(commentCid);\n currentCommentCidRef.current = commentCid;\n const [frozenComment, setFrozenComment] = useState<Comment | undefined>();\n const [freezeSettledCid, setFreezeSettledCid] = useState<string>();\n\n useEffect(() => {\n if (!commentCid || !account) {\n return;\n }\n validator.validateUseCommentArguments(commentCid, account);\n if (!commentFromStore && !onlyIfCached) {\n // if comment isn't already in store, add it\n addCommentToStore(commentCid, account).catch((error: unknown) =>\n log.error(\"useComment addCommentToStore error\", { commentCid, error }),\n );\n }\n }, [commentCid, account?.id, onlyIfCached]);\n\n useEffect(() => {\n if (!commentCid || !account || onlyIfCached || !autoUpdate) {\n return;\n }\n\n startCommentAutoUpdate(commentCid, autoUpdateSubscriptionId.current, account).catch(\n (error: unknown) =>\n log.error(\"useComment startCommentAutoUpdate error\", { commentCid, error }),\n );\n\n return () => {\n stopCommentAutoUpdate(commentCid, autoUpdateSubscriptionId.current).catch((error: unknown) =>\n log.error(\"useComment stopCommentAutoUpdate error\", { commentCid, error }),\n );\n };\n }, [commentCid, account?.id, onlyIfCached, autoUpdate]);\n\n let selectedComment = commentFromStore;\n\n if (commentCid && communitiesPagesComment) {\n selectedComment = preferFresher(selectedComment, communitiesPagesComment);\n }\n if (commentCid && repliesPagesComment) {\n selectedComment = preferFresher(selectedComment, repliesPagesComment);\n }\n\n // if comment is still not defined, but account comment is, use account comment\n // check `comment.timestamp` instead of `comment` in case comment exists but in a loading state\n const commentFromStoreNotLoaded = !selectedComment?.timestamp;\n if (commentCid && commentFromStoreNotLoaded && accountComment) {\n selectedComment = accountComment;\n }\n\n const selectedCommentState = getCommentStateAndReplyCount(selectedComment).state;\n const freezeSettledForCurrentCid = freezeSettledCid === commentCid;\n\n useEffect(() => {\n if (autoUpdate) {\n setFrozenComment(undefined);\n setFreezeSettledCid(undefined);\n return;\n }\n\n setFrozenComment(undefined);\n setFreezeSettledCid(undefined);\n }, [commentCid, autoUpdate]);\n\n useEffect(() => {\n if (autoUpdate) {\n return;\n }\n if (!commentCid) {\n setFrozenComment(undefined);\n setFreezeSettledCid(undefined);\n return;\n }\n if (freezeSettledForCurrentCid || !selectedComment) {\n return;\n }\n\n setFrozenComment(selectedComment);\n if (selectedCommentState === \"succeeded\") {\n setFreezeSettledCid(commentCid);\n }\n }, [autoUpdate, commentCid, selectedComment, selectedCommentState, freezeSettledForCurrentCid]);\n\n const frozenCommentForCurrentCid = frozenComment?.cid === commentCid ? frozenComment : undefined;\n let comment = autoUpdate\n ? selectedComment\n : freezeSettledForCurrentCid\n ? frozenCommentForCurrentCid\n : frozenCommentForCurrentCid || selectedComment;\n comment = addCommentModeration(comment);\n\n const { state, replyCount } = getCommentStateAndReplyCount(comment);\n\n if (account && commentCid) {\n log(\"useComment\", {\n commentCid,\n comment,\n replyCount,\n state,\n commentFromStore,\n communitiesPagesComment,\n repliesPagesComment,\n accountComment,\n commentsStore: useCommentsStore.getState().comments,\n account,\n onlyIfCached,\n autoUpdate,\n });\n }\n\n const refresh = useCallback(async () => {\n if (!commentCid || !account) {\n throw Error(\"useComment cannot refresh comment not initialized yet\");\n }\n\n const refreshCommentCid = commentCid;\n const refreshedComment = await refreshCommentInStore(refreshCommentCid, account);\n if (!autoUpdate && refreshedComment && currentCommentCidRef.current === refreshCommentCid) {\n setFrozenComment(refreshedComment);\n setFreezeSettledCid(refreshCommentCid);\n }\n }, [account, autoUpdate, commentCid, refreshCommentInStore]);\n\n return useMemo(\n () => ({\n ...comment,\n replyCount,\n state,\n refresh,\n error: errors?.[errors.length - 1],\n errors: errors || [],\n }),\n [comment, commentCid, errors, refresh, state, replyCount],\n );\n}\n\n/**\n * @param commentCids - The IPFS CIDs of the comments to get\n * @param acountName - The nickname of the account, e.g. 'Account 1'. If no accountName is provided, use\n * the active account.\n */\nexport function useComments(options?: UseCommentsOptions): UseCommentsResult {\n assert(\n !options || typeof options === \"object\",\n `useComments options argument '${options}' not an object`,\n );\n const { commentCids = [], accountName, onlyIfCached, autoUpdate = true } = options ?? {};\n const account = useAccount({ accountName });\n const commentsStoreComments: (Comment | undefined)[] = useCommentsStore(\n (state: any) => commentCids.map((commentCid) => state.comments[commentCid || \"\"]),\n shallow,\n );\n const communitiesPagesComments: (Comment | undefined)[] = useCommunitiesPagesStore(\n (state: any) => commentCids.map((commentCid) => state.comments[commentCid || \"\"]),\n shallow,\n );\n\n const addCommentToStore = useCommentsStore((state: any) => state.addCommentToStore);\n const startCommentAutoUpdate = useCommentsStore((state: any) => state.startCommentAutoUpdate);\n const stopCommentAutoUpdate = useCommentsStore((state: any) => state.stopCommentAutoUpdate);\n const refreshCommentInStore = useCommentsStore((state: any) => state.refreshComment);\n const autoUpdateSubscriptionId = useRef(`useComments-${++commentsAutoUpdateSubscriptionCount}`);\n const commentCidsKey = JSON.stringify(commentCids);\n const commentsKey = `${account?.id || \"\"}:${commentCidsKey}`;\n const currentCommentsKeyRef = useRef(commentsKey);\n currentCommentsKeyRef.current = commentsKey;\n const [frozenComments, setFrozenComments] = useState<(Comment | undefined)[]>([]);\n const [frozenCommentsKey, setFrozenCommentsKey] = useState<string>();\n const [freezeSettledKey, setFreezeSettledKey] = useState<string>();\n\n useEffect(() => {\n if (!commentCids || !account) {\n return;\n }\n validator.validateUseCommentsArguments(commentCids, account);\n if (onlyIfCached) {\n return;\n }\n const uniqueCommentCids = new Set(commentCids);\n for (const commentCid of uniqueCommentCids) {\n addCommentToStore(commentCid, account).catch((error: unknown) =>\n log.error(\"useComments addCommentToStore error\", { commentCid, error }),\n );\n }\n }, [commentCidsKey, account?.id, onlyIfCached]);\n\n useEffect(() => {\n if (!commentCids || !account || onlyIfCached || !autoUpdate) {\n return;\n }\n\n const uniqueCommentCids = [...new Set(commentCids)];\n for (const commentCid of uniqueCommentCids) {\n startCommentAutoUpdate(commentCid, autoUpdateSubscriptionId.current, account).catch(\n (error: unknown) =>\n log.error(\"useComments startCommentAutoUpdate error\", { commentCid, error }),\n );\n }\n\n return () => {\n for (const commentCid of uniqueCommentCids) {\n stopCommentAutoUpdate(commentCid, autoUpdateSubscriptionId.current).catch(\n (error: unknown) =>\n log.error(\"useComments stopCommentAutoUpdate error\", { commentCid, error }),\n );\n }\n };\n }, [commentCidsKey, account?.id, onlyIfCached, autoUpdate]);\n\n if (account && commentCids?.length) {\n log(\"useComments\", {\n commentCids,\n commentsStoreComments,\n commentsStore: useCommentsStore.getState().comments,\n account,\n });\n }\n\n // if comment from community pages exists and is fresher (or current missing), use it instead\n const liveComments = useMemo(() => {\n const result = [...commentsStoreComments];\n for (const i in result) {\n const candidate = communitiesPagesComments[i];\n if (candidate) result[i] = preferFresher(result[i], candidate);\n }\n return result;\n }, [commentsStoreComments, communitiesPagesComments]);\n\n const liveCommentsSettled = liveComments.every(\n (comment) => getCommentStateAndReplyCount(comment).state === \"succeeded\",\n );\n const freezeSettledForCurrentKey = freezeSettledKey === commentsKey;\n\n useEffect(() => {\n if (autoUpdate) {\n setFrozenComments([]);\n setFrozenCommentsKey(undefined);\n setFreezeSettledKey(undefined);\n return;\n }\n\n setFrozenComments([]);\n setFrozenCommentsKey(undefined);\n setFreezeSettledKey(undefined);\n }, [commentsKey, autoUpdate]);\n\n useEffect(() => {\n if (autoUpdate || freezeSettledForCurrentKey) {\n return;\n }\n\n setFrozenComments(liveComments);\n setFrozenCommentsKey(commentsKey);\n if (liveCommentsSettled) {\n setFreezeSettledKey(commentsKey);\n }\n }, [autoUpdate, commentsKey, freezeSettledForCurrentKey, liveComments, liveCommentsSettled]);\n\n const frozenCommentsForCurrentSelection =\n frozenCommentsKey === commentsKey ? frozenComments : undefined;\n const comments = autoUpdate ? liveComments : frozenCommentsForCurrentSelection || liveComments;\n const normalizedComments = useMemo(() => addCommentModerationToComments(comments), [comments]);\n\n // succeed if no comments are undefined\n const state = getCommentsState(normalizedComments);\n\n const refresh = useCallback(async () => {\n if (!account) {\n throw Error(\"useComments cannot refresh comments not initialized yet\");\n }\n const uniqueCommentCids = [...new Set(commentCids)];\n const refreshedComments = await Promise.all(\n uniqueCommentCids.map((commentCid) => refreshCommentInStore(commentCid, account)),\n );\n\n if (!autoUpdate && currentCommentsKeyRef.current === commentsKey) {\n const latestCommunitiesPagesComments = useCommunitiesPagesStore.getState().comments;\n const refreshedCommentsByCid = uniqueCommentCids.reduce(\n (\n refreshedCommentsMap: { [commentCid: string]: Comment | undefined },\n commentCid,\n index,\n ) => {\n refreshedCommentsMap[commentCid] = refreshedComments[index];\n return refreshedCommentsMap;\n },\n {},\n );\n setFrozenComments(\n commentCids.map((commentCid) =>\n preferFresher(\n refreshedCommentsByCid[commentCid || \"\"],\n latestCommunitiesPagesComments[commentCid || \"\"],\n ),\n ),\n );\n setFrozenCommentsKey(commentsKey);\n setFreezeSettledKey(commentsKey);\n }\n }, [account, autoUpdate, commentCids, commentsKey, refreshCommentInStore]);\n\n return useMemo(\n () => ({\n comments: normalizedComments,\n state,\n refresh,\n error: undefined,\n errors: [],\n }),\n [normalizedComments, commentsKey, refresh, state],\n );\n}\n\nexport function useValidateComment(options?: UseValidateCommentOptions): UseValidateCommentResult {\n assert(\n !options || typeof options === \"object\",\n `useValidateComment options argument '${options}' not an object`,\n );\n let { comment, validateReplies, accountName } = options ?? {};\n validateReplies = validateReplies ?? true;\n const [validated, setValidated] = useState<boolean | undefined>();\n const [errors] = useState([]);\n const account = useAccount({ accountName });\n\n useEffect(() => {\n if (!comment || !account?.pkc) {\n setValidated(undefined);\n return;\n }\n // don't automatically block community because what community it comes from\n // a malicious community could try to block other communities, etc\n const blockCommunity = false;\n commentIsValid(comment, { validateReplies, blockCommunity }, account.pkc).then((validated) =>\n setValidated(validated),\n );\n }, [comment, validateReplies, account?.pkc]);\n\n let state = \"initializing\";\n if (validated === true) {\n state = \"succeeded\";\n }\n if (validated === false) {\n state = \"failed\";\n }\n\n // start valid at true always because most of the time the value will be true and we dont want to cause a rerender\n let valid = true;\n if (validated == false) {\n valid = false;\n }\n // if comment isn't defined, it would be confusing for valid to be true\n if (!comment) {\n valid = false;\n }\n\n return useMemo(\n () => ({\n valid,\n state,\n error: errors[errors.length - 1],\n errors,\n }),\n [valid, state],\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"comments.js","sourceRoot":"","sources":["../../src/hooks/comments.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useAccount } from \"./accounts\";\nimport validator from \"../lib/validator\";\nimport Logger from \"@pkcprotocol/pkc-logger\";\nconst log = Logger(\"bitsocial-react-hooks:comments:hooks\");\nimport assert from \"assert\";\nimport {\n Comment,\n UseCommentsOptions,\n UseCommentsResult,\n UseCommentOptions,\n UseCommentResult,\n UseValidateCommentOptions,\n UseValidateCommentResult,\n} from \"../types\";\nimport useCommentsStore from \"../stores/comments\";\nimport useAccountsStore from \"../stores/accounts\";\nimport { commentIsValid } from \"../lib/utils\";\nimport {\n addCommentModeration,\n addCommentModerationToComments,\n} from \"../lib/utils/comment-moderation\";\nimport useCommunitiesPagesStore from \"../stores/communities-pages\";\nimport useRepliesPagesStore from \"../stores/replies-pages\";\nimport shallow from \"zustand/shallow\";\nimport { assertCommunityRef } from \"../lib/community-ref\";\n\nexport function getCommentFreshness(comment: Comment | undefined): number {\n if (!comment) return 0;\n return Math.max(comment.updatedAt ?? 0, comment.timestamp ?? 0, 0);\n}\n\nexport function preferFresher(\n current: Comment | undefined,\n candidate: Comment | undefined,\n): Comment | undefined {\n if (!candidate) return current;\n if (!current) return candidate;\n return getCommentFreshness(candidate) > getCommentFreshness(current) ? candidate : current;\n}\n\nconst getCommentStateAndReplyCount = (comment: Comment | undefined) => {\n let state = comment?.updatingState || \"initializing\";\n // force 'fetching-ipns' even if could be something else, so the frontend can use\n // the correct loading skeleton\n if (comment?.timestamp) {\n state = \"fetching-update-ipns\";\n }\n // force succeeded even if the comment is fecthing a new update\n if (comment?.updatedAt) {\n state = \"succeeded\";\n }\n\n // force succeeded if the comment is newer than 5 minutes, no need to display loading skeleton if comment was just created\n let replyCount = comment?.replyCount;\n if (\n comment?.replyCount === undefined &&\n comment?.timestamp &&\n comment?.timestamp > Date.now() / 1000 - 5 * 60\n ) {\n state = \"succeeded\";\n // set replyCount because some frontend are likely to check if replyCount === undefined to show a loading skeleton\n replyCount = 0;\n }\n\n return { state, replyCount };\n};\n\nconst getCommentsState = (comments: (Comment | undefined)[]) =>\n comments.every((comment) => getCommentStateAndReplyCount(comment).state === \"succeeded\")\n ? \"succeeded\"\n : \"fetching-ipfs\";\n\nlet commentAutoUpdateSubscriptionCount = 0;\nlet commentsAutoUpdateSubscriptionCount = 0;\n\nconst getCommentCreateCommentData = (\n commentCid: string | undefined,\n community: UseCommentOptions[\"community\"] | undefined,\n ...comments: (Comment | undefined)[]\n) => {\n if (!commentCid) {\n return undefined;\n }\n\n const createCommentData: Comment = { cid: commentCid };\n let hasCommunityData = false;\n for (const comment of comments) {\n if (!comment) {\n continue;\n }\n if (!createCommentData.communityPublicKey && comment.communityPublicKey) {\n createCommentData.communityPublicKey = comment.communityPublicKey;\n hasCommunityData = true;\n }\n if (!createCommentData.communityName && comment.communityName) {\n createCommentData.communityName = comment.communityName;\n hasCommunityData = true;\n }\n }\n\n if (community?.publicKey) {\n createCommentData.communityPublicKey = community.publicKey;\n hasCommunityData = true;\n }\n if (community?.name) {\n createCommentData.communityName = community.name;\n hasCommunityData = true;\n }\n\n return hasCommunityData ? createCommentData : undefined;\n};\n\n/**\n * @param commentCid - The IPFS CID of the comment to get\n * @param community - The community identifier, e.g. {name: 'memes.eth', publicKey: '12D3KooW...'}.\n * @param acountName - The nickname of the account, e.g. 'Account 1'. If no accountName is provided, use\n * the active account.\n */\nexport function useComment(options?: UseCommentOptions): UseCommentResult {\n assert(\n !options || typeof options === \"object\",\n `useComment options argument '${options}' not an object`,\n );\n const { commentCid, community, accountName, onlyIfCached, autoUpdate = true } = options ?? {};\n if (community !== undefined) {\n assertCommunityRef(community, \"useComment community\");\n }\n const account = useAccount({ accountName });\n const commentFromStore = useCommentsStore((state: any) => state.comments[commentCid || \"\"]);\n const addCommentToStore = useCommentsStore((state: any) => state.addCommentToStore);\n const startCommentAutoUpdate = useCommentsStore((state: any) => state.startCommentAutoUpdate);\n const stopCommentAutoUpdate = useCommentsStore((state: any) => state.stopCommentAutoUpdate);\n const refreshCommentInStore = useCommentsStore((state: any) => state.refreshComment);\n const communitiesPagesComment = useCommunitiesPagesStore(\n (state: any) => state.comments[commentCid || \"\"],\n );\n const repliesPagesComment = useRepliesPagesStore(\n (state: any) => state.comments[commentCid || \"\"],\n );\n const errors = useCommentsStore((state: any) => state.errors[commentCid || \"\"]);\n\n // get account comment of the cid if any\n const accountCommentInfo = useAccountsStore(\n (state: any) => state.commentCidsToAccountsComments[commentCid || \"\"],\n );\n const accountComment = useAccountsStore(\n (state: any) =>\n state.accountsComments[accountCommentInfo?.accountId || \"\"]?.[\n Number(accountCommentInfo?.accountCommentIndex)\n ],\n );\n const createCommentData = useMemo(\n () =>\n getCommentCreateCommentData(\n commentCid,\n community,\n communitiesPagesComment,\n repliesPagesComment,\n ),\n [\n commentCid,\n community?.name,\n community?.publicKey,\n communitiesPagesComment?.communityName,\n communitiesPagesComment?.communityPublicKey,\n repliesPagesComment?.communityName,\n repliesPagesComment?.communityPublicKey,\n ],\n );\n const autoUpdateSubscriptionId = useRef(`useComment-${++commentAutoUpdateSubscriptionCount}`);\n const currentCommentCidRef = useRef<string | undefined>(commentCid);\n currentCommentCidRef.current = commentCid;\n const [frozenComment, setFrozenComment] = useState<Comment | undefined>();\n const [freezeSettledCid, setFreezeSettledCid] = useState<string>();\n\n useEffect(() => {\n if (!commentCid || !account) {\n return;\n }\n validator.validateUseCommentArguments(commentCid, account);\n if (!commentFromStore && !onlyIfCached) {\n // if comment isn't already in store, add it\n const addCommentPromise = createCommentData\n ? addCommentToStore(commentCid, account, createCommentData)\n : addCommentToStore(commentCid, account);\n addCommentPromise.catch((error: unknown) =>\n log.error(\"useComment addCommentToStore error\", { commentCid, error }),\n );\n }\n }, [commentCid, account?.id, onlyIfCached, createCommentData]);\n\n useEffect(() => {\n if (!commentCid || !account || onlyIfCached || !autoUpdate) {\n return;\n }\n\n const startAutoUpdatePromise = createCommentData\n ? startCommentAutoUpdate(\n commentCid,\n autoUpdateSubscriptionId.current,\n account,\n createCommentData,\n )\n : startCommentAutoUpdate(commentCid, autoUpdateSubscriptionId.current, account);\n startAutoUpdatePromise.catch((error: unknown) =>\n log.error(\"useComment startCommentAutoUpdate error\", { commentCid, error }),\n );\n\n return () => {\n stopCommentAutoUpdate(commentCid, autoUpdateSubscriptionId.current).catch((error: unknown) =>\n log.error(\"useComment stopCommentAutoUpdate error\", { commentCid, error }),\n );\n };\n }, [commentCid, account?.id, onlyIfCached, autoUpdate, createCommentData]);\n\n let selectedComment = commentFromStore;\n\n if (commentCid && communitiesPagesComment) {\n selectedComment = preferFresher(selectedComment, communitiesPagesComment);\n }\n if (commentCid && repliesPagesComment) {\n selectedComment = preferFresher(selectedComment, repliesPagesComment);\n }\n\n // if comment is still not defined, but account comment is, use account comment\n // check `comment.timestamp` instead of `comment` in case comment exists but in a loading state\n const commentFromStoreNotLoaded = !selectedComment?.timestamp;\n if (commentCid && commentFromStoreNotLoaded && accountComment) {\n selectedComment = accountComment;\n }\n\n const selectedCommentState = getCommentStateAndReplyCount(selectedComment).state;\n const freezeSettledForCurrentCid = freezeSettledCid === commentCid;\n\n useEffect(() => {\n if (autoUpdate) {\n setFrozenComment(undefined);\n setFreezeSettledCid(undefined);\n return;\n }\n\n setFrozenComment(undefined);\n setFreezeSettledCid(undefined);\n }, [commentCid, autoUpdate]);\n\n useEffect(() => {\n if (autoUpdate) {\n return;\n }\n if (!commentCid) {\n setFrozenComment(undefined);\n setFreezeSettledCid(undefined);\n return;\n }\n if (freezeSettledForCurrentCid || !selectedComment) {\n return;\n }\n\n setFrozenComment(selectedComment);\n if (selectedCommentState === \"succeeded\") {\n setFreezeSettledCid(commentCid);\n }\n }, [autoUpdate, commentCid, selectedComment, selectedCommentState, freezeSettledForCurrentCid]);\n\n const frozenCommentForCurrentCid = frozenComment?.cid === commentCid ? frozenComment : undefined;\n let comment = autoUpdate\n ? selectedComment\n : freezeSettledForCurrentCid\n ? frozenCommentForCurrentCid\n : frozenCommentForCurrentCid || selectedComment;\n comment = addCommentModeration(comment);\n\n const { state, replyCount } = getCommentStateAndReplyCount(comment);\n\n if (account && commentCid) {\n log(\"useComment\", {\n commentCid,\n comment,\n replyCount,\n state,\n commentFromStore,\n communitiesPagesComment,\n repliesPagesComment,\n accountComment,\n commentsStore: useCommentsStore.getState().comments,\n account,\n onlyIfCached,\n autoUpdate,\n });\n }\n\n const refresh = useCallback(async () => {\n if (!commentCid || !account) {\n throw Error(\"useComment cannot refresh comment not initialized yet\");\n }\n\n const refreshCommentCid = commentCid;\n const refreshedComment = createCommentData\n ? await refreshCommentInStore(refreshCommentCid, account, createCommentData)\n : await refreshCommentInStore(refreshCommentCid, account);\n if (!autoUpdate && refreshedComment && currentCommentCidRef.current === refreshCommentCid) {\n setFrozenComment(refreshedComment);\n setFreezeSettledCid(refreshCommentCid);\n }\n }, [account, autoUpdate, commentCid, createCommentData, refreshCommentInStore]);\n\n return useMemo(\n () => ({\n ...comment,\n replyCount,\n state,\n refresh,\n error: errors?.[errors.length - 1],\n errors: errors || [],\n }),\n [comment, commentCid, errors, refresh, state, replyCount],\n );\n}\n\n/**\n * @param commentCids - The IPFS CIDs of the comments to get\n * @param acountName - The nickname of the account, e.g. 'Account 1'. If no accountName is provided, use\n * the active account.\n */\nexport function useComments(options?: UseCommentsOptions): UseCommentsResult {\n assert(\n !options || typeof options === \"object\",\n `useComments options argument '${options}' not an object`,\n );\n const { commentCids = [], accountName, onlyIfCached, autoUpdate = true } = options ?? {};\n const account = useAccount({ accountName });\n const commentsStoreComments: (Comment | undefined)[] = useCommentsStore(\n (state: any) => commentCids.map((commentCid) => state.comments[commentCid || \"\"]),\n shallow,\n );\n const communitiesPagesComments: (Comment | undefined)[] = useCommunitiesPagesStore(\n (state: any) => commentCids.map((commentCid) => state.comments[commentCid || \"\"]),\n shallow,\n );\n\n const addCommentToStore = useCommentsStore((state: any) => state.addCommentToStore);\n const startCommentAutoUpdate = useCommentsStore((state: any) => state.startCommentAutoUpdate);\n const stopCommentAutoUpdate = useCommentsStore((state: any) => state.stopCommentAutoUpdate);\n const refreshCommentInStore = useCommentsStore((state: any) => state.refreshComment);\n const autoUpdateSubscriptionId = useRef(`useComments-${++commentsAutoUpdateSubscriptionCount}`);\n const commentCidsKey = JSON.stringify(commentCids);\n const commentsKey = `${account?.id || \"\"}:${commentCidsKey}`;\n const currentCommentsKeyRef = useRef(commentsKey);\n currentCommentsKeyRef.current = commentsKey;\n const [frozenComments, setFrozenComments] = useState<(Comment | undefined)[]>([]);\n const [frozenCommentsKey, setFrozenCommentsKey] = useState<string>();\n const [freezeSettledKey, setFreezeSettledKey] = useState<string>();\n\n useEffect(() => {\n if (!commentCids || !account) {\n return;\n }\n validator.validateUseCommentsArguments(commentCids, account);\n if (onlyIfCached) {\n return;\n }\n const uniqueCommentCids = new Set(commentCids);\n for (const commentCid of uniqueCommentCids) {\n addCommentToStore(commentCid, account).catch((error: unknown) =>\n log.error(\"useComments addCommentToStore error\", { commentCid, error }),\n );\n }\n }, [commentCidsKey, account?.id, onlyIfCached]);\n\n useEffect(() => {\n if (!commentCids || !account || onlyIfCached || !autoUpdate) {\n return;\n }\n\n const uniqueCommentCids = [...new Set(commentCids)];\n for (const commentCid of uniqueCommentCids) {\n startCommentAutoUpdate(commentCid, autoUpdateSubscriptionId.current, account).catch(\n (error: unknown) =>\n log.error(\"useComments startCommentAutoUpdate error\", { commentCid, error }),\n );\n }\n\n return () => {\n for (const commentCid of uniqueCommentCids) {\n stopCommentAutoUpdate(commentCid, autoUpdateSubscriptionId.current).catch(\n (error: unknown) =>\n log.error(\"useComments stopCommentAutoUpdate error\", { commentCid, error }),\n );\n }\n };\n }, [commentCidsKey, account?.id, onlyIfCached, autoUpdate]);\n\n if (account && commentCids?.length) {\n log(\"useComments\", {\n commentCids,\n commentsStoreComments,\n commentsStore: useCommentsStore.getState().comments,\n account,\n });\n }\n\n // if comment from community pages exists and is fresher (or current missing), use it instead\n const liveComments = useMemo(() => {\n const result = [...commentsStoreComments];\n for (const i in result) {\n const candidate = communitiesPagesComments[i];\n if (candidate) result[i] = preferFresher(result[i], candidate);\n }\n return result;\n }, [commentsStoreComments, communitiesPagesComments]);\n\n const liveCommentsSettled = liveComments.every(\n (comment) => getCommentStateAndReplyCount(comment).state === \"succeeded\",\n );\n const freezeSettledForCurrentKey = freezeSettledKey === commentsKey;\n\n useEffect(() => {\n if (autoUpdate) {\n setFrozenComments([]);\n setFrozenCommentsKey(undefined);\n setFreezeSettledKey(undefined);\n return;\n }\n\n setFrozenComments([]);\n setFrozenCommentsKey(undefined);\n setFreezeSettledKey(undefined);\n }, [commentsKey, autoUpdate]);\n\n useEffect(() => {\n if (autoUpdate || freezeSettledForCurrentKey) {\n return;\n }\n\n setFrozenComments(liveComments);\n setFrozenCommentsKey(commentsKey);\n if (liveCommentsSettled) {\n setFreezeSettledKey(commentsKey);\n }\n }, [autoUpdate, commentsKey, freezeSettledForCurrentKey, liveComments, liveCommentsSettled]);\n\n const frozenCommentsForCurrentSelection =\n frozenCommentsKey === commentsKey ? frozenComments : undefined;\n const comments = autoUpdate ? liveComments : frozenCommentsForCurrentSelection || liveComments;\n const normalizedComments = useMemo(() => addCommentModerationToComments(comments), [comments]);\n\n // succeed if no comments are undefined\n const state = getCommentsState(normalizedComments);\n\n const refresh = useCallback(async () => {\n if (!account) {\n throw Error(\"useComments cannot refresh comments not initialized yet\");\n }\n const uniqueCommentCids = [...new Set(commentCids)];\n const refreshedComments = await Promise.all(\n uniqueCommentCids.map((commentCid) => refreshCommentInStore(commentCid, account)),\n );\n\n if (!autoUpdate && currentCommentsKeyRef.current === commentsKey) {\n const latestCommunitiesPagesComments = useCommunitiesPagesStore.getState().comments;\n const refreshedCommentsByCid = uniqueCommentCids.reduce(\n (\n refreshedCommentsMap: { [commentCid: string]: Comment | undefined },\n commentCid,\n index,\n ) => {\n refreshedCommentsMap[commentCid] = refreshedComments[index];\n return refreshedCommentsMap;\n },\n {},\n );\n setFrozenComments(\n commentCids.map((commentCid) =>\n preferFresher(\n refreshedCommentsByCid[commentCid || \"\"],\n latestCommunitiesPagesComments[commentCid || \"\"],\n ),\n ),\n );\n setFrozenCommentsKey(commentsKey);\n setFreezeSettledKey(commentsKey);\n }\n }, [account, autoUpdate, commentCids, commentsKey, refreshCommentInStore]);\n\n return useMemo(\n () => ({\n comments: normalizedComments,\n state,\n refresh,\n error: undefined,\n errors: [],\n }),\n [normalizedComments, commentsKey, refresh, state],\n );\n}\n\nexport function useValidateComment(options?: UseValidateCommentOptions): UseValidateCommentResult {\n assert(\n !options || typeof options === \"object\",\n `useValidateComment options argument '${options}' not an object`,\n );\n let { comment, validateReplies, accountName } = options ?? {};\n validateReplies = validateReplies ?? true;\n const [validated, setValidated] = useState<boolean | undefined>();\n const [errors] = useState([]);\n const account = useAccount({ accountName });\n\n useEffect(() => {\n if (!comment || !account?.pkc) {\n setValidated(undefined);\n return;\n }\n // don't automatically block community because what community it comes from\n // a malicious community could try to block other communities, etc\n const blockCommunity = false;\n commentIsValid(comment, { validateReplies, blockCommunity }, account.pkc).then((validated) =>\n setValidated(validated),\n );\n }, [comment, validateReplies, account?.pkc]);\n\n let state = \"initializing\";\n if (validated === true) {\n state = \"succeeded\";\n }\n if (validated === false) {\n state = \"failed\";\n }\n\n // start valid at true always because most of the time the value will be true and we dont want to cause a rerender\n let valid = true;\n if (validated == false) {\n valid = false;\n }\n // if comment isn't defined, it would be confusing for valid to be true\n if (!comment) {\n valid = false;\n }\n\n return useMemo(\n () => ({\n valid,\n state,\n error: errors[errors.length - 1],\n errors,\n }),\n [valid, state],\n );\n}\n"]}
|
package/dist/lib/test-utils.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
type RenderHookOptions<Props> = {
|
|
2
2
|
initialProps?: Props;
|
|
3
|
-
|
|
3
|
+
trackHistory?: boolean;
|
|
4
|
+
};
|
|
5
|
+
declare function renderHook<Result, Props>(callback: (props: Props) => Result, options?: RenderHookOptions<Props>): {
|
|
4
6
|
result: {
|
|
5
7
|
current: Result | null;
|
|
6
8
|
all: Result[];
|
|
@@ -22,7 +24,14 @@ declare const testUtils: {
|
|
|
22
24
|
resetStores: () => Promise<void>;
|
|
23
25
|
resetDatabasesAndStores: () => Promise<void>;
|
|
24
26
|
createWaitFor: (rendered: any, waitForOptions?: WaitForOptions) => (waitForFunction: Function) => Promise<void>;
|
|
25
|
-
renderHookWithHistory:
|
|
27
|
+
renderHookWithHistory: <Result, Props>(callback: (props: Props) => Result, options?: RenderHookOptions<Props>) => {
|
|
28
|
+
result: {
|
|
29
|
+
current: Result | null;
|
|
30
|
+
all: Result[];
|
|
31
|
+
};
|
|
32
|
+
rerender: (rerenderCallbackProps: Props) => void;
|
|
33
|
+
unmount: () => void;
|
|
34
|
+
};
|
|
26
35
|
silenceWaitForWarning: boolean;
|
|
27
36
|
};
|
|
28
37
|
export default testUtils;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../../src/lib/test-utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"test-utils.d.ts","sourceRoot":"","sources":["../../src/lib/test-utils.ts"],"names":[],"mappings":"AAiBA,KAAK,iBAAiB,CAAC,KAAK,IAAI;IAC9B,YAAY,CAAC,EAAE,KAAK,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAMF,iBAAS,UAAU,CAAC,MAAM,EAAE,KAAK,EAC/B,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,EAClC,OAAO,CAAC,EAAE,iBAAiB,CAAC,KAAK,CAAC;;iBAGA,MAAM,GAAG,IAAI;aAAa,MAAM,EAAE;;sCAgB3B,KAAK;;EAO/C;AA6DD,KAAK,cAAc,GAAG;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAuEF,OAAO,EAAE,UAAU,EAAE,CAAC;AAEtB,QAAA,MAAM,SAAS;;;;;;;;8BAxEkB,GAAG,mBAAmB,cAAc,uBAI3B,QAAQ;4BA6DnB,MAAM,EAAE,KAAK,YAChC,CAAC,KAAK,EAAE,KAAK,KAAK,MAAM,YACxB,iBAAiB,CAAC,KAAK,CAAC;;;;;;;;;CAiBnC,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
package/dist/lib/test-utils.js
CHANGED
|
@@ -33,12 +33,14 @@ import { resetRepliesPagesStore, resetRepliesPagesDatabaseAndStore } from "../st
|
|
|
33
33
|
// result.current via useEffect, which breaks polling-based waitFor patterns
|
|
34
34
|
// when Zustand store updates trigger re-renders outside act().
|
|
35
35
|
function renderHook(callback, options) {
|
|
36
|
-
const _a = options || {}, { initialProps } = _a, renderOptions = __rest(_a, ["initialProps"]);
|
|
36
|
+
const _a = options || {}, { initialProps, trackHistory = false } = _a, renderOptions = __rest(_a, ["initialProps", "trackHistory"]);
|
|
37
37
|
const result = { current: null, all: [] };
|
|
38
38
|
function TestComponent({ renderCallbackProps }) {
|
|
39
39
|
const pendingResult = callback(renderCallbackProps);
|
|
40
40
|
result.current = pendingResult;
|
|
41
|
-
|
|
41
|
+
if (trackHistory) {
|
|
42
|
+
result.all.push(pendingResult);
|
|
43
|
+
}
|
|
42
44
|
return null;
|
|
43
45
|
}
|
|
44
46
|
const { rerender: baseRerender, unmount } = render(React.createElement(TestComponent, { renderCallbackProps: initialProps }), renderOptions);
|
|
@@ -163,9 +165,7 @@ const resetDatabasesAndStores = () => __awaiter(void 0, void 0, void 0, function
|
|
|
163
165
|
// always accounts last because it has async initialization
|
|
164
166
|
yield resetAccountsDatabaseAndStore();
|
|
165
167
|
});
|
|
166
|
-
|
|
167
|
-
// renderHook already tracks result.all, so this is just a passthrough.
|
|
168
|
-
const renderHookWithHistory = renderHook;
|
|
168
|
+
const renderHookWithHistory = (callback, options) => renderHook(callback, Object.assign(Object.assign({}, options), { trackHistory: true }));
|
|
169
169
|
export { renderHook };
|
|
170
170
|
const testUtils = {
|
|
171
171
|
silenceTestWasNotWrappedInActWarning,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../../src/lib/test-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { render, act as tlAct } from \"@testing-library/react\";\nimport React from \"react\";\nimport { resetCommentsStore, resetCommentsDatabaseAndStore } from \"../stores/comments\";\nimport { resetCommunitiesStore, resetCommunitiesDatabaseAndStore } from \"../stores/communities\";\nimport { resetAccountsStore, resetAccountsDatabaseAndStore } from \"../stores/accounts\";\nimport { resetFeedsStore, resetFeedsDatabaseAndStore } from \"../stores/feeds\";\nimport {\n resetCommunitiesPagesStore,\n resetCommunitiesPagesDatabaseAndStore,\n} from \"../stores/communities-pages\";\nimport {\n resetAuthorsCommentsStore,\n resetAuthorsCommentsDatabaseAndStore,\n} from \"../stores/authors-comments\";\nimport { resetRepliesStore, resetRepliesDatabaseAndStore } from \"../stores/replies\";\nimport { resetRepliesPagesStore, resetRepliesPagesDatabaseAndStore } from \"../stores/replies-pages\";\n\n// Custom renderHook that sets result.current synchronously during render,\n// matching @testing-library/react-hooks behavior. RTL v16's renderHook defers\n// result.current via useEffect, which breaks polling-based waitFor patterns\n// when Zustand store updates trigger re-renders outside act().\nfunction renderHook<Result, Props>(\n callback: (props: Props) => Result,\n options?: { initialProps?: Props },\n) {\n const { initialProps, ...renderOptions } = options || {};\n const result = { current: null as Result | null, all: [] as Result[] };\n\n function TestComponent({ renderCallbackProps }: { renderCallbackProps: Props }) {\n const pendingResult = callback(renderCallbackProps);\n result.current = pendingResult;\n result.all.push(pendingResult);\n return null;\n }\n\n const { rerender: baseRerender, unmount } = render(\n React.createElement(TestComponent, { renderCallbackProps: initialProps as Props }),\n renderOptions as any,\n );\n\n function rerender(rerenderCallbackProps: Props) {\n return baseRerender(\n React.createElement(TestComponent, { renderCallbackProps: rerenderCallbackProps }),\n );\n }\n\n return { result, rerender, unmount };\n}\n\nconst restorables: any = [];\n\nconst silenceUpdateUnmountedComponentWarning = () => {\n const originalError = console.error;\n console.error = (...args) => {\n if (/Can't perform a React state update on an unmounted component/.test(args[0])) {\n return;\n }\n originalError.call(console, ...args);\n };\n const restore = () => {\n console.error = originalError;\n };\n restorables.push(restore);\n return restore;\n};\n\nconst silenceTestWasNotWrappedInActWarning = () => {\n const originalError = console.error;\n console.error = (...args) => {\n if (/inside a test was not wrapped in act/.test(args[0])) {\n return;\n }\n originalError.call(console, ...args);\n };\n const restore = () => {\n console.error = originalError;\n };\n restorables.push(restore);\n return restore;\n};\n\n// this warning is usually good to have, so don't include it in silenceReactWarnings\nconst silenceOverlappingActWarning = () => {\n const originalError = console.error;\n console.error = (...args) => {\n if (/overlapping act\\(\\) calls/.test(args[0])) {\n return;\n }\n originalError.call(console, ...args);\n };\n const restore = () => {\n console.error = originalError;\n };\n restorables.push(restore);\n return restore;\n};\n\nconst silenceReactWarnings = () => {\n silenceUpdateUnmountedComponentWarning();\n silenceTestWasNotWrappedInActWarning();\n};\n\nconst restoreAll = () => {\n for (const restore of restorables) {\n restore();\n }\n};\n\ntype WaitForOptions = {\n timeout?: number;\n interval?: number;\n};\nconst createWaitFor = (rendered: any, waitForOptions?: WaitForOptions) => {\n if (!rendered?.result) {\n throw Error(`createWaitFor invalid 'rendered' argument`);\n }\n const waitFor = async (waitForFunction: Function) => {\n const stackTraceLimit = Error.stackTraceLimit;\n Error.stackTraceLimit = 10;\n const errorWithUsefulStackTrace = new Error(\"waitFor\");\n Error.stackTraceLimit = stackTraceLimit;\n\n if (typeof waitForFunction !== \"function\") {\n throw Error(`waitFor invalid 'waitForFunction' argument`);\n }\n // @ts-ignore\n if (typeof waitForFunction.then === \"function\") {\n throw Error(`waitFor 'waitForFunction' can't be async`);\n }\n const { timeout = 2000, interval = 50 } = waitForOptions || {};\n const start = Date.now();\n while (true) {\n // flush pending React/Zustand state updates before each check\n await tlAct(async () => {});\n try {\n if (waitForFunction()) return;\n } catch {\n // condition threw (e.g. accessing property on undefined), keep waiting\n }\n if (Date.now() - start >= timeout) {\n errorWithUsefulStackTrace.message = `Timed out in waitFor after ${timeout}ms. ${waitForFunction.toString()}`;\n if (!testUtils.silenceWaitForWarning) {\n console.warn(errorWithUsefulStackTrace);\n }\n return;\n }\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n };\n return waitFor;\n};\n\n// always reset the least important store first, because a store even can affect another store\nconst resetStores = async () => {\n await resetRepliesPagesStore();\n await resetRepliesStore();\n await resetAuthorsCommentsStore();\n await resetCommunitiesPagesStore();\n await resetFeedsStore();\n await resetCommunitiesStore();\n await resetCommentsStore();\n // always accounts last because it has async initialization\n await resetAccountsStore();\n};\n\nconst resetDatabasesAndStores = async () => {\n await resetRepliesPagesDatabaseAndStore();\n await resetRepliesDatabaseAndStore();\n await resetAuthorsCommentsDatabaseAndStore();\n await resetCommunitiesPagesDatabaseAndStore();\n await resetFeedsDatabaseAndStore();\n await resetCommunitiesDatabaseAndStore();\n await resetCommentsDatabaseAndStore();\n // always accounts last because it has async initialization\n await resetAccountsDatabaseAndStore();\n};\n\n// renderHookWithHistory is kept for backward compatibility but our custom\n// renderHook already tracks result.all, so this is just a passthrough.\nconst renderHookWithHistory = renderHook;\n\nexport { renderHook };\n\nconst testUtils = {\n silenceTestWasNotWrappedInActWarning,\n silenceUpdateUnmountedComponentWarning,\n silenceOverlappingActWarning,\n silenceReactWarnings,\n restoreAll,\n resetStores,\n resetDatabasesAndStores,\n createWaitFor,\n renderHookWithHistory,\n // can be useful to silence warnings in tests that use retry\n silenceWaitForWarning: false,\n};\n\nexport default testUtils;\n"]}
|
|
1
|
+
{"version":3,"file":"test-utils.js","sourceRoot":"","sources":["../../src/lib/test-utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { render, act as tlAct } from \"@testing-library/react\";\nimport React from \"react\";\nimport { resetCommentsStore, resetCommentsDatabaseAndStore } from \"../stores/comments\";\nimport { resetCommunitiesStore, resetCommunitiesDatabaseAndStore } from \"../stores/communities\";\nimport { resetAccountsStore, resetAccountsDatabaseAndStore } from \"../stores/accounts\";\nimport { resetFeedsStore, resetFeedsDatabaseAndStore } from \"../stores/feeds\";\nimport {\n resetCommunitiesPagesStore,\n resetCommunitiesPagesDatabaseAndStore,\n} from \"../stores/communities-pages\";\nimport {\n resetAuthorsCommentsStore,\n resetAuthorsCommentsDatabaseAndStore,\n} from \"../stores/authors-comments\";\nimport { resetRepliesStore, resetRepliesDatabaseAndStore } from \"../stores/replies\";\nimport { resetRepliesPagesStore, resetRepliesPagesDatabaseAndStore } from \"../stores/replies-pages\";\n\ntype RenderHookOptions<Props> = {\n initialProps?: Props;\n trackHistory?: boolean;\n};\n\n// Custom renderHook that sets result.current synchronously during render,\n// matching @testing-library/react-hooks behavior. RTL v16's renderHook defers\n// result.current via useEffect, which breaks polling-based waitFor patterns\n// when Zustand store updates trigger re-renders outside act().\nfunction renderHook<Result, Props>(\n callback: (props: Props) => Result,\n options?: RenderHookOptions<Props>,\n) {\n const { initialProps, trackHistory = false, ...renderOptions } = options || {};\n const result = { current: null as Result | null, all: [] as Result[] };\n\n function TestComponent({ renderCallbackProps }: { renderCallbackProps: Props }) {\n const pendingResult = callback(renderCallbackProps);\n result.current = pendingResult;\n if (trackHistory) {\n result.all.push(pendingResult);\n }\n return null;\n }\n\n const { rerender: baseRerender, unmount } = render(\n React.createElement(TestComponent, { renderCallbackProps: initialProps as Props }),\n renderOptions as any,\n );\n\n function rerender(rerenderCallbackProps: Props) {\n return baseRerender(\n React.createElement(TestComponent, { renderCallbackProps: rerenderCallbackProps }),\n );\n }\n\n return { result, rerender, unmount };\n}\n\nconst restorables: any = [];\n\nconst silenceUpdateUnmountedComponentWarning = () => {\n const originalError = console.error;\n console.error = (...args) => {\n if (/Can't perform a React state update on an unmounted component/.test(args[0])) {\n return;\n }\n originalError.call(console, ...args);\n };\n const restore = () => {\n console.error = originalError;\n };\n restorables.push(restore);\n return restore;\n};\n\nconst silenceTestWasNotWrappedInActWarning = () => {\n const originalError = console.error;\n console.error = (...args) => {\n if (/inside a test was not wrapped in act/.test(args[0])) {\n return;\n }\n originalError.call(console, ...args);\n };\n const restore = () => {\n console.error = originalError;\n };\n restorables.push(restore);\n return restore;\n};\n\n// this warning is usually good to have, so don't include it in silenceReactWarnings\nconst silenceOverlappingActWarning = () => {\n const originalError = console.error;\n console.error = (...args) => {\n if (/overlapping act\\(\\) calls/.test(args[0])) {\n return;\n }\n originalError.call(console, ...args);\n };\n const restore = () => {\n console.error = originalError;\n };\n restorables.push(restore);\n return restore;\n};\n\nconst silenceReactWarnings = () => {\n silenceUpdateUnmountedComponentWarning();\n silenceTestWasNotWrappedInActWarning();\n};\n\nconst restoreAll = () => {\n for (const restore of restorables) {\n restore();\n }\n};\n\ntype WaitForOptions = {\n timeout?: number;\n interval?: number;\n};\nconst createWaitFor = (rendered: any, waitForOptions?: WaitForOptions) => {\n if (!rendered?.result) {\n throw Error(`createWaitFor invalid 'rendered' argument`);\n }\n const waitFor = async (waitForFunction: Function) => {\n const stackTraceLimit = Error.stackTraceLimit;\n Error.stackTraceLimit = 10;\n const errorWithUsefulStackTrace = new Error(\"waitFor\");\n Error.stackTraceLimit = stackTraceLimit;\n\n if (typeof waitForFunction !== \"function\") {\n throw Error(`waitFor invalid 'waitForFunction' argument`);\n }\n // @ts-ignore\n if (typeof waitForFunction.then === \"function\") {\n throw Error(`waitFor 'waitForFunction' can't be async`);\n }\n const { timeout = 2000, interval = 50 } = waitForOptions || {};\n const start = Date.now();\n while (true) {\n // flush pending React/Zustand state updates before each check\n await tlAct(async () => {});\n try {\n if (waitForFunction()) return;\n } catch {\n // condition threw (e.g. accessing property on undefined), keep waiting\n }\n if (Date.now() - start >= timeout) {\n errorWithUsefulStackTrace.message = `Timed out in waitFor after ${timeout}ms. ${waitForFunction.toString()}`;\n if (!testUtils.silenceWaitForWarning) {\n console.warn(errorWithUsefulStackTrace);\n }\n return;\n }\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n };\n return waitFor;\n};\n\n// always reset the least important store first, because a store even can affect another store\nconst resetStores = async () => {\n await resetRepliesPagesStore();\n await resetRepliesStore();\n await resetAuthorsCommentsStore();\n await resetCommunitiesPagesStore();\n await resetFeedsStore();\n await resetCommunitiesStore();\n await resetCommentsStore();\n // always accounts last because it has async initialization\n await resetAccountsStore();\n};\n\nconst resetDatabasesAndStores = async () => {\n await resetRepliesPagesDatabaseAndStore();\n await resetRepliesDatabaseAndStore();\n await resetAuthorsCommentsDatabaseAndStore();\n await resetCommunitiesPagesDatabaseAndStore();\n await resetFeedsDatabaseAndStore();\n await resetCommunitiesDatabaseAndStore();\n await resetCommentsDatabaseAndStore();\n // always accounts last because it has async initialization\n await resetAccountsDatabaseAndStore();\n};\n\nconst renderHookWithHistory = <Result, Props>(\n callback: (props: Props) => Result,\n options?: RenderHookOptions<Props>,\n) => renderHook(callback, { ...options, trackHistory: true });\n\nexport { renderHook };\n\nconst testUtils = {\n silenceTestWasNotWrappedInActWarning,\n silenceUpdateUnmountedComponentWarning,\n silenceOverlappingActWarning,\n silenceReactWarnings,\n restoreAll,\n resetStores,\n resetDatabasesAndStores,\n createWaitFor,\n renderHookWithHistory,\n // can be useful to silence warnings in tests that use retry\n silenceWaitForWarning: false,\n};\n\nexport default testUtils;\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comments-store.d.ts","sourceRoot":"","sources":["../../../src/stores/comments/comments-store.ts"],"names":[],"mappings":"AAKA,OAAO,MAAM,MAAM,yBAAyB,CAAC;AAC7C,eAAO,MAAM,GAAG,QAAkD,CAAC;AACnE,OAAO,EAAW,QAAQ,EAAW,MAAM,aAAa,CAAC;AAkBzD,eAAO,MAAM,SAAS,EAAE,GAAQ,CAAC;AAEjC,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE;QAAE,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,EAAE,CAAA;KAAE,CAAC;IAC1C,iBAAiB,EAAE,QAAQ,CAAC;IAC5B,sBAAsB,EAAE,QAAQ,CAAC;IACjC,qBAAqB,EAAE,QAAQ,CAAC;IAChC,cAAc,EAAE,QAAQ,CAAC;CAC1B,CAAC;
|
|
1
|
+
{"version":3,"file":"comments-store.d.ts","sourceRoot":"","sources":["../../../src/stores/comments/comments-store.ts"],"names":[],"mappings":"AAKA,OAAO,MAAM,MAAM,yBAAyB,CAAC;AAC7C,eAAO,MAAM,GAAG,QAAkD,CAAC;AACnE,OAAO,EAAW,QAAQ,EAAW,MAAM,aAAa,CAAC;AAkBzD,eAAO,MAAM,SAAS,EAAE,GAAQ,CAAC;AAEjC,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE;QAAE,CAAC,UAAU,EAAE,MAAM,GAAG,KAAK,EAAE,CAAA;KAAE,CAAC;IAC1C,iBAAiB,EAAE,QAAQ,CAAC;IAC5B,sBAAsB,EAAE,QAAQ,CAAC;IACjC,qBAAqB,EAAE,QAAQ,CAAC;IAChC,cAAc,EAAE,QAAQ,CAAC;CAC1B,CAAC;AAuDF,QAAA,MAAM,aAAa,4EA2UjB,CAAC;AA8BH,eAAO,MAAM,kBAAkB,qBAgC9B,CAAC;AAGF,eAAO,MAAM,6BAA6B,qBAGzC,CAAC;AAEF,eAAe,aAAa,CAAC"}
|
|
@@ -39,6 +39,16 @@ const removeCommentListener = (comment, event, listener) => {
|
|
|
39
39
|
};
|
|
40
40
|
const getCommentAutoUpdateSubscribersCount = (commentCid) => Object.keys(commentAutoUpdateSubscribers[commentCid] || {}).length;
|
|
41
41
|
const hasCommentAutoUpdateSubscribers = (commentCid) => getCommentAutoUpdateSubscribersCount(commentCid) > 0;
|
|
42
|
+
const mergeCommentData = (commentCid, ...commentDataList) => {
|
|
43
|
+
const mergedCommentData = { cid: commentCid };
|
|
44
|
+
for (const commentData of commentDataList) {
|
|
45
|
+
if (commentData && typeof commentData === "object") {
|
|
46
|
+
Object.assign(mergedCommentData, utils.clone(commentData));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
mergedCommentData.cid = commentCid;
|
|
50
|
+
return mergedCommentData;
|
|
51
|
+
};
|
|
42
52
|
const releaseLiveComment = (commentCid, comment) => {
|
|
43
53
|
const liveComment = comment || liveComments[commentCid];
|
|
44
54
|
if (liveComment) {
|
|
@@ -172,8 +182,7 @@ const commentsStore = createStore((setState, getState) => {
|
|
|
172
182
|
return liveCommentPromises[commentCid];
|
|
173
183
|
}
|
|
174
184
|
const liveCommentPromise = (() => __awaiter(void 0, void 0, void 0, function* () {
|
|
175
|
-
const initialComment = normalizeCommentCommunityAddress(
|
|
176
|
-
{ cid: commentCid };
|
|
185
|
+
const initialComment = normalizeCommentCommunityAddress(mergeCommentData(commentCid, commentData));
|
|
177
186
|
const liveComment = normalizeCommentCommunityAddress(yield account.pkc.createComment(initialComment));
|
|
178
187
|
initializeComment(commentCid, liveComment, account);
|
|
179
188
|
return liveComment;
|
|
@@ -226,7 +235,7 @@ const commentsStore = createStore((setState, getState) => {
|
|
|
226
235
|
return {
|
|
227
236
|
comments: {},
|
|
228
237
|
errors: {},
|
|
229
|
-
addCommentToStore(commentCid, account) {
|
|
238
|
+
addCommentToStore(commentCid, account, commentData) {
|
|
230
239
|
return __awaiter(this, void 0, void 0, function* () {
|
|
231
240
|
const { comments } = getState();
|
|
232
241
|
const pendingKey = commentCid + account.id;
|
|
@@ -238,9 +247,9 @@ const commentsStore = createStore((setState, getState) => {
|
|
|
238
247
|
pkcGetCommentPending[pendingKey] = true;
|
|
239
248
|
try {
|
|
240
249
|
// try to find comment in database
|
|
241
|
-
comment = yield getCommentFromDatabase(commentCid, account);
|
|
250
|
+
comment = yield getCommentFromDatabase(commentCid, account, commentData);
|
|
242
251
|
if (!comment) {
|
|
243
|
-
comment = yield ensureLiveComment(commentCid, account,
|
|
252
|
+
comment = yield ensureLiveComment(commentCid, account, commentData);
|
|
244
253
|
comment = normalizeCommentCommunityAddress(comment);
|
|
245
254
|
log("commentsStore.addCommentToStore", { commentCid, comment, account });
|
|
246
255
|
setState((state) => ({
|
|
@@ -254,7 +263,7 @@ const commentsStore = createStore((setState, getState) => {
|
|
|
254
263
|
}));
|
|
255
264
|
// add comment replies pages to repliesPagesStore so they can be used in useComment
|
|
256
265
|
repliesPagesStore.getState().addRepliesPageCommentsToStore(comment);
|
|
257
|
-
comment = yield ensureLiveComment(commentCid, account, comment);
|
|
266
|
+
comment = yield ensureLiveComment(commentCid, account, mergeCommentData(commentCid, comment, commentData));
|
|
258
267
|
}
|
|
259
268
|
if (comment) {
|
|
260
269
|
requestCommentUpdate(commentCid, comment, { stopAfterNextUpdate: true });
|
|
@@ -269,7 +278,7 @@ const commentsStore = createStore((setState, getState) => {
|
|
|
269
278
|
}
|
|
270
279
|
});
|
|
271
280
|
},
|
|
272
|
-
startCommentAutoUpdate(commentCid, subscriberId, account) {
|
|
281
|
+
startCommentAutoUpdate(commentCid, subscriberId, account, commentData) {
|
|
273
282
|
return __awaiter(this, void 0, void 0, function* () {
|
|
274
283
|
const hadAutoUpdateSubscribers = hasCommentAutoUpdateSubscribers(commentCid);
|
|
275
284
|
commentAutoUpdateSubscribers[commentCid] = Object.assign(Object.assign({}, (commentAutoUpdateSubscribers[commentCid] || {})), { [subscriberId]: true });
|
|
@@ -277,7 +286,7 @@ const commentsStore = createStore((setState, getState) => {
|
|
|
277
286
|
return;
|
|
278
287
|
}
|
|
279
288
|
const storedComment = getState().comments[commentCid];
|
|
280
|
-
const liveComment = yield ensureLiveComment(commentCid, account, storedComment
|
|
289
|
+
const liveComment = yield ensureLiveComment(commentCid, account, mergeCommentData(commentCid, storedComment, commentData));
|
|
281
290
|
if (!storedComment) {
|
|
282
291
|
setState((state) => ({
|
|
283
292
|
comments: Object.assign(Object.assign({}, state.comments), { [commentCid]: utils.clone(liveComment) }),
|
|
@@ -308,10 +317,10 @@ const commentsStore = createStore((setState, getState) => {
|
|
|
308
317
|
maybeReleaseStoppedLiveComment(commentCid, liveComment);
|
|
309
318
|
});
|
|
310
319
|
},
|
|
311
|
-
refreshComment(commentCid, account) {
|
|
320
|
+
refreshComment(commentCid, account, commentData) {
|
|
312
321
|
return __awaiter(this, void 0, void 0, function* () {
|
|
313
322
|
const storedComment = getState().comments[commentCid];
|
|
314
|
-
const liveComment = yield ensureLiveComment(commentCid, account, storedComment
|
|
323
|
+
const liveComment = yield ensureLiveComment(commentCid, account, mergeCommentData(commentCid, storedComment, commentData));
|
|
315
324
|
if (!hasCommentAutoUpdateSubscribers(commentCid) &&
|
|
316
325
|
(liveComment === null || liveComment === void 0 ? void 0 : liveComment.updatingState) !== "stopped") {
|
|
317
326
|
yield stopLiveComment(commentCid, liveComment);
|
|
@@ -325,13 +334,13 @@ const commentsStore = createStore((setState, getState) => {
|
|
|
325
334
|
},
|
|
326
335
|
};
|
|
327
336
|
});
|
|
328
|
-
const getCommentFromDatabase = (commentCid, account) => __awaiter(void 0, void 0, void 0, function* () {
|
|
337
|
+
const getCommentFromDatabase = (commentCid, account, initialCommentData) => __awaiter(void 0, void 0, void 0, function* () {
|
|
329
338
|
const commentData = yield commentsDatabase.getItem(commentCid);
|
|
330
339
|
if (!commentData) {
|
|
331
340
|
return;
|
|
332
341
|
}
|
|
333
342
|
try {
|
|
334
|
-
const comment = normalizeCommentCommunityAddress(yield account.pkc.createComment(commentData));
|
|
343
|
+
const comment = normalizeCommentCommunityAddress(yield account.pkc.createComment(mergeCommentData(commentCid, commentData, initialCommentData)));
|
|
335
344
|
return comment;
|
|
336
345
|
}
|
|
337
346
|
catch (e) {
|