personal web client for Bluesky
typescript
solidjs
bluesky
atcute
1import { createMemo } from 'solid-js';
2
3import type { Did } from '@atcute/lexicons';
4
5import { createProfileFollowingQuery } from '~/api/queries/profile-following';
6
7import { useParams, useTitle } from '~/lib/navigation/router';
8
9import * as Page from '~/components/page';
10import PagedList from '~/components/paged-list';
11import ProfileFollowButton from '~/components/profiles/profile-follow-button';
12import ProfileItem from '~/components/profiles/profile-item';
13import VirtualItem from '~/components/virtual-item';
14
15const ProfileFollowingPage = () => {
16 const { did } = useParams<{ did: Did }>();
17
18 const following = createProfileFollowingQuery(() => did);
19 const subject = createMemo(() => following.data?.pages[0].subject);
20
21 useTitle(() => {
22 const data = subject();
23 if (data) {
24 const handle = data.handle.toLowerCase();
25
26 return `Users followed by @${handle} — ${import.meta.env.VITE_APP_NAME}`;
27 }
28
29 return `Users followed by — ${import.meta.env.VITE_APP_NAME}`;
30 });
31
32 return (
33 <>
34 <Page.Header>
35 <Page.HeaderAccessory>
36 <Page.Back to={`/${did}`} />
37 </Page.HeaderAccessory>
38
39 <Page.Heading
40 title="Following"
41 subtitle={(() => {
42 const $subject = subject();
43 if ($subject) {
44 return '@' + $subject.handle.toLowerCase();
45 }
46 })()}
47 />
48 </Page.Header>
49
50 <PagedList
51 data={following.data?.pages.map((page) => page.profiles)}
52 error={following.error}
53 render={(item) => {
54 return (
55 <VirtualItem estimateHeight={64}>
56 <ProfileItem item={item} AsideComponent={<ProfileFollowButton profile={item} />} />
57 </VirtualItem>
58 );
59 }}
60 hasNextPage={following.hasNextPage}
61 isFetchingNextPage={following.isFetching}
62 onEndReached={() => following.fetchNextPage()}
63 />
64 </>
65 );
66};
67
68export default ProfileFollowingPage;