🚀 Auto-deploy: melhoria no snap e medição AR em 25/05/2026 00:40:00
This commit is contained in:
@@ -623,6 +623,21 @@ export default function MeetingRoom() {
|
|||||||
sectionInvert: false
|
sectionInvert: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Carrega modificações da peça vindas do Viewer se houver
|
||||||
|
useEffect(() => {
|
||||||
|
const savedState = localStorage.getItem('tsxr_initial_meeting_state');
|
||||||
|
if (savedState) {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(savedState) as PresentationState;
|
||||||
|
setPresentationState(parsed);
|
||||||
|
console.log('🔄 [MeetingRoom] Estado inicial carregado do Viewer:', parsed);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Falha ao carregar estado inicial do Viewer', err);
|
||||||
|
}
|
||||||
|
localStorage.removeItem('tsxr_initial_meeting_state');
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
const channelRef = useRef<ReturnType<typeof supabase.channel> | null>(null);
|
const channelRef = useRef<ReturnType<typeof supabase.channel> | null>(null);
|
||||||
const chatScrollRef = useRef<HTMLDivElement>(null);
|
const chatScrollRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
@@ -799,6 +814,16 @@ export default function MeetingRoom() {
|
|||||||
empresa: empresa.trim() || 'SteelXR Corp',
|
empresa: empresa.trim() || 'SteelXR Corp',
|
||||||
joinedAt: new Date().toISOString(),
|
joinedAt: new Date().toISOString(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Se for o apresentador, propaga o estado inicial de apresentação (vinda do Viewer) para todos
|
||||||
|
if (isPresenter) {
|
||||||
|
channel.send({
|
||||||
|
type: 'broadcast',
|
||||||
|
event: 'presentation_update',
|
||||||
|
payload: presentationState
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
setInRoom(true);
|
setInRoom(true);
|
||||||
toast.success(`Entrou na sala de reunião: ${finalRoomId}`);
|
toast.success(`Entrou na sala de reunião: ${finalRoomId}`);
|
||||||
navigate(`/meeting/${finalRoomId}`, { replace: true });
|
navigate(`/meeting/${finalRoomId}`, { replace: true });
|
||||||
|
|||||||
+45
-3
@@ -1,5 +1,5 @@
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { ArrowLeft, Glasses, Box, Ruler, FileText, Upload, Loader2 } from "lucide-react";
|
import { ArrowLeft, Glasses, Box, Ruler, FileText, Upload, Loader2, Users } from "lucide-react";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { useModelStore } from "@/stores/useModelStore";
|
import { useModelStore } from "@/stores/useModelStore";
|
||||||
import { ModelViewerCanvas } from "@/components/three/ModelViewer";
|
import { ModelViewerCanvas } from "@/components/three/ModelViewer";
|
||||||
@@ -23,7 +23,18 @@ import { convertIFCtoGLB } from "@/lib/convertIFC";
|
|||||||
|
|
||||||
const Viewer = () => {
|
const Viewer = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { model, xrSupported, addModel, models, maxModels, scaleRatio } = useModelStore();
|
const {
|
||||||
|
model,
|
||||||
|
xrSupported,
|
||||||
|
addModel,
|
||||||
|
models,
|
||||||
|
maxModels,
|
||||||
|
scaleRatio,
|
||||||
|
fineTuning,
|
||||||
|
sectionEnabled,
|
||||||
|
sectionInvert,
|
||||||
|
sectionLevel
|
||||||
|
} = useModelStore();
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
const [converting, setConverting] = useState(false);
|
const [converting, setConverting] = useState(false);
|
||||||
|
|
||||||
@@ -101,6 +112,29 @@ const Viewer = () => {
|
|||||||
navigate("/xr");
|
navigate("/xr");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleEnterMeeting = () => {
|
||||||
|
// Coleta o eixo habilitado de seção no Viewer
|
||||||
|
const enabledAxis = (['x', 'y', 'z'] as const).find(ax => sectionEnabled[ax]);
|
||||||
|
const isSectionActive = !!enabledAxis;
|
||||||
|
const sectionAxis = enabledAxis || 'y';
|
||||||
|
const sectionLevelVal = isSectionActive ? sectionLevel[sectionAxis] : 0.0;
|
||||||
|
const sectionInvertVal = isSectionActive ? sectionInvert[sectionAxis] : false;
|
||||||
|
|
||||||
|
// Salva o estado atual da peça
|
||||||
|
const initialMeetingState = {
|
||||||
|
rotation: [fineTuning.rotX, fineTuning.rotY, fineTuning.rotZ],
|
||||||
|
scale: fineTuning.scale,
|
||||||
|
sectionEnabled: isSectionActive,
|
||||||
|
sectionAxis,
|
||||||
|
sectionLevel: sectionLevelVal,
|
||||||
|
sectionInvert: sectionInvertVal
|
||||||
|
};
|
||||||
|
|
||||||
|
localStorage.setItem('tsxr_initial_meeting_state', JSON.stringify(initialMeetingState));
|
||||||
|
toast.success('Configurações da maquete salvas. Direcionando para a reunião...');
|
||||||
|
navigate('/meeting');
|
||||||
|
};
|
||||||
|
|
||||||
const canAddMore = models.length < maxModels;
|
const canAddMore = models.length < maxModels;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -128,8 +162,16 @@ const Viewer = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className="gap-2 border-primary/30 hover:bg-primary/10 text-primary font-mono h-9"
|
||||||
|
onClick={handleEnterMeeting}
|
||||||
|
>
|
||||||
|
<Users className="h-4 w-4" />
|
||||||
|
Reunião Virtual
|
||||||
|
</Button>
|
||||||
<ShareButton />
|
<ShareButton />
|
||||||
<Button className="gap-2 glow-primary" disabled={!xrSupported} onClick={handleEnterXR}>
|
<Button className="gap-2 glow-primary h-9" disabled={!xrSupported} onClick={handleEnterXR}>
|
||||||
<Glasses className="h-4 w-4" />
|
<Glasses className="h-4 w-4" />
|
||||||
Entrar em Modo XR
|
Entrar em Modo XR
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
Reference in New Issue
Block a user