🚀 Auto-deploy: melhoria no snap e medição AR em 25/05/2026 16:24:11

This commit is contained in:
2026-05-25 16:24:11 +00:00
parent 2e70d2e133
commit 03411d9224
+43 -18
View File
@@ -236,12 +236,12 @@ function MiiAvatarBackup({
return ( return (
<group ref={groupRef} position={positionVector} rotation={rotationEuler} scale={scale}> <group ref={groupRef} position={positionVector} rotation={rotationEuler} scale={scale}>
<group position={[0, 0.32, 0]}> <group position={[0, 0.38, 0]}>
<mesh position={[0, 0, -0.001]}> <mesh position={[0, 0, -0.001]}>
<planeGeometry args={[0.22, 0.05]} /> <planeGeometry args={[0.44, 0.1]} />
<meshBasicMaterial color="#0f172a" transparent opacity={0.7} /> <meshBasicMaterial color="#0f172a" transparent opacity={0.7} />
</mesh> </mesh>
<Text fontSize={0.024} color="#ffffff" anchorX="center" anchorY="middle" fontWeight="bold"> <Text fontSize={0.048} color="#ffffff" anchorX="center" anchorY="middle" fontWeight="bold">
{username} {username}
</Text> </Text>
</group> </group>
@@ -253,9 +253,9 @@ function MiiAvatarBackup({
</mesh> </mesh>
)} )}
{/* Cabeça do Avatar: Toon Head do Dicebear em HTML Billboard para resiliência contra erros de CORS/Rede */} {/* Cabeça do Avatar: Toon Head do Dicebear em HTML Transformado em 3D Plano (olhando para a mesa) */}
<group ref={headRef} position={[0, 0.16, 0]}> <group ref={headRef} position={[0, 0.16, 0]}>
<Html center distanceFactor={1.2}> <Html transform center distanceFactor={1.2}>
<div className="w-16 h-16 flex items-center justify-center pointer-events-none select-none"> <div className="w-16 h-16 flex items-center justify-center pointer-events-none select-none">
<img <img
src={avatarUrl} src={avatarUrl}
@@ -447,14 +447,14 @@ function RealMiiAvatar({
}, [props.rotation]); }, [props.rotation]);
return ( return (
<group ref={groupRef} position={positionVector} rotation={rotationEuler}> <group ref={groupRef} position={positionVector} rotation={rotationEuler} scale={scale}>
{/* Balão de Nome acima da cabeça */} {/* Balão de Nome acima da cabeça */}
<group position={[0, 0.76, 0]}> <group position={[0, 0.9, 0]}>
<mesh position={[0, 0, -0.001]}> <mesh position={[0, 0, -0.001]}>
<planeGeometry args={[0.26, 0.055]} /> <planeGeometry args={[0.52, 0.11]} />
<meshBasicMaterial color="#0f172a" transparent opacity={0.8} /> <meshBasicMaterial color="#0f172a" transparent opacity={0.8} />
</mesh> </mesh>
<Text fontSize={0.026} color="#ffffff" anchorX="center" anchorY="middle" fontWeight="bold"> <Text fontSize={0.052} color="#ffffff" anchorX="center" anchorY="middle" fontWeight="bold">
{username} {username}
</Text> </Text>
</group> </group>
@@ -832,12 +832,38 @@ export default function MeetingRoom() {
// Estados da Sala (Conexão Supabase) // Estados da Sala (Conexão Supabase)
const [peers, setPeers] = useState<Record<string, PeerData>>({}); const [peers, setPeers] = useState<Record<string, PeerData>>({});
const mergedPeers = useMemo(() => {
if (!inRoom) return peers;
// Se o usuário local já estiver no peers (via sync do Supabase), usamos o peers original
if (peers[selectedChair]) {
return peers;
}
// Caso contrário, injetamos o usuário local no dicionário temporário
return {
...peers,
[selectedChair]: {
presence_ref: 'local_user',
username: name,
avatarId: selectedAvatar,
chairId: selectedChair,
role: isPresenter ? 'presenter' : 'guest',
cargo: cargo || 'Apresentador',
empresa: empresa || 'SteelXR Corp',
joinedAt: new Date().toISOString()
} as unknown as PeerData
};
}, [peers, inRoom, selectedChair, name, selectedAvatar, isPresenter, cargo, empresa]);
const activeUsersCount = useMemo(() => Object.keys(mergedPeers).length, [mergedPeers]);
const [chatMessages, setChatMessages] = useState<{ id: string; sender: string; text: string; time: string }[]>([]); const [chatMessages, setChatMessages] = useState<{ id: string; sender: string; text: string; time: string }[]>([]);
const [newMessage, setNewMessage] = useState(''); const [newMessage, setNewMessage] = useState('');
const [lastChatSender, setLastChatSender] = useState<string | null>(null); const [lastChatSender, setLastChatSender] = useState<string | null>(null);
const [isMuted, setIsMuted] = useState(false); const [isMuted, setIsMuted] = useState(false);
const [isTalking, setIsTalking] = useState(false); const [isTalking, setIsTalking] = useState(false);
const [activeUsersCount, setActiveUsersCount] = useState(1);
const [roomCode, setRoomCode] = useState(roomId || ''); const [roomCode, setRoomCode] = useState(roomId || '');
const [activeTab, setActiveTab] = useState<'chat' | 'participants'>('participants'); const [activeTab, setActiveTab] = useState<'chat' | 'participants'>('participants');
@@ -1050,7 +1076,6 @@ export default function MeetingRoom() {
}); });
console.log("👥 [Presence Sync] Peers formatados:", formattedPeers); console.log("👥 [Presence Sync] Peers formatados:", formattedPeers);
setPeers(formattedPeers); setPeers(formattedPeers);
setActiveUsersCount(count);
}) })
.on('presence', { event: 'join' }, ({ key, newPresences }) => { .on('presence', { event: 'join' }, ({ key, newPresences }) => {
if (key.startsWith('lobby_watcher_')) return; if (key.startsWith('lobby_watcher_')) return;
@@ -1405,8 +1430,8 @@ export default function MeetingRoom() {
<ThreeMeetingRoomScene currentActiveModel={activeModel} presentationState={presentationState} isFocusMode={isFocusMode} /> <ThreeMeetingRoomScene currentActiveModel={activeModel} presentationState={presentationState} isFocusMode={isFocusMode} />
{/* Renderizar avatares de TODOS na sala - Ocultados se modo foco */} {/* Renderizar avatares de TODOS na sala - Ocultados se modo foco */}
{!isFocusMode && Object.keys(peers).map((chairKey) => { {!isFocusMode && Object.keys(mergedPeers).map((chairKey) => {
const peer = peers[chairKey]; const peer = mergedPeers[chairKey];
const chairConf = CHAIRS.find((c) => c.id === peer.chairId); const chairConf = CHAIRS.find((c) => c.id === peer.chairId);
if (!chairConf) return null; if (!chairConf) return null;
@@ -1414,14 +1439,14 @@ export default function MeetingRoom() {
return ( return (
<MiiAvatar <MiiAvatar
key={peer.presence_ref} key={peer.presence_ref || 'local'}
avatarId={peer.avatarId} avatarId={peer.avatarId}
username={isLocalUser ? `${peer.username} (Você)` : peer.username} username={isLocalUser ? `${peer.username} (Você)` : peer.username}
position={chairConf.pos} position={chairConf.pos}
rotation={chairConf.rot} rotation={chairConf.rot}
isTalking={isLocalUser ? isTalking : (isTalking && Math.random() > 0.5)} isTalking={isLocalUser ? isTalking : (isTalking && Math.random() > 0.5)}
isLastChatSender={peer.username === lastChatSender} isLastChatSender={peer.username === lastChatSender}
scale={1.2} scale={4.8}
/> />
); );
})} })}
@@ -1711,13 +1736,13 @@ export default function MeetingRoom() {
<span className="font-mono text-[9px] text-muted-foreground uppercase tracking-widest block mb-2">Quem está na sala</span> <span className="font-mono text-[9px] text-muted-foreground uppercase tracking-widest block mb-2">Quem está na sala</span>
<div className="space-y-2.5"> <div className="space-y-2.5">
{Object.keys(peers).map((chairKey) => { {Object.keys(mergedPeers).map((chairKey) => {
const peer = peers[chairKey]; const peer = mergedPeers[chairKey];
const isHost = peer.role === 'presenter'; const isHost = peer.role === 'presenter';
const isMe = peer.chairId === selectedChair; const isMe = peer.chairId === selectedChair;
return ( return (
<div key={peer.presence_ref} className="rounded-lg border border-slate-800 bg-slate-950/40 p-3 flex items-start gap-3 relative overflow-hidden"> <div key={peer.presence_ref || 'local'} className="rounded-lg border border-slate-800 bg-slate-950/40 p-3 flex items-start gap-3 relative overflow-hidden">
{/* Indicador da cor do avatar do Mii via classe estática Tailwind */} {/* Indicador da cor do avatar do Mii via classe estática Tailwind */}
<div className={`h-8 w-8 rounded-full border border-slate-800 flex items-center justify-center font-bold text-xs ${getAvatarBgClass(peer.avatarId)}`}> <div className={`h-8 w-8 rounded-full border border-slate-800 flex items-center justify-center font-bold text-xs ${getAvatarBgClass(peer.avatarId)}`}>
{peer.username.substring(0, 2).toUpperCase()} {peer.username.substring(0, 2).toUpperCase()}