@rocapine/community-core 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/hooks.d.ts +5 -7
- package/lib/hooks.js +9 -12
- package/lib/models.d.ts +1 -1
- package/lib/models.js +7 -3
- package/lib/service.d.ts +3 -3
- package/lib/service.js +17 -7
- package/package.json +1 -1
package/lib/hooks.d.ts
CHANGED
|
@@ -120,16 +120,14 @@ export declare function useVotePoll(): import("@tanstack/react-query").UseMutati
|
|
|
120
120
|
optionId: string;
|
|
121
121
|
}, PostCacheSnapshot>;
|
|
122
122
|
/**
|
|
123
|
-
* Optimistic reaction across every post cache (mirror of
|
|
124
|
-
* from the mold's `usePrayForPost`). `
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
* that post already had `hasReacted` so a retap of an already-reacted post
|
|
128
|
-
* (the reaction is non-retractable, `setReaction` is idempotent) does not
|
|
129
|
-
* re-emit the analytics event.
|
|
123
|
+
* Optimistic reaction toggle across every post cache (mirror of useToggleLike;
|
|
124
|
+
* renamed from the mold's `usePrayForPost`). `on` defaults to true (react);
|
|
125
|
+
* `on: false` withdraws it. `alreadyReacted` keeps a retap of an
|
|
126
|
+
* already-reacted post from re-emitting the analytics event.
|
|
130
127
|
*/
|
|
131
128
|
export declare function useReactToPost(): import("@tanstack/react-query").UseMutationResult<void, Error, {
|
|
132
129
|
postId: string;
|
|
130
|
+
on?: boolean;
|
|
133
131
|
}, PostCacheSnapshot & {
|
|
134
132
|
alreadyReacted: boolean;
|
|
135
133
|
}>;
|
package/lib/hooks.js
CHANGED
|
@@ -476,27 +476,24 @@ function useVotePoll() {
|
|
|
476
476
|
});
|
|
477
477
|
}
|
|
478
478
|
/**
|
|
479
|
-
* Optimistic reaction across every post cache (mirror of
|
|
480
|
-
* from the mold's `usePrayForPost`). `
|
|
481
|
-
*
|
|
482
|
-
*
|
|
483
|
-
* that post already had `hasReacted` so a retap of an already-reacted post
|
|
484
|
-
* (the reaction is non-retractable, `setReaction` is idempotent) does not
|
|
485
|
-
* re-emit the analytics event.
|
|
479
|
+
* Optimistic reaction toggle across every post cache (mirror of useToggleLike;
|
|
480
|
+
* renamed from the mold's `usePrayForPost`). `on` defaults to true (react);
|
|
481
|
+
* `on: false` withdraws it. `alreadyReacted` keeps a retap of an
|
|
482
|
+
* already-reacted post from re-emitting the analytics event.
|
|
486
483
|
*/
|
|
487
484
|
function useReactToPost() {
|
|
488
485
|
const cfg = (0, provider_1.useCommunityConfig)();
|
|
489
486
|
const queryClient = (0, react_query_1.useQueryClient)();
|
|
490
487
|
return (0, react_query_1.useMutation)({
|
|
491
|
-
mutationFn: ({ postId }) => (0, service_1.setReaction)(cfg, postId),
|
|
492
|
-
onMutate: async ({ postId }) => {
|
|
488
|
+
mutationFn: ({ postId, on = true }) => (0, service_1.setReaction)(cfg, postId, on),
|
|
489
|
+
onMutate: async ({ postId, on = true }) => {
|
|
493
490
|
let alreadyReacted = false;
|
|
494
491
|
const snapshot = await applyOptimisticToAllPostCaches(queryClient, (post) => {
|
|
495
492
|
if (post.id !== postId)
|
|
496
493
|
return post;
|
|
497
494
|
if (post.hasReacted)
|
|
498
495
|
alreadyReacted = true;
|
|
499
|
-
return (0, models_1.applyReaction)(post);
|
|
496
|
+
return (0, models_1.applyReaction)(post, on);
|
|
500
497
|
});
|
|
501
498
|
return { ...snapshot, alreadyReacted };
|
|
502
499
|
},
|
|
@@ -504,8 +501,8 @@ function useReactToPost() {
|
|
|
504
501
|
if (context)
|
|
505
502
|
rollbackPostCaches(queryClient, context);
|
|
506
503
|
},
|
|
507
|
-
onSuccess: (_data, { postId }, context) => {
|
|
508
|
-
if (!context?.alreadyReacted)
|
|
504
|
+
onSuccess: (_data, { postId, on = true }, context) => {
|
|
505
|
+
if (on && !context?.alreadyReacted)
|
|
509
506
|
(0, events_1.emitEvent)(cfg, events_1.COMMUNITY_EVENTS.reactionAdded, { postId });
|
|
510
507
|
},
|
|
511
508
|
});
|
package/lib/models.d.ts
CHANGED
|
@@ -203,7 +203,7 @@ export declare function applyPollVote(post: FeedPost, postId: string, optionId:
|
|
|
203
203
|
* caller is expected to have already located the target post (e.g. via
|
|
204
204
|
* `posts.map((p) => (p.id === postId ? applyReaction(p) : p))`).
|
|
205
205
|
*/
|
|
206
|
-
export declare function applyReaction(post: FeedPost): FeedPost;
|
|
206
|
+
export declare function applyReaction(post: FeedPost, on?: boolean): FeedPost;
|
|
207
207
|
export declare function mapCommentRow(row: CommentRow, myUid: string, fallback: string): ThreadComment;
|
|
208
208
|
/** Floating pill label. "1 new post" / "N new posts". */
|
|
209
209
|
export declare function newPostsLabel(count: number): string;
|
package/lib/models.js
CHANGED
|
@@ -150,10 +150,14 @@ function applyPollVote(post, postId, optionId) {
|
|
|
150
150
|
* caller is expected to have already located the target post (e.g. via
|
|
151
151
|
* `posts.map((p) => (p.id === postId ? applyReaction(p) : p))`).
|
|
152
152
|
*/
|
|
153
|
-
function applyReaction(post) {
|
|
154
|
-
if (post.hasReacted)
|
|
153
|
+
function applyReaction(post, on = true) {
|
|
154
|
+
if (post.hasReacted === on)
|
|
155
155
|
return post;
|
|
156
|
-
return {
|
|
156
|
+
return {
|
|
157
|
+
...post,
|
|
158
|
+
hasReacted: on,
|
|
159
|
+
reactionCount: Math.max(0, post.reactionCount + (on ? 1 : -1)),
|
|
160
|
+
};
|
|
157
161
|
}
|
|
158
162
|
function mapCommentRow(row, myUid, fallback) {
|
|
159
163
|
return {
|
package/lib/service.d.ts
CHANGED
|
@@ -102,10 +102,10 @@ export declare function moderateOne(cfg: ResolvedCommunityConfig, input: {
|
|
|
102
102
|
}): Promise<ModerationVerdict>;
|
|
103
103
|
export declare function setLike(cfg: ResolvedCommunityConfig, postId: string, on: boolean): Promise<void>;
|
|
104
104
|
/**
|
|
105
|
-
* `setPrayed` generalized to `setReaction`: insert my private
|
|
106
|
-
* reaction row
|
|
105
|
+
* `setPrayed` generalized to `setReaction`: insert (`on`) or delete my private
|
|
106
|
+
* reaction row, like `setLike`. Gated on `cfg.modules.reaction`.
|
|
107
107
|
*/
|
|
108
|
-
export declare function setReaction(cfg: ResolvedCommunityConfig, postId: string): Promise<void>;
|
|
108
|
+
export declare function setReaction(cfg: ResolvedCommunityConfig, postId: string, on?: boolean): Promise<void>;
|
|
109
109
|
export type ReportReason = "spam" | "harassment" | "hate" | "inappropriate" | "other";
|
|
110
110
|
export interface ReportInput {
|
|
111
111
|
reportedUserId: string;
|
package/lib/service.js
CHANGED
|
@@ -419,18 +419,28 @@ async function setLike(cfg, postId, on) {
|
|
|
419
419
|
}
|
|
420
420
|
}
|
|
421
421
|
/**
|
|
422
|
-
* `setPrayed` generalized to `setReaction`: insert my private
|
|
423
|
-
* reaction row
|
|
422
|
+
* `setPrayed` generalized to `setReaction`: insert (`on`) or delete my private
|
|
423
|
+
* reaction row, like `setLike`. Gated on `cfg.modules.reaction`.
|
|
424
424
|
*/
|
|
425
|
-
async function setReaction(cfg, postId) {
|
|
425
|
+
async function setReaction(cfg, postId, on = true) {
|
|
426
426
|
if (!cfg.modules.reaction)
|
|
427
427
|
throw new Error("reaction module is not enabled");
|
|
428
428
|
const client = cfg.requireClient();
|
|
429
429
|
const uid = await requireUid(cfg);
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
430
|
+
if (on) {
|
|
431
|
+
const { error } = await client.from("post_reactions").insert({ post_id: postId, user_id: uid });
|
|
432
|
+
// 23505 = already reacted to this post: the desired state holds.
|
|
433
|
+
if (error && error.code !== "23505")
|
|
434
|
+
throw error;
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
const { error } = await client
|
|
438
|
+
.from("post_reactions")
|
|
439
|
+
.delete()
|
|
440
|
+
.match({ post_id: postId, user_id: uid });
|
|
441
|
+
if (error)
|
|
442
|
+
throw error;
|
|
443
|
+
}
|
|
434
444
|
}
|
|
435
445
|
async function reportContent(cfg, input) {
|
|
436
446
|
const client = cfg.requireClient();
|
package/package.json
CHANGED