@@ -19,10 +19,13 @@ export function CopyMarkdownButton({pathname}: CopyMarkdownButtonProps) {
1919 const [ error , setError ] = useState ( false ) ;
2020 const [ isOpen , setIsOpen ] = useState ( false ) ;
2121 const [ isMounted , setIsMounted ] = useState ( false ) ;
22+ const [ prefetchedContent , setPrefetchedContent ] = useState < string | null > ( null ) ;
2223 const buttonRef = useRef < HTMLDivElement > ( null ) ;
2324 const dropdownRef = useRef < HTMLDivElement > ( null ) ;
2425 const { emit} = usePlausibleEvent ( ) ;
2526
27+
28+
2629 const copyMarkdownToClipboard = async ( ) => {
2730 setIsLoading ( true ) ;
2831 setCopied ( false ) ;
@@ -32,14 +35,22 @@ export function CopyMarkdownButton({pathname}: CopyMarkdownButtonProps) {
3235 emit ( 'Copy Page' , { props : { page : pathname , source : 'copy_button' } } ) ;
3336
3437 try {
35- // This doesn't work on local development since we need the generated markdown
36- // files, and we need to be aware of the origin since we have two different origins.
37- const response = await fetch ( `${ window . location . origin } /${ pathname } .md` ) ;
38- if ( ! response . ok ) {
39- throw new Error ( `Failed to fetch markdown content: ${ response . status } ` ) ;
38+ let content : string ;
39+
40+ // Use pre-fetched content if available (for mobile)
41+ if ( prefetchedContent ) {
42+ content = prefetchedContent ;
43+ } else {
44+ // This doesn't work on local development since we need the generated markdown
45+ // files, and we need to be aware of the origin since we have two different origins.
46+ const response = await fetch ( `${ window . location . origin } /${ pathname } .md` ) ;
47+ if ( ! response . ok ) {
48+ throw new Error ( `Failed to fetch markdown content: ${ response . status } ` ) ;
49+ }
50+ content = await response . text ( ) ;
4051 }
4152
42- await navigator . clipboard . writeText ( await response . text ( ) ) ;
53+ await navigator . clipboard . writeText ( content ) ;
4354 setCopied ( true ) ;
4455 setTimeout ( ( ) => setCopied ( false ) , 2000 ) ;
4556 } catch ( err ) {
@@ -82,6 +93,23 @@ export function CopyMarkdownButton({pathname}: CopyMarkdownButtonProps) {
8293 } ;
8394 } , [ ] ) ;
8495
96+ // Pre-fetch markdown content to avoid losing user gesture context
97+ useEffect ( ( ) => {
98+ if ( ! prefetchedContent ) {
99+ const prefetchContent = async ( ) => {
100+ try {
101+ const response = await fetch ( `${ window . location . origin } /${ pathname } .md` ) ;
102+ if ( response . ok ) {
103+ setPrefetchedContent ( await response . text ( ) ) ;
104+ }
105+ } catch ( err ) {
106+ // Silently fail - we'll fall back to regular fetch on click
107+ }
108+ } ;
109+ prefetchContent ( ) ;
110+ }
111+ } , [ pathname , prefetchedContent ] ) ;
112+
85113 const getDropdownPosition = ( ) => {
86114 if ( ! buttonRef . current ) return { top : 0 , left : 0 } ;
87115 const rect = buttonRef . current . getBoundingClientRect ( ) ;
0 commit comments