Skip to content

Commit f83faee

Browse files
committed
Merge branch 'preview'
2 parents 7077813 + 5bc7df1 commit f83faee

File tree

17 files changed

+174
-640
lines changed

17 files changed

+174
-640
lines changed

package-lock.json

Lines changed: 4 additions & 523 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
"react-dropzone": "^14.2.3",
4141
"react-hot-toast": "^2.4.1",
4242
"react-intersection-observer": "^9.5.3",
43-
"sharp": "^0.33.1",
4443
"tailwindcss-animate": "^1.0.7",
4544
"tinyld": "^1.3.4",
4645
"use-clipboard-copy": "^0.2.0",

src/app/providers/query.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export default function QueryProvider({
1818
// With SSR, we usually want to set some default staleTime
1919
// above 0 to avoid refetching immediately on the client
2020
staleTime: 60 * 1000,
21+
retry: false,
2122
},
2223
},
2324
})

src/components/contentDisplay/searchList/PostsSearchList.tsx

Lines changed: 0 additions & 49 deletions
This file was deleted.

src/components/contentDisplay/searchList/SearchList.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
"use client";
22

33
import { useState } from "react";
4-
import UsersSearchList from "./UsersSearchList";
5-
import PostsSearchList from "./PostsSearchList";
4+
import PostSearchContainer from "@/containers/search/PostSearchContainer";
5+
import UserSearchContainer from "@/containers/search/UserSearchContainer";
66

77
interface Props {
88
query: string;
@@ -47,8 +47,8 @@ export default function SearchList(props: Props) {
4747
</button>
4848
</div>
4949

50-
{currenTab === "posts" && <PostsSearchList query={query} />}
51-
{currenTab === "users" && <UsersSearchList query={query} />}
50+
{currenTab === "posts" && <PostSearchContainer query={query} />}
51+
{currenTab === "users" && <UserSearchContainer query={query} />}
5252
</section>
5353
);
5454
}

src/components/dataDisplay/postEmbed/BlockedEmbed.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,28 @@ import { Icon } from "@iconify/react/dist/iconify.js";
22

33
interface Props {
44
depth: number;
5+
isReply?: boolean;
56
}
67

