Something went wrong. Try again.
A Bsky-like frontend using the atprotocol natively.
Something went wrong. Try again.
3.0 kB · 96 lines
TSX
at main
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697import { useState, useCallback, useRef, useEffect } from 'react';import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';import { faShareNodes, faLink, faCheck, faArrowUpRightFromSquare,} from '@fortawesome/free-solid-svg-icons';
interface ShareButtonProps { handle: string; rkey: string; localPath: string;}
export default function ShareButton({ handle, rkey, localPath }: ShareButtonProps) { const [showMenu, setShowMenu] = useState(false); const [copiedLocal, setCopiedLocal] = useState(false); const [copiedBsky, setCopiedBsky] = useState(false); const menuRef = useRef<HTMLDivElement>(null);
const localUrl = `${window.location.origin}${localPath}`; const bskyUrl = `https://bsky.app/profile/${handle}/post/${rkey}`; const canNativeShare = typeof navigator.share === 'function';
useEffect(() => { if (!showMenu) return; const handleClick = (e: MouseEvent) => { if (menuRef.current && !menuRef.current.contains(e.target as Node)) { setShowMenu(false); } }; document.addEventListener('mousedown', handleClick); return () => document.removeEventListener('mousedown', handleClick); }, [showMenu]);
const handleCopyLocal = useCallback(() => { navigator.clipboard.writeText(localUrl).then(() => { setCopiedLocal(true); setTimeout(() => setCopiedLocal(false), 2000); }); }, [localUrl]);
const handleCopyBsky = useCallback(() => { navigator.clipboard.writeText(bskyUrl).then(() => { setCopiedBsky(true); setTimeout(() => setCopiedBsky(false), 2000); }); }, [bskyUrl]);
const handleNativeShare = useCallback(async () => { try { await navigator.share({ url: localUrl }); } catch {/* ignore*/} }, [localUrl]);
return ( <div className="share-button-wrapper" ref={menuRef}> <button className="post-action post-action--share" onClick={(e) => { e.stopPropagation(); if (canNativeShare) { handleNativeShare(); } else { setShowMenu(!showMenu); } }} title="Share" type="button" > <FontAwesomeIcon icon={faShareNodes} /> </button> {showMenu && ( <div className="share-menu" onClick={(e) => e.stopPropagation()}> <button className="share-menu-item" onClick={handleCopyLocal} type="button" > <FontAwesomeIcon icon={copiedLocal ? faCheck : faLink} /> <span>{copiedLocal ? 'Copied!' : 'Copy link'}</span> </button> <button className="share-menu-item" onClick={handleCopyBsky} type="button" > <FontAwesomeIcon icon={copiedBsky ? faCheck : faArrowUpRightFromSquare} /> <span>{copiedBsky ? 'Copied!' : 'Copy Bluesky link'}</span> </button> </div> )} </div> );}