diff --git a/apps/admin-x-activitypub/src/api/activitypub.ts b/apps/admin-x-activitypub/src/api/activitypub.ts index 5c26cdd737..2c38b517f5 100644 --- a/apps/admin-x-activitypub/src/api/activitypub.ts +++ b/apps/admin-x-activitypub/src/api/activitypub.ts @@ -117,4 +117,14 @@ export class ActivityPubAPI { const json = await this.fetchJSON(new URL(url)); return json as Actor; } + + async like(id: string): Promise { + const url = new URL(`.ghost/activitypub/actions/like/${encodeURIComponent(id)}`, this.apiUrl); + await this.fetchJSON(url, 'POST'); + } + + async unlike(id: string): Promise { + const url = new URL(`.ghost/activitypub/actions/unlike/${encodeURIComponent(id)}`, this.apiUrl); + await this.fetchJSON(url, 'POST'); + } } diff --git a/apps/admin-x-activitypub/src/components/feed/FeedItem.tsx b/apps/admin-x-activitypub/src/components/feed/FeedItem.tsx index 5b529ac4a1..80b12bcc4a 100644 --- a/apps/admin-x-activitypub/src/components/feed/FeedItem.tsx +++ b/apps/admin-x-activitypub/src/components/feed/FeedItem.tsx @@ -4,6 +4,7 @@ import getRelativeTimestamp from '../../utils/get-relative-timestamp'; import getUsername from '../../utils/get-username'; import {ActorProperties, ObjectProperties} from '@tryghost/admin-x-framework/api/activitypub'; import {Button, Heading, Icon} from '@tryghost/admin-x-design-system'; +import {useLikeMutationForUser, useUnlikeMutationForUser} from '../../hooks/useActivityPubQueries'; export function renderFeedAttachment(object: ObjectProperties, layout: string) { let attachment; @@ -135,20 +136,16 @@ const FeedItemStats: React.FC<{ }> = ({object, likeCount, commentCount, onLikeClick, onCommentClick}) => { const [isClicked, setIsClicked] = useState(false); const [isLiked, setIsLiked] = useState(object.liked); + const likeMutation = useLikeMutationForUser('index'); + const unlikeMutation = useUnlikeMutationForUser('index'); const handleLikeClick = async () => { setIsClicked(true); - let req; if (!isLiked) { - req = fetch(`/.ghost/activitypub/actions/like/${encodeURIComponent(object.id)}`, { - method: 'POST' - }); + likeMutation.mutate(object.id); } else { - req = fetch(`/.ghost/activitypub/actions/unlike/${encodeURIComponent(object.id)}`, { - method: 'POST' - }); + unlikeMutation.mutate(object.id); } - await req; setIsLiked(!isLiked); setIsClicked(false); // Reset the animation class after request completed @@ -389,4 +386,4 @@ const FeedItem: React.FC = ({actor, object, layout, type, last}) return (<>); }; -export default FeedItem; \ No newline at end of file +export default FeedItem; diff --git a/apps/admin-x-activitypub/src/hooks/useActivityPubQueries.ts b/apps/admin-x-activitypub/src/hooks/useActivityPubQueries.ts index b1140e14b9..c1589c7161 100644 --- a/apps/admin-x-activitypub/src/hooks/useActivityPubQueries.ts +++ b/apps/admin-x-activitypub/src/hooks/useActivityPubQueries.ts @@ -1,6 +1,6 @@ import {ActivityPubAPI} from '../api/activitypub'; import {useBrowseSite} from '@tryghost/admin-x-framework/api/site'; -import {useQuery} from '@tanstack/react-query'; +import {useMutation, useQuery} from '@tanstack/react-query'; const useSiteUrl = () => { const site = useBrowseSite(); @@ -15,6 +15,26 @@ function createActivityPubAPI(handle: string, siteUrl: string) { ); } +export function useLikeMutationForUser(handle: string) { + const siteUrl = useSiteUrl(); + const api = createActivityPubAPI(handle, siteUrl); + return useMutation({ + mutationFn(id: string) { + return api.like(id); + } + }); +} + +export function useUnlikeMutationForUser(handle: string) { + const siteUrl = useSiteUrl(); + const api = createActivityPubAPI(handle, siteUrl); + return useMutation({ + mutationFn(id: string) { + return api.unlike(id); + } + }); +} + export function useFollowersCountForUser(handle: string) { const siteUrl = useSiteUrl(); const api = createActivityPubAPI(handle, siteUrl); @@ -58,4 +78,4 @@ export function useFollowersForUser(handle: string) { return api.getFollowers(); } }); -} \ No newline at end of file +}