feat: 添加二维码邀请功能,扫码即可加入房间

This commit is contained in:
2026-02-24 20:00:55 +08:00
parent 25eb228e09
commit a6fc523f4f
4 changed files with 162 additions and 28 deletions
+12 -28
View File
@@ -2,8 +2,9 @@
import { useState, useCallback } from "react";
import { useRouter } from "next/navigation";
import { Users, Share2, LogOut } from "lucide-react";
import { Users, QrCode, LogOut } from "lucide-react";
import { motion, AnimatePresence } from "framer-motion";
import QrInviteModal from "./QrInviteModal";
interface TopNavProps {
roomId: string;
@@ -13,46 +14,22 @@ interface TopNavProps {
export default function TopNav({ roomId, userCount }: TopNavProps) {
const router = useRouter();
const [toast, setToast] = useState("");
const [showQr, setShowQr] = useState(false);
const showToast = useCallback((msg: string) => {
setToast(msg);
setTimeout(() => setToast(""), 2200);
}, []);
const handleInvite = useCallback(async () => {
const url = `${window.location.origin}/invite/${roomId}`;
const shareData = {
title: "别说随便啦,来滑卡片决定吃什么!",
text: "我建好房间了,快点开链接一起选餐厅,滑中同一家就去吃!",
url,
};
try {
if (navigator.share && navigator.canShare?.(shareData)) {
await navigator.share(shareData);
return;
}
} catch (e) {
if (e instanceof Error && e.name === "AbortError") return;
}
try {
await navigator.clipboard.writeText(url);
showToast("邀请链接已复制,快去发给朋友吧!");
} catch {
showToast("复制失败,请手动复制链接");
}
}, [roomId, showToast]);
return (
<>
<nav className="relative z-10 flex h-14 items-center justify-between px-4">
<div className="w-24">
<button
onClick={handleInvite}
onClick={() => setShowQr(true)}
className="flex items-center gap-1 rounded-full bg-emerald-50 px-2.5 py-1 text-xs font-semibold text-emerald-600 transition-colors active:bg-emerald-100"
>
<Share2 size={13} />
<QrCode size={13} />
</button>
</div>
@@ -95,6 +72,13 @@ export default function TopNav({ roomId, userCount }: TopNavProps) {
</motion.div>
)}
</AnimatePresence>
<QrInviteModal
open={showQr}
onClose={() => setShowQr(false)}
roomId={roomId}
onToast={showToast}
/>
</>
);
}