0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-06 22:40:14 -05:00

Refactored like and unlike API requests

We don't want our components littered with fetch calls, as it makes it
difficult to test. Instead we move our http api code into the ActivityPubAPI,
giving us a central place for adding authentication and tests in the future.

We also make sure that the components use a react query wrapped call - so that
we can take advantage of the query invalidation.
This commit is contained in:
Fabien O'Carroll 2024-09-06 11:42:14 +07:00 committed by Fabien 'egg' O'Carroll
parent ee514a397c
commit c0386b6c69
3 changed files with 38 additions and 11 deletions

View file

@ -117,4 +117,14 @@ export class ActivityPubAPI {
const json = await this.fetchJSON(new URL(url)); const json = await this.fetchJSON(new URL(url));
return json as Actor; return json as Actor;
} }
async like(id: string): Promise<void> {
const url = new URL(`.ghost/activitypub/actions/like/${encodeURIComponent(id)}`, this.apiUrl);
await this.fetchJSON(url, 'POST');
}
async unlike(id: string): Promise<void> {
const url = new URL(`.ghost/activitypub/actions/unlike/${encodeURIComponent(id)}`, this.apiUrl);
await this.fetchJSON(url, 'POST');
}
} }

View file

@ -4,6 +4,7 @@ import getRelativeTimestamp from '../../utils/get-relative-timestamp';
import getUsername from '../../utils/get-username'; import getUsername from '../../utils/get-username';
import {ActorProperties, ObjectProperties} from '@tryghost/admin-x-framework/api/activitypub'; import {ActorProperties, ObjectProperties} from '@tryghost/admin-x-framework/api/activitypub';
import {Button, Heading, Icon} from '@tryghost/admin-x-design-system'; import {Button, Heading, Icon} from '@tryghost/admin-x-design-system';
import {useLikeMutationForUser, useUnlikeMutationForUser} from '../../hooks/useActivityPubQueries';
export function renderFeedAttachment(object: ObjectProperties, layout: string) { export function renderFeedAttachment(object: ObjectProperties, layout: string) {
let attachment; let attachment;
@ -135,20 +136,16 @@ const FeedItemStats: React.FC<{
}> = ({object, likeCount, commentCount, onLikeClick, onCommentClick}) => { }> = ({object, likeCount, commentCount, onLikeClick, onCommentClick}) => {
const [isClicked, setIsClicked] = useState(false); const [isClicked, setIsClicked] = useState(false);
const [isLiked, setIsLiked] = useState(object.liked); const [isLiked, setIsLiked] = useState(object.liked);
const likeMutation = useLikeMutationForUser('index');
const unlikeMutation = useUnlikeMutationForUser('index');
const handleLikeClick = async () => { const handleLikeClick = async () => {
setIsClicked(true); setIsClicked(true);
let req;
if (!isLiked) { if (!isLiked) {
req = fetch(`/.ghost/activitypub/actions/like/${encodeURIComponent(object.id)}`, { likeMutation.mutate(object.id);
method: 'POST'
});
} else { } else {
req = fetch(`/.ghost/activitypub/actions/unlike/${encodeURIComponent(object.id)}`, { unlikeMutation.mutate(object.id);
method: 'POST'
});
} }
await req;
setIsLiked(!isLiked); setIsLiked(!isLiked);
setIsClicked(false); // Reset the animation class after request completed setIsClicked(false); // Reset the animation class after request completed

View file

@ -1,6 +1,6 @@
import {ActivityPubAPI} from '../api/activitypub'; import {ActivityPubAPI} from '../api/activitypub';
import {useBrowseSite} from '@tryghost/admin-x-framework/api/site'; 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 useSiteUrl = () => {
const site = useBrowseSite(); 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) { export function useFollowersCountForUser(handle: string) {
const siteUrl = useSiteUrl(); const siteUrl = useSiteUrl();
const api = createActivityPubAPI(handle, siteUrl); const api = createActivityPubAPI(handle, siteUrl);