Skip to content
This repository has been archived by the owner on Jan 15, 2025. It is now read-only.

Comments pinning #1524

Merged
merged 19 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
3b5100c
Comment pin: separated discussion file to multiple ones
dkildar Dec 21, 2023
7533533
Comment pin: migrated discussion requests to queries
dkildar Dec 22, 2023
682af21
Comment pin: improved font stylings
dkildar Dec 22, 2023
55d1332
Comment pin: migrated to mutations, updating discussions query after …
dkildar Dec 22, 2023
ed5b512
Comment pin: splitted mutations to separated files, added immediately…
dkildar Dec 23, 2023
0f750b4
Comment pin: updated dropdown component for comment actions
dkildar Dec 23, 2023
b5e9f52
Comment pin: fixup styles
dkildar Dec 23, 2023
746ad45
Comment pin: added pinning of comments and sub-comments
dkildar Dec 23, 2023
c769c69
Comment pin: fixed replying from decks and added pinning from decks
dkildar Dec 23, 2023
d5875f7
Comment pin: removed discussion store module, added bubbling up pinne…
dkildar Dec 23, 2023
7d1ef19
Comment pin: disable tests while fixing it
dkildar Dec 23, 2023
627fcc1
Comment pin: fixed build errors
dkildar Dec 23, 2023
0524f13
Comment pin: fixed dropdown and popover confirm overlapping
dkildar Dec 24, 2023
e89a0b6
Comment pin: unable to delete pinned comment
dkildar Dec 24, 2023
a26fe9b
Comment pin: fixed tests
dkildar Dec 24, 2023
a01f373
remove no action button
feruzm Jan 10, 2024
c259ac6
Merge branch 'development' into feature/pinned-comment
dkildar Jan 11, 2024
4e3af75
Comment pin: updating via patching, fixed dropdown condition, allow t…
dkildar Jan 11, 2024
c517a48
Merge branch 'development' into feature/pinned-comment
feruzm Jan 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,21 +1,7 @@
import { FullAccount } from "../../store/accounts/types";
import { useMutation } from "@tanstack/react-query";
import { usrActivity } from "./private-api";
import { claimAccount, claimAccountByKeychain } from "./operations";
import { FullAccount } from "../store/accounts/types";
import { PrivateKey } from "@hiveio/dhive";

interface Params {
bl?: string | number;
tx?: string | number;
}

export function useUserActivity(username: string | undefined, ty: number) {
return useMutation(["user-activity", username, ty], async (params: Params | undefined) => {
if (username) {
await usrActivity(username, ty, params?.bl, params?.tx);
}
});
}
import { claimAccount, claimAccountByKeychain } from "../operations";

export function useAccountClaiming(account: FullAccount) {
return useMutation(
Expand Down
94 changes: 94 additions & 0 deletions src/common/api/mutations/create-reply.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { Entry } from "../../store/entries/types";
import { useMappedStore } from "../../store/use-mapped-store";
import { useContext } from "react";
import { EntriesCacheContext, QueryIdentifiers } from "../../core";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { comment, CommentOptions, formatError, MetaData } from "../operations";
import tempEntry from "../../helper/temp-entry";
import { FullAccount } from "../../store/accounts/types";
import * as ss from "../../util/session-storage";
import { error } from "../../components/feedback";

export function useCreateReply(entry: Entry | null, parent?: Entry, onSuccess?: () => void) {
const { activeUser } = useMappedStore();
const { addReply, updateRepliesCount, updateCache } = useContext(EntriesCacheContext);
const queryClient = useQueryClient();

return useMutation(
["reply-create", activeUser?.username, entry?.author, entry?.permlink],
async ({
permlink,
text,
jsonMeta,
options,
point
}: {
permlink: string;
text: string;
jsonMeta: MetaData;
point: boolean;
options?: CommentOptions;
}) => {
if (!activeUser || !activeUser.data.__loaded || !entry) {
throw new Error("[Reply][Create] – no active user provided");
}

await comment(
activeUser.username,
entry.author,
entry.permlink,
permlink,
"",
text,
jsonMeta,
options ?? null,
point
);
return tempEntry({
author: activeUser.data as FullAccount,
permlink,
parentAuthor: entry.author,
parentPermlink: entry.permlink,
title: "",
body: text,
tags: [],
description: null
});
},
{
onSuccess: (data) => {
if (!entry) {
return;
}

addReply(entry, data);
updateCache([data]);

// remove reply draft
ss.remove(`reply_draft_${entry.author}_${entry.permlink}`);

if (entry.children === 0) {
// Update parent comment.
updateRepliesCount(entry, 1);
}
const previousReplies =
queryClient.getQueryData<Entry[]>([
QueryIdentifiers.FETCH_DISCUSSIONS,
parent?.author ?? entry.author,
parent?.permlink ?? entry.permlink
]) ?? [];
queryClient.setQueryData(
[
QueryIdentifiers.FETCH_DISCUSSIONS,
parent?.author ?? entry.author,
parent?.permlink ?? entry.permlink
],
[data, ...previousReplies]
);

onSuccess?.();
},
onError: (e) => error(...formatError(e))
}
);
}
5 changes: 5 additions & 0 deletions src/common/api/mutations/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from "./account-claiming";
export * from "./create-reply";
export * from "./update-reply";
export * from "./user-activity";
export * from "./pin-reply";
26 changes: 26 additions & 0 deletions src/common/api/mutations/pin-reply.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useMutation } from "@tanstack/react-query";
import { Entry } from "../../store/entries/types";
import { createPatch, makeJsonMetaDataReply } from "../../helper/posting";
import { version } from "../../../../package.json";
import { useUpdateReply } from "./update-reply";
import { MetaData } from "../operations";

export function usePinReply(reply: Entry, parent: Entry) {
const { mutateAsync: updateReply } = useUpdateReply(parent);

return useMutation(["reply-pin", reply, parent], async ({ pin }: { pin: boolean }) => {
const meta = makeJsonMetaDataReply(
parent.json_metadata.tags || ["ecency"],
version
) as MetaData;

let newBody = parent.body.replace(/[\x00-\x09\x0B-\x0C\x0E-\x1F\x7F-\x9F]/g, "");
const patch = createPatch(parent.body, newBody.trim());
if (patch && patch.length < Buffer.from(parent.body, "utf-8").length) {
newBody = patch;
}

meta.pinned_reply = pin ? `${reply.author}/${reply.permlink}` : undefined;
return updateReply({ text: newBody, point: true, jsonMeta: meta });
});
}
63 changes: 63 additions & 0 deletions src/common/api/mutations/update-reply.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Entry } from "../../store/entries/types";
import { useMappedStore } from "../../store/use-mapped-store";
import { useContext } from "react";
import { EntriesCacheContext } from "../../core";
import { useMutation } from "@tanstack/react-query";
import { comment, CommentOptions, formatError, MetaData } from "../operations";
import * as ss from "../../util/session-storage";
import { error } from "../../components/feedback";

