🚀 Auto-deploy: melhoria no snap e medição AR em 25/05/2026 01:28:33

This commit is contained in:
2026-05-25 01:28:33 +00:00
parent 61591dc84e
commit 0baed4a871
+71 -31
View File
@@ -538,6 +538,26 @@ function HologramModel({ model, presentationState }: { model: SceneModel; presen
// Cenário da Sala de Reunião Clara // Cenário da Sala de Reunião Clara
function ThreeMeetingRoomScene({ currentActiveModel, presentationState, isFocusMode }: { currentActiveModel: SceneModel | null; presentationState: PresentationState; isFocusMode: boolean }) { function ThreeMeetingRoomScene({ currentActiveModel, presentationState, isFocusMode }: { currentActiveModel: SceneModel | null; presentationState: PresentationState; isFocusMode: boolean }) {
const tableGeom = useMemo(() => {
// Geometria da mesa em U / Retangular de cantos arredondados
const shape = new THREE.Shape();
shape.moveTo(-1.6, -1.1);
shape.lineTo(1.6, -1.1);
shape.quadraticCurveTo(1.9, -1.1, 1.9, -0.8);
shape.lineTo(1.9, 0.8);
shape.quadraticCurveTo(1.9, 1.1, 1.6, 1.1);
shape.lineTo(-1.6, 1.1);
shape.quadraticCurveTo(-1.9, 1.1, -1.9, 0.8);
shape.lineTo(-1.9, -0.8);
shape.quadraticCurveTo(-1.9, -1.1, -1.6, -1.1);
const hole = new THREE.Path();
hole.absellipse(0, 0, 0.9, 0.45, 0, Math.PI * 2, true);
shape.holes.push(hole);
return new THREE.ExtrudeGeometry(shape, { depth: 0.06, bevelEnabled: true, bevelThickness: 0.01, bevelSize: 0.01, bevelSegments: 3 });
}, []);
return ( return (
<group> <group>
{/* Luzes da Sala / Foco */} {/* Luzes da Sala / Foco */}
@@ -577,29 +597,28 @@ function ThreeMeetingRoomScene({ currentActiveModel, presentationState, isFocusM
<meshStandardMaterial color="#bae6fd" roughness={0.1} emissive="#bae6fd" emissiveIntensity={0.4} /> <meshStandardMaterial color="#bae6fd" roughness={0.1} emissive="#bae6fd" emissiveIntensity={0.4} />
</mesh> </mesh>
{/* Mesa Cilíndrica Central de 1m de diâmetro (raio 0.5) */} {/* Mesa Elíptica/Retangular com furo central (Madeira Mel Carvalho Clara) */}
<group position={[0, 0, 0]}> <group position={[0, 0.8, 0]} rotation={[Math.PI / 2, 0, 0]}>
{/* Base no chão */} <mesh geometry={tableGeom} castShadow receiveShadow>
<mesh position={[0, 0.01, 0]} castShadow receiveShadow> <meshStandardMaterial color="#d97706" roughness={0.2} metalness={0.1} />
<cylinderGeometry args={[0.25, 0.25, 0.02, 32]} />
<meshStandardMaterial color="#475569" metalness={0.7} roughness={0.2} />
</mesh> </mesh>
{/* Coluna / Pé da mesa */} </group>
<mesh position={[0, 0.45, 0]} castShadow receiveShadow>
<cylinderGeometry args={[0.06, 0.06, 0.9, 32]} /> {/* Pés da mesa (Cromados) */}
<meshStandardMaterial color="#64748b" metalness={0.8} roughness={0.1} /> {[-1.3, 1.3].map((x) =>
[-0.7, 0.7].map((z) => (
<mesh key={`${x}-${z}`} position={[x, 0.4, z]} castShadow receiveShadow>
<cylinderGeometry args={[0.035, 0.035, 0.8]} />
<meshStandardMaterial color="#d4d4d8" metalness={0.9} roughness={0.1} />
</mesh> </mesh>
{/* Tampo da mesa (Diâmetro 1m, altura 0.9m) */} ))
<mesh position={[0, 0.9, 0]} castShadow receiveShadow> )}
<cylinderGeometry args={[0.5, 0.5, 0.06, 48]} />
<meshStandardMaterial color="#d97706" roughness={0.4} metalness={0.1} /> {/* Projetor de Holograma / Círculo centralizado desenhado na mesa */}
</mesh> <mesh position={[0, 0.861, 0]} rotation={[-Math.PI / 2, 0, 0]}>
{/* Projetor de Holograma (Centro da mesa) */}
<mesh position={[0, 0.931, 0]} rotation={[-Math.PI / 2, 0, 0]}>
<ringGeometry args={[0.22, 0.25, 32]} /> <ringGeometry args={[0.22, 0.25, 32]} />
<meshBasicMaterial color="#0ea5e9" transparent opacity={0.6} /> <meshBasicMaterial color="#0ea5e9" transparent opacity={0.6} />
</mesh> </mesh>
</group>
</> </>
)} )}
@@ -787,18 +806,28 @@ export default function MeetingRoom() {
tempChannel tempChannel
.on('presence', { event: 'sync' }, () => { .on('presence', { event: 'sync' }, () => {
const state = tempChannel.presenceState(); const state = tempChannel.presenceState();
console.log("👥 [Lobby Watcher Sync] Estado de presença bruto:", state);
const formattedPeers: Record<string, PeerData> = {}; const formattedPeers: Record<string, PeerData> = {};
Object.keys(state).forEach((chairKey) => { Object.keys(state).forEach((key) => {
// Ignora outros watchers do lobby if (key.startsWith('lobby_watcher_')) return;
if (chairKey.startsWith('lobby_watcher_')) return; const presences = state[key] as unknown as PeerData[];
const presences = state[chairKey] as unknown as PeerData[];
if (presences && presences.length > 0) { if (presences && presences.length > 0) {
formattedPeers[chairKey] = presences[0]; presences.forEach((presence) => {
if (presence && presence.chairId && presence.username) {
formattedPeers[presence.chairId] = {
...presence,
avatarId: Number(presence.avatarId) || 1,
cargo: presence.cargo || 'Colaborador',
empresa: presence.empresa || 'SteelXR Corp',
role: presence.role || 'guest'
};
}
});
} }
}); });
console.log("👥 [Lobby Watcher Sync] Peers formatados:", formattedPeers);
setPeers(formattedPeers); setPeers(formattedPeers);
}) })
.subscribe(); .subscribe();
@@ -862,28 +891,39 @@ export default function MeetingRoom() {
const channel = supabase.channel(`meeting_room_${finalRoomId}`, { const channel = supabase.channel(`meeting_room_${finalRoomId}`, {
config: { config: {
broadcast: { self: true }, broadcast: { self: true }
presence: { key: selectedChair },
}, },
}); });
channelRef.current = channel; channelRef.current = channel;
// Sincroniza participantes online // Sincroniza participantes online com tolerância a múltiplos formatos e falhas de conexão
channel channel
.on('presence', { event: 'sync' }, () => { .on('presence', { event: 'sync' }, () => {
const state = channel.presenceState(); const state = channel.presenceState();
console.log("👥 [Presence Sync] Estado de presença bruto da reunião:", state);
const formattedPeers: Record<string, PeerData> = {}; const formattedPeers: Record<string, PeerData> = {};
let count = 0; let count = 0;
Object.keys(state).forEach((chairKey) => { Object.keys(state).forEach((key) => {
if (chairKey.startsWith('lobby_watcher_')) return; if (key.startsWith('lobby_watcher_')) return;
const presences = state[chairKey] as unknown as PeerData[]; const presences = state[key] as unknown as PeerData[];
if (presences && presences.length > 0) { if (presences && presences.length > 0) {
formattedPeers[chairKey] = presences[0]; presences.forEach((presence) => {
if (presence && presence.chairId && presence.username) {
formattedPeers[presence.chairId] = {
...presence,
avatarId: Number(presence.avatarId) || 1,
cargo: presence.cargo || 'Colaborador',
empresa: presence.empresa || 'SteelXR Corp',
role: presence.role || 'guest'
};
count++; count++;
} }
}); });
}
});
console.log("👥 [Presence Sync] Peers formatados:", formattedPeers);
setPeers(formattedPeers); setPeers(formattedPeers);
setActiveUsersCount(count); setActiveUsersCount(count);
}) })