From ea167df109c84c071c94c860b1a2a6d5ff221e76 Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Tue, 24 Mar 2026 11:17:29 +0000 Subject: [PATCH 1/2] [#488] Add Share to X, Farcaster, and Copy Link buttons on story page Replace single ShareToFarcaster button with three-button share group: - Share to X (Twitter intent URL) - Farcaster (SDK composeCast in-app, farcaster.com intent on web) - Copy Link (clipboard with confirmation toast) Co-Authored-By: Claude Opus 4.6 (1M context) --- src/app/story/[storylineId]/page.tsx | 6 +- src/components/ShareButtons.tsx | 151 +++++++++++++++++++++++++++ 2 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 src/components/ShareButtons.tsx diff --git a/src/app/story/[storylineId]/page.tsx b/src/app/story/[storylineId]/page.tsx index 1ca218ff..aa841117 100644 --- a/src/app/story/[storylineId]/page.tsx +++ b/src/app/story/[storylineId]/page.tsx @@ -8,7 +8,7 @@ import { PriceChart } from "../../../components/PriceChart"; import { DonateWidget } from "../../../components/DonateWidget"; import { RatingWidget } from "../../../components/RatingWidget"; import { RatingSummary } from "../../../components/RatingSummary"; -import { ShareToFarcaster } from "../../../components/ShareToFarcaster"; +import { ShareButtons } from "../../../components/ShareButtons"; import { getTokenPrice, type TokenPriceInfo } from "../../../../lib/price"; import { RESERVE_LABEL, STORY_FACTORY } from "../../../../lib/contracts/constants"; import { formatPrice, formatSupply } from "../../../../lib/format"; @@ -166,7 +166,7 @@ export default async function StoryPage({ params }: { params: Params }) { {/* Share — visible on mobile (sidebar hidden) */}
- +
@@ -185,7 +185,7 @@ export default async function StoryPage({ params }: { params: Params }) { {sl.token_address && ( )} - + diff --git a/src/components/ShareButtons.tsx b/src/components/ShareButtons.tsx new file mode 100644 index 00000000..d961753d --- /dev/null +++ b/src/components/ShareButtons.tsx @@ -0,0 +1,151 @@ +"use client"; + +import { useState, useCallback } from "react"; +import { usePlatformDetection } from "../hooks/usePlatformDetection"; + +interface ShareButtonsProps { + storylineId: number; + title: string; +} + +export function ShareButtons({ storylineId, title }: ShareButtonsProps) { + const { platform } = usePlatformDetection(); + const [copied, setCopied] = useState(false); + + const appUrl = process.env.NEXT_PUBLIC_APP_URL ?? "http://localhost:3000"; + const storyUrl = `${appUrl}/story/${storylineId}`; + const shareText = `Check out "${title}" on PlotLink`; + + const handleShareX = useCallback(() => { + const fullText = `${shareText}\n${storyUrl}`; + window.open( + `https://twitter.com/intent/tweet?text=${encodeURIComponent(fullText)}`, + "_blank", + ); + }, [shareText, storyUrl]); + + const handleShareFarcaster = useCallback(async () => { + if (platform === "farcaster") { + try { + const { sdk } = await import("@farcaster/miniapp-sdk"); + await sdk.actions.composeCast({ + text: shareText, + embeds: [storyUrl], + }); + return; + } catch { + // Fall through to intent URL + } + } + const fullText = `${shareText}\n${storyUrl}`; + window.open( + `https://farcaster.com/~/compose?text=${encodeURIComponent(fullText)}`, + "_blank", + ); + }, [platform, shareText, storyUrl]); + + const handleCopy = useCallback(async () => { + try { + await navigator.clipboard.writeText(storyUrl); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } catch { + // Clipboard API may fail in some contexts + } + }, [storyUrl]); + + return ( +
+ {/* Share to X */} + + + {/* Share to Farcaster */} + + + {/* Copy Link */} + +
+ ); +} + +function XIcon() { + return ( + + + + ); +} + +function FarcasterIcon() { + return ( + + + + + + ); +} + +function CopyIcon() { + return ( + + + + + ); +} + +function CheckIcon() { + return ( + + + + ); +} From 9eb2da70bcdd5d130925b849105a41a4c2eca5fa Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Tue, 24 Mar 2026 11:19:41 +0000 Subject: [PATCH 2/2] [#488] Move share buttons below chapters in main content area Remove share from desktop sidebar and show in main story flow beneath chapter list on all screen sizes per review feedback. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/app/story/[storylineId]/page.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/app/story/[storylineId]/page.tsx b/src/app/story/[storylineId]/page.tsx index aa841117..eb74791c 100644 --- a/src/app/story/[storylineId]/page.tsx +++ b/src/app/story/[storylineId]/page.tsx @@ -164,8 +164,8 @@ export default async function StoryPage({ params }: { params: Params }) { /> )} - {/* Share — visible on mobile (sidebar hidden) */} -
+ {/* Share buttons — below chapters */} +
@@ -185,7 +185,6 @@ export default async function StoryPage({ params }: { params: Params }) { {sl.token_address && ( )} -