From a0b4a26ad398137e13c35f3fe0dad99154537d91 Mon Sep 17 00:00:00 2001 From: Mohamed Bassem Date: Tue, 30 Dec 2025 12:52:50 +0200 Subject: feat: 2025 wrapped (#2322) * feat: 2025 wrapped * don't add wrapped for new users --- apps/web/components/wrapped/ShareButton.tsx | 92 +++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 apps/web/components/wrapped/ShareButton.tsx (limited to 'apps/web/components/wrapped/ShareButton.tsx') diff --git a/apps/web/components/wrapped/ShareButton.tsx b/apps/web/components/wrapped/ShareButton.tsx new file mode 100644 index 00000000..048cafea --- /dev/null +++ b/apps/web/components/wrapped/ShareButton.tsx @@ -0,0 +1,92 @@ +"use client"; + +import { RefObject, useState } from "react"; +import { Button } from "@/components/ui/button"; +import { Download, Loader2, Share2 } from "lucide-react"; +import { domToPng } from "modern-screenshot"; + +interface ShareButtonProps { + contentRef: RefObject; + fileName?: string; +} + +export function ShareButton({ + contentRef, + fileName = "karakeep-wrapped-2025.png", +}: ShareButtonProps) { + const [isGenerating, setIsGenerating] = useState(false); + + const handleShare = async () => { + if (!contentRef.current) return; + + setIsGenerating(true); + + try { + // Capture the content as PNG data URL + const dataUrl = await domToPng(contentRef.current, { + scale: 2, // Higher resolution + quality: 1, + debug: false, + width: contentRef.current.scrollWidth, // Capture full width + height: contentRef.current.scrollHeight, // Capture full height including scrolled content + drawImageInterval: 100, // Add delay for rendering + }); + + // Convert data URL to blob + const response = await fetch(dataUrl); + const blob = await response.blob(); + + // Try native share API first (works well on mobile) + if ( + typeof navigator.share !== "undefined" && + typeof navigator.canShare !== "undefined" + ) { + const file = new File([blob], fileName, { type: "image/png" }); + if (navigator.canShare({ files: [file] })) { + await navigator.share({ + files: [file], + title: "My 2025 Karakeep Wrapped", + text: "Check out my 2025 Karakeep Wrapped!", + }); + return; + } + } + + // Fallback: download the image + const a = document.createElement("a"); + a.href = dataUrl; + a.download = fileName; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + } catch (error) { + console.error("Failed to capture or share image:", error); + } finally { + setIsGenerating(false); + } + }; + + const isNativeShareAvailable = + typeof navigator.share !== "undefined" && + typeof navigator.canShare !== "undefined"; + + return ( + + ); +} -- cgit v1.2.3-70-g09d2