From b591912c748b83a72151439336d8e7402fd21d4f Mon Sep 17 00:00:00 2001 From: Fabien 'egg' O'Carroll Date: Tue, 5 Nov 2024 17:15:39 +0000 Subject: [PATCH] Updated the local state after following an account (#21509) refs https://linear.app/ghost/issue/AP-523 We want to preempt the Accept activity from our Follows, so we make the assumption that it's succeeded. What this means is that we have to update our `following`, `followingCount` as well as the fetched profile to set the `isFollowing` property. This gives a more fluid user experience when following accounts and keeps our state up to date. Accounts where the follow request has to be accepted manually, are a little trickier as we don't currently have easy access to the "requested but not accepted state" --- .../src/api/activitypub.ts | 5 ++-- .../src/hooks/useActivityPubQueries.ts | 29 ++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/apps/admin-x-activitypub/src/api/activitypub.ts b/apps/admin-x-activitypub/src/api/activitypub.ts index 1c84aadb8f..ab37d24788 100644 --- a/apps/admin-x-activitypub/src/api/activitypub.ts +++ b/apps/admin-x-activitypub/src/api/activitypub.ts @@ -234,9 +234,10 @@ export class ActivityPubAPI { }; } - async follow(username: string): Promise { + async follow(username: string): Promise { const url = new URL(`.ghost/activitypub/actions/follow/${username}`, this.apiUrl); - await this.fetchJSON(url, 'POST'); + const json = await this.fetchJSON(url, 'POST'); + return json as Actor; } async getActor(url: string): Promise { diff --git a/apps/admin-x-activitypub/src/hooks/useActivityPubQueries.ts b/apps/admin-x-activitypub/src/hooks/useActivityPubQueries.ts index 85f3481816..13fce3194b 100644 --- a/apps/admin-x-activitypub/src/hooks/useActivityPubQueries.ts +++ b/apps/admin-x-activitypub/src/hooks/useActivityPubQueries.ts @@ -282,13 +282,40 @@ export function useSearchForUser(handle: string, query: string) { } export function useFollow(handle: string, onSuccess: () => void, onError: () => void) { + const queryClient = useQueryClient(); return useMutation({ async mutationFn(username: string) { const siteUrl = await getSiteUrl(); const api = createActivityPubAPI(handle, siteUrl); return api.follow(username); }, - onSuccess, + onSuccess(followedActor, fullHandle) { + queryClient.setQueryData([`profile:${fullHandle}`], (currentProfile: unknown) => { + if (!currentProfile) { + return currentProfile; + } + return { + ...currentProfile, + isFollowing: true + }; + }); + + queryClient.setQueryData(['following:index'], (currentFollowing?: unknown[]) => { + if (!currentFollowing) { + return currentFollowing; + } + return [followedActor].concat(currentFollowing); + }); + + queryClient.setQueryData(['followingCount:index'], (currentFollowingCount?: number) => { + if (!currentFollowingCount) { + return 1; + } + return currentFollowingCount + 1; + }); + + onSuccess(); + }, onError }); }