export function useUpdateReply(entry: Entry | null, onSuccess?: () => void) {
const { activeUser } = useMappedStore();
const { updateCache } = useContext(EntriesCacheContext);

return useMutation(
["reply-update", activeUser?.username, entry?.author, entry?.permlink],
async ({
text,
jsonMeta,
options,
point
}: {
text: string;
jsonMeta: MetaData;
point: boolean;
options?: CommentOptions;
}) => {
if (!activeUser || !activeUser.data.__loaded || !entry) {
throw new Error("[Reply][Create] – no active user provided");
}

await comment(
activeUser.username,
entry.parent_author ?? "",
entry.parent_permlink ?? entry.category,
entry.permlink,
"",
text,
jsonMeta,
options ?? null,
point
);
return {
...entry,
json_metadata: jsonMeta,
body: text
};
},
{
onSuccess: (data) => {
if (!entry) {
return;
}

updateCache([data]);

// remove reply draft
ss.remove(`reply_draft_${entry.author}_${entry.permlink}`);
onSuccess?.();
},
onError: (e) => error(...formatError(e))
}
);
}
15 changes: 15 additions & 0 deletions src/common/api/mutations/user-activity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useMutation } from "@tanstack/react-query";
import { usrActivity } from "../private-api";

interface Params {
bl?: string | number;
tx?: string | number;
}

export function useUserActivity(username: string | undefined, ty: number) {
return useMutation(["user-activity", username, ty], async (params: Params | undefined) => {
if (username) {
await usrActivity(username, ty, params?.bl, params?.tx);
}
});
}
1 change: 1 addition & 0 deletions src/common/api/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export interface MetaData {
description?: string;
video?: any;
type?: string;
pinned_reply?: string; // author/permlink
}

export interface BeneficiaryRoute {
Expand Down
61 changes: 58 additions & 3 deletions src/common/api/queries.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { useQueries, useQuery } from "@tanstack/react-query";
import { QueryIdentifiers } from "../core";
import { useQueries, useQuery, UseQueryOptions } from "@tanstack/react-query";
import { EntriesCacheContext, QueryIdentifiers } from "../core";
import { getPoints, getPointTransactions } from "./private-api";
import { useMappedStore } from "../store/use-mapped-store";
import axios from "axios";
import { catchPostImage } from "@ecency/render-helper";
import { Entry } from "../store/entries/types";
import { getAccountFull } from "./hive";
import { getAccountFull, getFollowing } from "./hive";
import { getAccountPosts, getDiscussion } from "./bridge";
import { SortOrder } from "../store/discussion/types";
import { useContext } from "react";
import { sortDiscussions } from "../util/sort-discussions";

const DEFAULT = {
points: "0.000",
Expand Down Expand Up @@ -105,3 +109,54 @@ export function useGetAccountsFullQuery(usernames: string[]) {
}))
});
}

export function useGetAccountPostsQuery(username?: string) {
return useQuery({
queryKey: [QueryIdentifiers.GET_POSTS, username],
queryFn: () => getAccountPosts("posts", username!).then((response) => response ?? []),
enabled: !!username,
initialData: []
});
}

export function useFetchDiscussionsQuery(
entry: Entry,
order: SortOrder,
queryOptions?: UseQueryOptions<Entry[]>
) {
const { updateCache } = useContext(EntriesCacheContext);

return useQuery<Entry[]>(
[QueryIdentifiers.FETCH_DISCUSSIONS, entry?.author, entry?.permlink],
async () => {
const response = await getDiscussion(entry.author, entry.permlink);
if (response) {
const entries = Array.from(Object.values(response));
updateCache([...entries], true);
return entries;
}
return [];
},
{
...queryOptions,
initialData: [],
select: (data) => sortDiscussions(entry, data, order)
}
);
}

export function useFetchMutedUsersQuery(username?: string) {
const { activeUser } = useMappedStore();

return useQuery(
[QueryIdentifiers.FETCH_MUTED_USERS, username ?? activeUser?.username ?? "anon"],
async () => {
const response = await getFollowing(username ?? activeUser!!.username, "", "ignore", 100);
return response.map((user) => user.following);
},
{
initialData: [],
enabled: !!username || !!activeUser
}
);
}
Loading