refactor: 提取 useShare hook,统一分享和剪贴板逻辑

新增 useShare(Web Share API + clipboard fallback),
消除 QrInviteModal、BlindboxRoomPage、ShareCardModal 三处重复的分享代码。
This commit is contained in:
2026-02-26 19:25:44 +08:00
parent 1229bb849b
commit c9e20d4c95
4 changed files with 70 additions and 64 deletions
+10 -28
View File
@@ -7,7 +7,7 @@ import type { SceneType } from "@/types";
import { getSceneConfig } from "@/lib/sceneConfig";
import Modal from "@/components/Modal";
import Button from "@/components/Button";
import { useToast } from "@/hooks/useToast";
import { useShare } from "@/hooks/useShare";
interface QrInviteModalProps {
open: boolean;
@@ -22,40 +22,22 @@ export default function QrInviteModal({
roomId,
scene = "eat",
}: QrInviteModalProps) {
const toast = useToast();
const { share, copyToClipboard } = useShare();
const sceneConfig = getSceneConfig(scene);
const inviteUrl =
typeof window !== "undefined"
? `${window.location.origin}/invite/${roomId}`
: "";
const handleCopy = useCallback(async () => {
try {
await navigator.clipboard.writeText(inviteUrl);
toast.show("邀请链接已复制,快去发给朋友吧!");
} catch {
toast.show("复制失败,请手动复制链接");
}
}, [inviteUrl, toast]);
const handleCopy = useCallback(
() => copyToClipboard(inviteUrl, "邀请链接已复制,快去发给朋友吧!"),
[inviteUrl, copyToClipboard],
);
const handleShare = useCallback(async () => {
const shareData = {
title: sceneConfig.shareTitle,
text: sceneConfig.shareText,
url: inviteUrl,
};
try {
if (navigator.share && navigator.canShare?.(shareData)) {
await navigator.share(shareData);
return;
}
} catch (e) {
if (e instanceof Error && e.name === "AbortError") return;
}
handleCopy();
}, [inviteUrl, handleCopy, sceneConfig]);
const handleShare = useCallback(
() => share({ title: sceneConfig.shareTitle, text: sceneConfig.shareText, url: inviteUrl }, handleCopy),
[inviteUrl, sceneConfig, share, handleCopy],
);
return (
<Modal open={open} onClose={onClose}>