🚀 Auto-deploy: melhoria no snap e medição AR em 31/05/2026 23:46:46

This commit is contained in:
2026-05-31 23:46:46 +00:00
parent 126bc6f80d
commit a2ac72cfe7
2 changed files with 99 additions and 7 deletions
+18 -1
View File
@@ -13,7 +13,7 @@ import {
} from './three/viewCubeBus'; } from './three/viewCubeBus';
import { useModelStore } from '@/stores/useModelStore'; import { useModelStore } from '@/stores/useModelStore';
import { getModelLocalGroup } from '@/lib/modelTransforms'; import { getModelLocalGroup } from '@/lib/modelTransforms';
import { Check, RotateCcw } from 'lucide-react'; import { Check, RotateCcw, Maximize2 } from 'lucide-react';
import { toast } from 'sonner'; import { toast } from 'sonner';
/** Builds a square canvas texture with a label centered on it. */ /** Builds a square canvas texture with a label centered on it. */
@@ -296,6 +296,23 @@ export function ViewCube() {
<RotateCcw className="h-2.5 w-2.5" /> reset <RotateCcw className="h-2.5 w-2.5" /> reset
</button> </button>
)} )}
{/* Botão de Tela Cheia */}
<button
type="button"
onClick={() => {
const container = document.getElementById("canvas-container");
if (container) {
container.requestFullscreen().catch((err) => {
toast.error("Não foi possível entrar em tela cheia: " + err.message);
});
}
}}
className="flex h-7 w-full items-center justify-center gap-1 rounded border border-primary/40 bg-background/40 font-mono text-[10px] uppercase tracking-widest text-primary hover:bg-primary/10 transition-colors"
title="Entrar em modo tela cheia"
>
<Maximize2 className="h-3 w-3" /> Tela Cheia
</button>
</div> </div>
); );
} }
+81 -6
View File
@@ -1,6 +1,6 @@
import { useNavigate, useSearchParams } from "react-router-dom"; import { useNavigate, useSearchParams } from "react-router-dom";
import { supabase } from "@/integrations/supabase/client"; import { supabase } from "@/integrations/supabase/client";
import { ArrowLeft, Glasses, Box, Ruler, FileText, Upload, Loader2, Users } from "lucide-react"; import { ArrowLeft, Glasses, Box, Ruler, FileText, Upload, Loader2, Users, Menu, Target } 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";
@@ -21,6 +21,7 @@ import { Separator } from "@/components/ui/separator";
import { getSupportedExtension, convertToGLB, ACCEPTED_EXTENSIONS } from "@/lib/convertToGLB"; import { getSupportedExtension, convertToGLB, ACCEPTED_EXTENSIONS } from "@/lib/convertToGLB";
import { validateModelFile } from "@/lib/validateModelFile"; import { validateModelFile } from "@/lib/validateModelFile";
import { convertIFCtoGLB } from "@/lib/convertIFC"; import { convertIFCtoGLB } from "@/lib/convertIFC";
import { mainCameraRef, mainControlsRef } from "@/components/three/viewCubeBus";
const Viewer = () => { const Viewer = () => {
const navigate = useNavigate(); const navigate = useNavigate();
@@ -39,6 +40,44 @@ const Viewer = () => {
const fileInputRef = useRef<HTMLInputElement>(null); const fileInputRef = useRef<HTMLInputElement>(null);
const [converting, setConverting] = useState(false); const [converting, setConverting] = useState(false);
const [isFullscreen, setIsFullscreen] = useState(false);
const [sidebarOpen, setSidebarOpen] = useState(true);
useEffect(() => {
const handleFullscreenChange = () => {
setIsFullscreen(!!document.fullscreenElement);
};
document.addEventListener("fullscreenchange", handleFullscreenChange);
return () => {
document.removeEventListener("fullscreenchange", handleFullscreenChange);
};
}, []);
const handleRecenter = useCallback(() => {
const camera = mainCameraRef.current;
const controls = mainControlsRef.current;
if (camera) {
camera.position.set(2, 2, 2);
camera.up.set(0, 1, 0);
camera.lookAt(0, 0, 0);
}
if (controls) {
// @ts-ignore
controls.target.set(0, 0, 0);
// @ts-ignore
controls.update();
}
toast.success("Visualização centralizada");
}, []);
const exitFullscreen = useCallback(() => {
if (document.fullscreenElement) {
document.exitFullscreen().catch((err) => {
console.error("Erro ao sair de tela cheia:", err);
});
}
}, []);
const [searchParams] = useSearchParams(); const [searchParams] = useSearchParams();
const roomId = searchParams.get("room"); const roomId = searchParams.get("room");
const channelRef = useRef<ReturnType<typeof supabase.channel> | null>(null); const channelRef = useRef<ReturnType<typeof supabase.channel> | null>(null);
@@ -325,15 +364,51 @@ const Viewer = () => {
<div className="flex flex-1 overflow-hidden"> <div className="flex flex-1 overflow-hidden">
{/* 3D Canvas with floating controls */} {/* 3D Canvas with floating controls */}
<div className="relative flex-1"> <div className="relative flex-1" id="canvas-container">
<ModelViewerCanvas /> <ModelViewerCanvas />
<ViewCube /> {isFullscreen ? (
<ViewerControls /> <div className="absolute top-4 left-4 z-50 flex gap-2">
<SectionCutPanel /> <Button
variant="outline"
className="gap-2 bg-background/80 border-primary/40 hover:bg-primary/20 text-foreground font-mono shadow-md backdrop-blur-sm h-9"
onClick={handleRecenter}
>
<Target className="h-4 w-4 text-primary animate-pulse" />
Centralizar
</Button>
<Button
variant="outline"
className="gap-2 bg-background/80 border-destructive/40 hover:bg-destructive/20 text-foreground font-mono shadow-md backdrop-blur-sm h-9"
onClick={exitFullscreen}
>
<ArrowLeft className="h-4 w-4 text-destructive" />
Retornar (ESC)
</Button>
</div>
) : (
<>
{/* Botão de Toggle do Sidebar */}
<Button
variant="outline"
size="icon"
onClick={() => setSidebarOpen(!sidebarOpen)}
className={`absolute z-30 h-8 w-8 rounded-md bg-background/80 border-primary/30 text-primary shadow-md hover:bg-primary/10 transition-all duration-300 ${
sidebarOpen ? "right-[332px]" : "right-4"
} top-[205px]`}
title={sidebarOpen ? "Recolher menu" : "Expandir menu"}
>
<Menu className="h-4 w-4" />
</Button>
<ViewCube />
<ViewerControls />
<SectionCutPanel />
</>
)}
</div> </div>
{/* Side panel */} {/* Side panel */}
<aside className="w-80 shrink-0 border-l bg-card"> <aside className={`transition-all duration-300 border-l bg-card flex flex-col ${sidebarOpen ? 'w-80 opacity-100' : 'w-0 opacity-0 pointer-events-none border-l-0 overflow-hidden'}`}>
<ScrollArea className="h-full"> <ScrollArea className="h-full">
<div className="p-4 space-y-5"> <div className="p-4 space-y-5">
<div> <div>