Added support for listing likes

We can reuse the FeedItem here, and I've defaulted to the 'feed' layout - I'm
not 100% sure if that's correct.

The liked collection doesn't have `liked` properties, and it's a little tricky
to add on the backend with how fedify works - so for now we hardcode the
`liked` property to true, which we can do because we're rendering all of the
liked content!
This commit is contained in:
Fabien O'Carroll 2024-09-06 11:46:22 +07:00 committed by Fabien 'egg' O'Carroll
parent c0386b6c69
commit bd66efa70a
3 changed files with 61 additions and 6 deletions

View File

@ -118,6 +118,21 @@ export class ActivityPubAPI {
return json as Actor;
}
get likedApiUrl() {
return new URL(`.ghost/activitypub/liked/${this.handle}`, this.apiUrl);
}
async getLiked() {
const json = await this.fetchJSON(this.likedApiUrl);
if (json === null) {
return [];
}
if ('orderedItems' in json) {
return Array.isArray(json.orderedItems) ? json.orderedItems : [json.orderedItems];
}
return [];
}
async like(id: string): Promise<void> {
const url = new URL(`.ghost/activitypub/actions/like/${encodeURIComponent(id)}`, this.apiUrl);
await this.fetchJSON(url, 'POST');

View File

@ -1,10 +1,11 @@
import APAvatar from './global/APAvatar';
import ActivityItem from './activities/ActivityItem';
import FeedItem from './feed/FeedItem';
import MainNavigation from './navigation/MainNavigation';
import React, {useState} from 'react';
import getUsername from '../utils/get-username';
import {Button, Heading, List, NoValueLabel, Tab, TabView} from '@tryghost/admin-x-design-system';
import {useFollowersCountForUser, useFollowersForUser, useFollowingCountForUser, useFollowingForUser} from '../hooks/useActivityPubQueries';
import {useFollowersCountForUser, useFollowersForUser, useFollowingCountForUser, useFollowingForUser, useLikedForUser} from '../hooks/useActivityPubQueries';
interface ProfileProps {}
@ -13,11 +14,14 @@ const Profile: React.FC<ProfileProps> = ({}) => {
const {data: followingCount = 0} = useFollowingCountForUser('index');
const {data: following = []} = useFollowingForUser('index');
const {data: followers = []} = useFollowersForUser('index');
const {data: liked = []} = useLikedForUser('index');
type ProfileTab = 'posts' | 'likes' | 'following' | 'followers';
const [selectedTab, setSelectedTab] = useState<ProfileTab>('posts');
const layout = 'feed';
const tabs = [
{
id: 'posts',
@ -30,10 +34,35 @@ const Profile: React.FC<ProfileProps> = ({}) => {
{
id: 'likes',
title: 'Likes',
contents: (<div><NoValueLabel icon='heart'>
You haven&apos;t liked anything yet.
</NoValueLabel></div>),
counter: 27
contents: (
<div>
{liked.length === 0 ? (
<NoValueLabel icon='heart'>
You haven&apos;t liked anything yet.
</NoValueLabel>
) : (
<ul className='mx-auto flex max-w-[640px] flex-col'>
{liked.map((activity, index) => (
<li
key={activity.id}
data-test-view-article
>
<FeedItem
actor={activity.actor}
layout={layout}
object={Object.assign({}, activity.object, {liked: true})}
type={activity.type}
/>
{index < liked.length - 1 && (
<div className="h-px w-full bg-grey-200"></div>
)}
</li>
))}
</ul>
)}
</div>
),
counter: liked.length
},
{
id: 'following',
@ -124,4 +153,4 @@ const Profile: React.FC<ProfileProps> = ({}) => {
);
};
export default Profile;
export default Profile;

View File

@ -15,6 +15,17 @@ function createActivityPubAPI(handle: string, siteUrl: string) {
);
}
export function useLikedForUser(handle: string) {
const siteUrl = useSiteUrl();
const api = createActivityPubAPI(handle, siteUrl);
return useQuery({
queryKey: [`liked:${handle}`],
async queryFn() {
return api.getLiked();
}
});
}
export function useLikeMutationForUser(handle: string) {
const siteUrl = useSiteUrl();
const api = createActivityPubAPI(handle, siteUrl);