78
export default function BlockedEmbed(props: Props) {
8-
const { depth } = props;
9+
const { depth = 0, isReply = false } = props;
10+
const replyStyle = isReply && "mb-6";
911

1012
return (
1113
<>
1214
{depth < 1 && (
13-
<div className="p-3 mt-2 border rounded-xl bg-white">
15+
<div
16+
className={`relative p-3 border rounded-xl bg-white ${replyStyle}`}
17+
>
1418
<div className="flex gap-2">
1519
<Icon icon="fluent:shield-error-24-filled" className="text-2xl" />
1620
<span>
1721
Post is from a blocked user or someone who has blocked you.
1822
</span>
1923
</div>
24+
{isReply && (
25+
<div className="absolute left-6 top-12 h-full border-l-2" />
26+
)}
2027
</div>
2128
)}
2229
</>

src/components/dataDisplay/postEmbed/NotFoundEmbed.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,26 @@ import { Icon } from "@iconify/react/dist/iconify.js";
22

33
interface Props {
44
depth: number;
5+
isReply?: boolean;
56
}
67

78
export default function NotFoundEmbed(props: Props) {
8-
const { depth } = props;
9+
const { depth = 0, isReply = false } = props;
10+
const replyStyle = isReply && "mb-6";
911

1012
return (
1113
<>
1214
{depth < 1 && (
13-
<div className="p-3 mt-2 border rounded-xl bg-white">
15+
<div
16+
className={`relative p-3 border rounded-xl bg-white ${replyStyle}`}
17+
>
1418
<div className="flex gap-2">
1519
<Icon icon="ep:warning-filled" className="text-2xl" />
16-
<span>Post cannot be found</span>
20+
<span>Deleted post</span>
1721
</div>
22+
{isReply && (
23+
<div className="absolute left-6 top-12 h-full border-l-2" />
24+
)}
1825
</div>
1926
)}
2027
</>

src/components/dataDisplay/postEmbed/RecordEmbed.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,16 @@ export default function RecordEmbed(props: Props) {
2323

2424
return (
2525
<article className="flex flex-col rounded-xl">
26-
{isBlocked && <BlockedEmbed depth={depth} />}
27-
{notFound && <NotFoundEmbed depth={depth} />}
26+
{isBlocked && (
27+
<div className="mt-2">
28+
<BlockedEmbed depth={depth} />
29+
</div>
30+
)}
31+
{notFound && (
32+
<div className="mt-2">
33+
<NotFoundEmbed depth={depth} />
34+
</div>
35+
)}
2836
{media && <PostEmbed content={media} depth={depth + 1} />}
2937
{isViewable && depth < 1 && (
3038
<div

src/containers/FeedContainer.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export default function FeedContainer(props: Props) {
2828
isFetchingFeedNextPage,
2929
feedHasNextPage,
3030
} = useFeed(feed);
31+
3132
const isEmpty =
3233
!isFetchingFeed &&
3334
!isFetchingFeedNextPage &&
@@ -42,7 +43,7 @@ export default function FeedContainer(props: Props) {
4243
<Refetch
4344
onRefetch={() => {
4445
window.scrollTo({ top: 0, behavior: "smooth" });
45-
refetchFeed();
46+
refetchFeed();
4647
}}
4748
/>
4849
<ComposeButton mode="float" />
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { searchPosts } from "@/lib/api/bsky/actor";
2+
import useAgent from "@/lib/hooks/bsky/useAgent";
3+
import { useInfiniteQuery } from "@tanstack/react-query";
4+
import { Fragment, useEffect } from "react";
5+
import EndOfFeed from "@/components/feedback/endOfFeed/EndOfFeed";
6+
import FeedAlert from "@/components/feedback/feedAlert/FeedAlert";
7+
import FeedPostSkeleton from "@/components/contentDisplay/feedPost/FeedPostSkeleton";
8+
import SearchPost from "@/components/contentDisplay/searchPost/SearchPost";
9+
import { Icon } from "@iconify/react/dist/iconify.js";
10+
import { useInView } from "react-intersection-observer";
11+
12+
interface Props {
13+
query: string;
14+
}
15+
16+
export default function PostSearchContainer(props: Props) {
17+
const { query } = props;
18+
const decoded = decodeURIComponent(query);
19+
const agent = useAgent();
20+
21+
const {
22+
status,
23+
data: posts,
24+
error,
25+
isLoading,
26+
isFetching,
27+
isFetchingNextPage,
28+
hasNextPage,
29+
fetchNextPage,
30+
} = useInfiniteQuery({
31+
queryKey: ["searchPosts", query],
32+
queryFn: ({ pageParam }) => searchPosts(decoded, pageParam, agent),
33+
initialPageParam: "",
34+
getNextPageParam: (lastPage) => lastPage?.cursor,
35+
});
36+
37+
const isEmpty =
38+
!isFetching && !isFetchingNextPage && posts?.pages[0]?.posts?.length === 0;
39+
40+
const { ref: observerRef, inView } = useInView();
41+
42+
useEffect(() => {
43+
if (inView) {
44+
fetchNextPage();
45+
}
46+
}, [fetchNextPage, inView]);
47+
48+
return (
49+
<div>
50+
<section className="flex flex-col">
51+
{posts?.pages
52+
.flatMap((page) => page?.posts)
53+
.map((post, i) => (
54+
<Fragment key={i}>
55+
{post && <SearchPost key={i} post={post} />}
56+
</Fragment>
57+
))}
58+
</section>
59+
{isEmpty && !hasNextPage && (
60+
<div className="mx-3 md:mx-0 border-t">
61+
<FeedAlert variant="empty" message="No posts found" />
62+
</div>
63+
)}
64+
{isFetching && !isFetchingNextPage && <FeedPostSkeleton />}
65+
{isFetchingNextPage && (
66+
<section className="flex flex-1 justify-center mt-3">
67+
<Icon icon="eos-icons:loading" className="text-xl" />
68+
</section>
69+
)}
70+
{error && (
71+
<FeedAlert variant="badResponse" message="Something went wrong" />
72+
)}
73+
{!isEmpty &&
74+
!error &&
75+
!isFetching &&
76+
!hasNextPage &&
77+
!isFetchingNextPage && <EndOfFeed />}
78+
<div ref={observerRef} />
79+
</div>
80+
);
81+
}

0 commit comments

Comments
 (0)