Files
wehub-resource-sync e30e75b5d4
Code Quality / Oxlint + Oxfmt (push) Waiting to run
Code Quality / Template Sync (push) Waiting to run
Code Quality / Build Changed Packages (push) Waiting to run
Code Quality / Test Changed Packages (push) Waiting to run
Deploy Expo Example / Deploy Production (push) Waiting to run
Deploy Ink Example / Deploy Production (push) Waiting to run
Python Tests / pytest (assistant-stream, 3.10) (push) Waiting to run
Python Tests / pytest (assistant-stream, 3.12) (push) Waiting to run
Python Tests / pytest (assistant-ui-sync-server-api, 3.10) (push) Waiting to run
Python Tests / pytest (assistant-ui-sync-server-api, 3.12) (push) Waiting to run
Deploy Shadcn Registry / Deploy Production (push) Waiting to run
Template Metrics / LOC + Bundle Size (push) Waiting to run
Changesets / Create Version PR (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:40:13 +08:00

43 lines
1.1 KiB
TypeScript

"use client";
import { useEffect, useRef, useState, useCallback } from "react";
import { toast } from "sonner";
export function useMarkdownCopy(markdownUrl: string | undefined) {
const [content, setContent] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(false);
const hasFetched = useRef(false);
useEffect(() => {
hasFetched.current = false;
setContent(null);
}, []);
const prefetch = useCallback(() => {
if (!markdownUrl || hasFetched.current) return;
hasFetched.current = true;
setIsLoading(true);
fetch(markdownUrl)
.then((res) => {
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.text();
})
.then(setContent)
.catch(() => setContent(null))
.finally(() => setIsLoading(false));
}, [markdownUrl]);
const copy = useCallback(() => {
if (!content) {
toast.error("Content not loaded yet");
return;
}
navigator.clipboard
.writeText(content)
.then(() => toast.success("Copied to clipboard"))
.catch(() => toast.error("Failed to copy"));
}, [content]);
return { copy, prefetch, isLoading };
}