Files
spsays-training/components/social/share-post-provider.tsx
T

70 lines
2.0 KiB
TypeScript

"use client";
/**
* SharePostProvider — mounts a single global SharePostSheet that any
* component in the tree can summon via `useSharePost().openShareSheet(post)`.
*
* The sheet itself is a heavy modal/drawer that loads URLs, pre-fetches
* images for native share, etc. — we don't want every caller to mount
* its own copy. Mounting once at the root and triggering via context
* keeps state isolated and makes "Share" a one-liner anywhere downstream:
*
* const { openShareSheet } = useSharePost();
* openShareSheet(newlyCreatedPost);
*
* Used today by compose-post.tsx (toast after a successful post create
* offers a "Share" action that opens the sheet for the new post).
* Future surfaces like profile cards can call into the same hook.
*/
import {
createContext,
useCallback,
useContext,
useState,
} from "react";
import type { Post } from "@/lib/social";
import { useMediaQuery } from "@/components/selection-toolbar/shared";
import { SharePostSheet } from "./share-post-sheet";
type SharePostContextValue = {
openShareSheet: (post: Post) => void;
};
const SharePostContext = createContext<SharePostContextValue | null>(null);
export function useSharePost(): SharePostContextValue {
const v = useContext(SharePostContext);
if (!v) {
throw new Error("useSharePost must be used inside <SharePostProvider>");
}
return v;
}
export function SharePostProvider({
children,
}: {
children: React.ReactNode;
}) {
const [activePost, setActivePost] = useState<Post | null>(null);
const isMobile = useMediaQuery("(max-width: 767px)");
const openShareSheet = useCallback((post: Post) => {
setActivePost(post);
}, []);
return (
<SharePostContext.Provider value={{ openShareSheet }}>
{children}
{activePost ? (
<SharePostSheet
open={true}
onClose={() => setActivePost(null)}
post={activePost}
isMobile={isMobile}
/>
) : null}
</SharePostContext.Provider>
);
}