mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-04-08 02:52:39 -05:00
Wired 'Undo Repost' action with the backend API endpoint (#22124)
ref https://linear.app/ghost/issue/AP-699 - when the user clicks again on the Repost icon, we undo the Repost action, by calling the corresponding API endpoint `POST /actions/derepost/:id` - UX/UI and copy are still WIP - at this stage, we're still missing acceptance tests in the frontend app. We will be starting acceptance testing in a separate commit
This commit is contained in:
parent
c755df1e2f
commit
2bd95b3efc
3 changed files with 65 additions and 3 deletions
|
@ -224,6 +224,11 @@ export class ActivityPubAPI {
|
|||
await this.fetchJSON(url, 'POST');
|
||||
}
|
||||
|
||||
async derepost(id: string): Promise<void> {
|
||||
const url = new URL(`.ghost/activitypub/actions/derepost/${encodeURIComponent(id)}`, this.apiUrl);
|
||||
await this.fetchJSON(url, 'POST');
|
||||
}
|
||||
|
||||
get activitiesApiUrl() {
|
||||
return new URL(`.ghost/activitypub/activities/${this.handle}`, this.apiUrl);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, {useState} from 'react';
|
||||
import {Button} from '@tryghost/admin-x-design-system';
|
||||
import {ObjectProperties} from '@tryghost/admin-x-framework/api/activitypub';
|
||||
import {useLikeMutationForUser, useRepostMutationForUser, useUnlikeMutationForUser} from '../../hooks/useActivityPubQueries';
|
||||
import {useDerepostMutationForUser, useLikeMutationForUser, useRepostMutationForUser, useUnlikeMutationForUser} from '../../hooks/useActivityPubQueries';
|
||||
|
||||
interface FeedItemStatsProps {
|
||||
object: ObjectProperties;
|
||||
|
@ -27,6 +27,7 @@ const FeedItemStats: React.FC<FeedItemStatsProps> = ({
|
|||
const likeMutation = useLikeMutationForUser('index');
|
||||
const unlikeMutation = useUnlikeMutationForUser('index');
|
||||
const repostMutation = useRepostMutationForUser('index');
|
||||
const derepostMutation = useDerepostMutationForUser('index');
|
||||
|
||||
const handleLikeClick = async (e: React.MouseEvent<HTMLElement>) => {
|
||||
e.stopPropagation();
|
||||
|
@ -82,15 +83,18 @@ const FeedItemStats: React.FC<FeedItemStatsProps> = ({
|
|||
id='repost'
|
||||
label={new Intl.NumberFormat().format(repostCount)}
|
||||
size='md'
|
||||
title='Repost'
|
||||
title={`${isReposted ? 'Undo repost' : 'Repost'}`}
|
||||
unstyled={true}
|
||||
onClick={(e?: React.MouseEvent<HTMLElement>) => {
|
||||
e?.stopPropagation();
|
||||
|
||||
if (!isReposted) {
|
||||
repostMutation.mutate(object.id);
|
||||
setIsReposted(true);
|
||||
} else {
|
||||
derepostMutation.mutate(object.id);
|
||||
}
|
||||
|
||||
setIsReposted(!isReposted);
|
||||
}}
|
||||
/>
|
||||
</div>);
|
||||
|
|
|
@ -208,6 +208,59 @@ export function useRepostMutationForUser(handle: string) {
|
|||
});
|
||||
}
|
||||
|
||||
export function useDerepostMutationForUser(handle: string) {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
async mutationFn(id: string) {
|
||||
const siteUrl = await getSiteUrl();
|
||||
const api = createActivityPubAPI(handle, siteUrl);
|
||||
|
||||
return api.derepost(id);
|
||||
},
|
||||
onMutate: async (id) => {
|
||||
const previousInbox = queryClient.getQueryData([`inbox:${handle}`]);
|
||||
const previousReposted = queryClient.getQueryData([`reposted:${handle}`]);
|
||||
|
||||
if (previousInbox) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
queryClient.setQueryData([`inbox:${handle}`], (old?: any[]) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return old?.map((item: any) => {
|
||||
if (item.object.id === id) {
|
||||
return {
|
||||
...item,
|
||||
object: {
|
||||
...item.object,
|
||||
reposted: false
|
||||
}
|
||||
};
|
||||
}
|
||||
return item;
|
||||
});
|
||||
});
|
||||
}
|
||||
if (previousReposted) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
queryClient.setQueryData([`reposted:${handle}`], (old?: any[]) => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return old?.filter((item: any) => item.object.id !== id);
|
||||
});
|
||||
}
|
||||
|
||||
// This sets the context for the onError handler
|
||||
return {previousInbox, previousReposted};
|
||||
},
|
||||
onError: (_err, _id, context) => {
|
||||
if (context?.previousInbox) {
|
||||
queryClient.setQueryData([`inbox:${handle}`], context?.previousInbox);
|
||||
}
|
||||
if (context?.previousReposted) {
|
||||
queryClient.setQueryData([`reposted:${handle}`], context?.previousReposted);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function useUserDataForUser(handle: string) {
|
||||
return useQuery({
|
||||
queryKey: [`user:${handle}`],
|
||||
|
|
Loading…
Add table
Reference in a new issue