91 lines
2.8 KiB
TypeScript
91 lines
2.8 KiB
TypeScript
/**
|
|
* InviteDialog — input player name, copy invite link
|
|
*/
|
|
import { Component, createSignal } from "solid-js";
|
|
import { useJournalStream } from "../stores/journalStream";
|
|
|
|
interface InviteDialogProps {
|
|
onClose: () => void;
|
|
}
|
|
|
|
export const InviteDialog: Component<InviteDialogProps> = (props) => {
|
|
const stream = useJournalStream();
|
|
const [playerName, setPlayerName] = createSignal("");
|
|
const [copied, setCopied] = createSignal(false);
|
|
|
|
const inviteLink = () => {
|
|
const url = new URL(window.location.href);
|
|
url.searchParams.set("session", stream.sessionId || "default");
|
|
if (playerName().trim()) {
|
|
url.searchParams.set("player", playerName().trim());
|
|
}
|
|
url.searchParams.set("autojoin", "1");
|
|
return url.toString();
|
|
};
|
|
|
|
const handleCopy = async () => {
|
|
try {
|
|
await navigator.clipboard.writeText(inviteLink());
|
|
setCopied(true);
|
|
setTimeout(() => setCopied(false), 2000);
|
|
} catch {
|
|
const input = document.getElementById(
|
|
"invite-link-input",
|
|
) as HTMLInputElement;
|
|
if (input) input.select();
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div
|
|
class="absolute inset-0 z-50 flex items-center justify-center bg-black/20"
|
|
onClick={props.onClose}
|
|
>
|
|
<div
|
|
class="bg-white rounded-lg border border-gray-200 shadow-xl w-[280px] p-4 space-y-3"
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<div class="flex items-center justify-between">
|
|
<h3 class="text-sm font-semibold text-gray-800">邀请玩家</h3>
|
|
<button
|
|
onClick={props.onClose}
|
|
class="text-gray-400 hover:text-gray-600 text-sm"
|
|
>
|
|
✕
|
|
</button>
|
|
</div>
|
|
<p class="text-xs text-gray-500">
|
|
输入玩家名字并分享链接,对方将以玩家身份加入。
|
|
</p>
|
|
<input
|
|
type="text"
|
|
value={playerName()}
|
|
onInput={(e) => setPlayerName(e.currentTarget.value)}
|
|
placeholder="玩家名字"
|
|
class="w-full border border-gray-300 rounded px-2 py-1 text-xs"
|
|
autofocus
|
|
/>
|
|
<div class="flex gap-1">
|
|
<input
|
|
id="invite-link-input"
|
|
type="text"
|
|
value={inviteLink()}
|
|
readonly
|
|
class="flex-1 border border-gray-200 rounded px-2 py-1 text-xs bg-gray-50 text-gray-600 font-mono truncate"
|
|
/>
|
|
<button
|
|
onClick={handleCopy}
|
|
class={`shrink-0 rounded px-2 py-1 text-xs font-medium transition-colors ${
|
|
copied()
|
|
? "bg-green-100 text-green-700"
|
|
: "bg-blue-600 text-white hover:bg-blue-700"
|
|
}`}
|
|
>
|
|
{copied() ? "已复制!" : "复制"}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|