diff --git a/bun.lockb b/bun.lockb index 1491662a..202b0b47 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 70c25964..ce4c3e68 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "web" ], "dependencies": { - "jazz-nodejs": "^0.7.34", + "jazz-nodejs": "0.7.35-unique.2", "react-icons": "^5.3.0" }, "devDependencies": { diff --git a/web/components/routes/topics/detail/TopicDetailRoute.tsx b/web/components/routes/topics/detail/TopicDetailRoute.tsx index 6843b7c5..e4faf368 100644 --- a/web/components/routes/topics/detail/TopicDetailRoute.tsx +++ b/web/components/routes/topics/detail/TopicDetailRoute.tsx @@ -1,6 +1,6 @@ "use client" -import React from "react" +import React, { useRef } from "react" import { TopicDetailHeader } from "./Header" import { TopicSections } from "./partials/topic-sections" import { useLinkNavigation } from "./use-link-navigation" @@ -16,8 +16,10 @@ export const openPopoverForIdAtom = atom(null) export function TopicDetailRoute({ topicName }: TopicDetailRouteProps) { const { me } = useAccount({ root: { personalLinks: [] } }) - const { topic, allLinks } = useTopicData(topicName) - const { activeIndex, setActiveIndex, containerRef, linkRefs } = useLinkNavigation(allLinks) + const { topic } = useTopicData(topicName, me) + // const { activeIndex, setActiveIndex, containerRef, linkRefs } = useLinkNavigation(allLinks) + const linksRefDummy = useRef<(HTMLLIElement | null)[]>([]) + const containerRefDummy = useRef(null) if (!topic || !me) { return null @@ -29,10 +31,10 @@ export function TopicDetailRoute({ topicName }: TopicDetailRouteProps) { {}} + linkRefs={linksRefDummy} + containerRef={containerRefDummy} me={me} personalLinks={me.root.personalLinks} /> diff --git a/web/components/routes/topics/detail/partials/section.tsx b/web/components/routes/topics/detail/partials/section.tsx index 4a711d84..23dbc865 100644 --- a/web/components/routes/topics/detail/partials/section.tsx +++ b/web/components/routes/topics/detail/partials/section.tsx @@ -1,6 +1,8 @@ -import React from "react" +import React, { useCallback, useEffect, useMemo, useRef, useState } from "react" import { LinkItem } from "./link-item" import { LaAccount, PersonalLinkLists, Section as SectionSchema, Topic, UserRoot } from "@/lib/schema" +import { Skeleton } from "@/components/ui/skeleton" +import { Loader2 } from "lucide-react" interface SectionProps { topic: Topic @@ -27,6 +29,12 @@ export function Section({ me, personalLinks }: SectionProps) { + const [nLinksToLoad, setNLinksToLoad] = useState(10); + + const linksToLoad = useMemo(() => { + return section.links?.slice(0, nLinksToLoad) + }, [section.links, nLinksToLoad]) + return (
@@ -35,9 +43,9 @@ export function Section({
- {section.links?.map( + {linksToLoad?.map( (link, index) => - link?.url && ( + link?.url ? ( + ) : ( + ) )} + {section.links?.length && section.links?.length > nLinksToLoad && ( + setNLinksToLoad(n => n + 10)} /> + )}
) } + +const LoadMoreSpinner = ({ onLoadMore }: { onLoadMore: () => void }) => { + const spinnerRef = useRef(null) + + const handleIntersection = useCallback( + (entries: IntersectionObserverEntry[]) => { + const [entry] = entries + if (entry.isIntersecting) { + onLoadMore() + } + }, + [onLoadMore] + ) + + useEffect(() => { + const observer = new IntersectionObserver(handleIntersection, { + root: null, + rootMargin: "0px", + threshold: 1.0, + }) + + if (spinnerRef.current) { + observer.observe(spinnerRef.current) + } + + return () => { + if (spinnerRef.current) { + observer.unobserve(spinnerRef.current) + } + } + }, [handleIntersection]) + + return ( +
+ +
+ ) +} diff --git a/web/hooks/use-topic-data.ts b/web/hooks/use-topic-data.ts index 80b8efd9..bfdc10f2 100644 --- a/web/hooks/use-topic-data.ts +++ b/web/hooks/use-topic-data.ts @@ -1,29 +1,15 @@ import { useMemo } from "react" import { useCoState } from "@/lib/providers/jazz-provider" import { PublicGlobalGroup } from "@/lib/schema/master/public-group" -import { ID } from "jazz-tools" -import { Link } from "@/lib/schema" +import { Account, ID } from "jazz-tools" +import { Link, Topic } from "@/lib/schema" const GLOBAL_GROUP_ID = process.env.NEXT_PUBLIC_JAZZ_GLOBAL_GROUP as ID -export function useTopicData(topicName: string) { - const group = useCoState(PublicGlobalGroup, GLOBAL_GROUP_ID, { - root: { topics: [] } - }) +export function useTopicData(topicName: string, me: Account | undefined) { + const topicID = useMemo(() => me && Topic.findUnique({topicName}, GLOBAL_GROUP_ID, me), [topicName, me]) - // const topic = useCoState(Topic, "co_zS3TH4Lkj5MK9GEehinxhjjNTxB" as ID, {}) - const topic = useMemo( - () => group?.root.topics.find(topic => topic?.name === topicName), - [group?.root.topics, topicName] - ) + const topic = useCoState(Topic, topicID, {latestGlobalGuide: {sections: [{links: []}]}}) - const allLinks = useMemo(() => { - if (!topic?.latestGlobalGuide?.sections) return [] - - return topic.latestGlobalGuide.sections.flatMap( - section => section?.links?.filter((link): link is Link => !!link?.url) ?? [] - ) - }, [topic?.latestGlobalGuide?.sections]) - - return { topic, allLinks } + return { topic } } diff --git a/web/lib/schema/index.ts b/web/lib/schema/index.ts index 0528647f..c0a29f54 100644 --- a/web/lib/schema/index.ts +++ b/web/lib/schema/index.ts @@ -39,6 +39,8 @@ export class LaAccount extends Account { // so just do default profile create provided by jazz-tools super.migrate(creationProps) + console.log("In migration", this._refs.root, creationProps) + if (!this._refs.root && creationProps) { this.root = UserRoot.create( { diff --git a/web/package.json b/web/package.json index 1a786c21..3b6c7811 100644 --- a/web/package.json +++ b/web/package.json @@ -67,9 +67,9 @@ "cmdk": "^1.0.0", "date-fns": "^3.6.0", "framer-motion": "^11.3.31", - "jazz-react": "0.7.35-new-auth.1", + "jazz-react": "0.7.35-unique.2", "jazz-react-auth-clerk": "0.7.33-new-auth.1", - "jazz-tools": "0.7.35-new-auth.0", + "jazz-tools": "0.7.35-unique.2", "jotai": "^2.9.3", "lowlight": "^3.1.0", "lucide-react": "^0.429.0",