0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-17 23:44:39 -05:00

Wired Repost button to the new ActivityPub endpoint (#22111)

ref https://linear.app/ghost/issue/AP-699

- wired the frontend to the new Create Repost API endpoint (POST
/actions/repost/:id)
- the UX/UI is yet to be worked on by Djordje
- the frontend activity-pub app is currently missing acceptance tests
altogether. A follow-up commit will set up and add a basic acceptance
test to the FE app, so that we can add tests as we ship new changes
This commit is contained in:
Sag 2025-02-05 13:38:10 +07:00 committed by GitHub
parent 6c4c94c5a8
commit d0df0e7f45
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 67 additions and 1 deletions

View file

@ -219,6 +219,11 @@ export class ActivityPubAPI {
await this.fetchJSON(url, 'POST'); await this.fetchJSON(url, 'POST');
} }
async repost(id: string): Promise<void> {
const url = new URL(`.ghost/activitypub/actions/repost/${encodeURIComponent(id)}`, this.apiUrl);
await this.fetchJSON(url, 'POST');
}
get activitiesApiUrl() { get activitiesApiUrl() {
return new URL(`.ghost/activitypub/activities/${this.handle}`, this.apiUrl); return new URL(`.ghost/activitypub/activities/${this.handle}`, this.apiUrl);
} }

View file

@ -1,7 +1,7 @@
import React, {useState} from 'react'; import React, {useState} from 'react';
import {Button} from '@tryghost/admin-x-design-system'; import {Button} from '@tryghost/admin-x-design-system';
import {ObjectProperties} from '@tryghost/admin-x-framework/api/activitypub'; import {ObjectProperties} from '@tryghost/admin-x-framework/api/activitypub';
import {useLikeMutationForUser, useUnlikeMutationForUser} from '../../hooks/useActivityPubQueries'; import {useLikeMutationForUser, useRepostMutationForUser, useUnlikeMutationForUser} from '../../hooks/useActivityPubQueries';
interface FeedItemStatsProps { interface FeedItemStatsProps {
object: ObjectProperties; object: ObjectProperties;
@ -21,8 +21,10 @@ const FeedItemStats: React.FC<FeedItemStatsProps> = ({
onCommentClick onCommentClick
}) => { }) => {
const [isLiked, setIsLiked] = useState(object.liked); const [isLiked, setIsLiked] = useState(object.liked);
const [isReposted, setIsReposted] = useState(object.reposted);
const likeMutation = useLikeMutationForUser('index'); const likeMutation = useLikeMutationForUser('index');
const unlikeMutation = useUnlikeMutationForUser('index'); const unlikeMutation = useUnlikeMutationForUser('index');
const repostMutation = useRepostMutationForUser('index');
const handleLikeClick = async (e: React.MouseEvent<HTMLElement>) => { const handleLikeClick = async (e: React.MouseEvent<HTMLElement>) => {
e.stopPropagation(); e.stopPropagation();
@ -68,6 +70,22 @@ const FeedItemStats: React.FC<FeedItemStatsProps> = ({
onCommentClick(); onCommentClick();
}} }}
/> />
<Button
className={buttonClassName}
icon='reload'
iconColorClass={`w-[18px] h-[18px] ${isReposted && 'text-green'}`}
id='repost'
size='md'
unstyled={true}
onClick={(e?: React.MouseEvent<HTMLElement>) => {
e?.stopPropagation();
if (!isReposted) {
repostMutation.mutate(object.id);
setIsReposted(true);
}
}}
/>
</div>); </div>);
}; };

View file

@ -165,6 +165,49 @@ export function useUnlikeMutationForUser(handle: string) {
}); });
} }
export function useRepostMutationForUser(handle: string) {
const queryClient = useQueryClient();
return useMutation({
async mutationFn(id: string) {
const siteUrl = await getSiteUrl();
const api = createActivityPubAPI(handle, siteUrl);
return api.repost(id);
},
onMutate: (id) => {
const previousInbox = queryClient.getQueryData([`inbox:${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: true
}
};
}
return item;
});
});
}
// This sets the context for the onError handler
return {previousInbox};
},
onError: (_err, _id, context) => {
if (context?.previousInbox) {
queryClient.setQueryData([`inbox:${handle}`], context?.previousInbox);
}
},
onSettled: () => {
queryClient.invalidateQueries({queryKey: [`reposted:${handle}`]});
}
});
}
export function useUserDataForUser(handle: string) { export function useUserDataForUser(handle: string) {
return useQuery({ return useQuery({
queryKey: [`user:${handle}`], queryKey: [`user:${handle}`],