162 lines
5.0 KiB
TypeScript
162 lines
5.0 KiB
TypeScript
import React, { useState, KeyboardEvent, useRef } from "react";
|
|
import { Input, Button, Box, Typography, Tooltip, Dialog, DialogTitle, DialogContent, DialogActions } from "@mui/material";
|
|
import { Session } from "./GlobalContext";
|
|
|
|
interface NameSetterProps {
|
|
session: Session;
|
|
sendJsonMessage: (message: any) => void;
|
|
onNameSet?: () => void;
|
|
initialName?: string;
|
|
initialPassword?: string;
|
|
}
|
|
|
|
const NameSetter: React.FC<NameSetterProps> = ({
|
|
session,
|
|
sendJsonMessage,
|
|
onNameSet,
|
|
initialName = "",
|
|
initialPassword = "",
|
|
}) => {
|
|
const [editName, setEditName] = useState<string>(initialName);
|
|
const [editPassword, setEditPassword] = useState<string>(initialPassword);
|
|
const [showDialog, setShowDialog] = useState<boolean>(!session.name);
|
|
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
|
|
|
|
const nameInputRef = useRef<HTMLInputElement>(null);
|
|
const passwordInputRef = useRef<HTMLInputElement>(null);
|
|
|
|
const setName = (name: string) => {
|
|
setIsSubmitting(true);
|
|
sendJsonMessage({
|
|
type: "set_name",
|
|
data: { name, password: editPassword ? editPassword : undefined },
|
|
});
|
|
if (onNameSet) {
|
|
onNameSet();
|
|
}
|
|
setShowDialog(false);
|
|
setIsSubmitting(false);
|
|
setEditName("");
|
|
setEditPassword("");
|
|
};
|
|
|
|
const handleNameKeyDown = (event: KeyboardEvent<HTMLInputElement>): void => {
|
|
if (event.key === "Enter") {
|
|
event.preventDefault();
|
|
if (passwordInputRef.current) {
|
|
passwordInputRef.current.focus();
|
|
}
|
|
}
|
|
};
|
|
|
|
const handlePasswordKeyDown = (event: KeyboardEvent<HTMLInputElement>): void => {
|
|
if (event.key === "Enter") {
|
|
event.preventDefault();
|
|
handleSubmit();
|
|
}
|
|
};
|
|
|
|
const handleSubmit = () => {
|
|
const newName = editName.trim();
|
|
if (!newName || (session?.name && session.name === newName)) {
|
|
return;
|
|
}
|
|
setName(newName);
|
|
};
|
|
|
|
const handleOpenDialog = () => {
|
|
setEditName(session.name || "");
|
|
setEditPassword("");
|
|
setShowDialog(true);
|
|
// Focus the name input when dialog opens
|
|
setTimeout(() => {
|
|
if (nameInputRef.current) {
|
|
nameInputRef.current.focus();
|
|
}
|
|
}, 100);
|
|
};
|
|
|
|
const handleCloseDialog = () => {
|
|
setShowDialog(false);
|
|
setEditName("");
|
|
setEditPassword("");
|
|
};
|
|
|
|
const hasNameChanged = editName.trim() !== (session.name || "");
|
|
const canSubmit = editName.trim() && hasNameChanged && !isSubmitting;
|
|
|
|
return (
|
|
<Box sx={{ gap: 1, display: "flex", flexDirection: "column", alignItems: "flex-start" }}>
|
|
{session.name && !showDialog && (
|
|
<Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
|
|
<Typography>You are logged in as: {session.name}</Typography>
|
|
<Button variant="outlined" size="small" onClick={handleOpenDialog}>
|
|
Change Name
|
|
</Button>
|
|
</Box>
|
|
)}
|
|
|
|
{/* Dialog for name change */}
|
|
<Dialog open={showDialog} onClose={handleCloseDialog} maxWidth="sm" fullWidth>
|
|
<DialogTitle>
|
|
{session.name ? "Change Your Name" : "Enter Your Name"}
|
|
</DialogTitle>
|
|
<DialogContent>
|
|
<Box sx={{ display: "flex", flexDirection: "column", gap: 2, pt: 1 }}>
|
|
<Typography variant="body2" color="text.secondary">
|
|
{session.name
|
|
? "Enter a new name to change your current name."
|
|
: "Enter your name to join the lobby."
|
|
}
|
|
</Typography>
|
|
<Typography variant="caption" color="text.secondary">
|
|
You can optionally set a password to reserve this name; supply it again to takeover the name from another client.
|
|
</Typography>
|
|
|
|
<Input
|
|
inputRef={nameInputRef}
|
|
type="text"
|
|
value={editName}
|
|
onChange={(e): void => {
|
|
setEditName(e.target.value);
|
|
}}
|
|
onKeyDown={handleNameKeyDown}
|
|
placeholder="Your name"
|
|
fullWidth
|
|
autoFocus
|
|
/>
|
|
|
|
<Input
|
|
inputRef={passwordInputRef}
|
|
type="password"
|
|
value={editPassword}
|
|
onChange={(e): void => setEditPassword(e.target.value)}
|
|
onKeyDown={handlePasswordKeyDown}
|
|
placeholder="Optional password"
|
|
fullWidth
|
|
/>
|
|
|
|
<Tooltip title="Optional: choose a short password to reserve this name. Keep it secret.">
|
|
<span />
|
|
</Tooltip>
|
|
</Box>
|
|
</DialogContent>
|
|
<DialogActions>
|
|
<Button onClick={handleCloseDialog} disabled={isSubmitting}>
|
|
Cancel
|
|
</Button>
|
|
<Button
|
|
variant="contained"
|
|
onClick={handleSubmit}
|
|
disabled={!canSubmit}
|
|
color={hasNameChanged ? "primary" : "inherit"}
|
|
>
|
|
{isSubmitting ? "Changing..." : (session.name ? "Change Name" : "Join")}
|
|
</Button>
|
|
</DialogActions>
|
|
</Dialog>
|
|
</Box>
|
|
);
|
|
};
|
|
|
|
export default NameSetter; |