diff --git a/navi/main.py b/navi/main.py index d299c9d..305c4b6 100644 --- a/navi/main.py +++ b/navi/main.py @@ -152,6 +152,17 @@ pass +from fastapi.responses import RedirectResponse + + +@app.get("/sessions/{session_id}/files/{filename}", include_in_schema=False) +async def legacy_session_file_redirect(session_id: str, filename: str, download: bool = False): + target = f"/api/sessions/{session_id}/files/{filename}" + if download: + target += "?download=1" + return RedirectResponse(url=target, status_code=301) + + @app.get("/", include_in_schema=False) async def index() -> FileResponse: return FileResponse(str(_base / "webclient" / "dist" / "index.html"), headers={"Cache-Control": "no-store"}) diff --git a/webclient/dist/content-viewers/stl.html b/webclient/dist/content-viewers/stl.html index 7c39978..233fa99 100644 --- a/webclient/dist/content-viewers/stl.html +++ b/webclient/dist/content-viewers/stl.html @@ -63,63 +63,64 @@ + 'Try enabling hardware acceleration or a different browser.

' + ''; console.error('WebGL init failed:', err); - throw err; } - const controls = new OrbitControls(camera, renderer.domElement); - controls.enableDamping = true; - controls.dampingFactor = 0.05; - controls.autoRotate = true; - controls.autoRotateSpeed = 1; + if (renderer) { + const controls = new OrbitControls(camera, renderer.domElement); + controls.enableDamping = true; + controls.dampingFactor = 0.05; + controls.autoRotate = true; + controls.autoRotateSpeed = 1; - // Lights - scene.add(new THREE.AmbientLight(0x404040, 2)); - const dirLight = new THREE.DirectionalLight(0xffffff, 2); - dirLight.position.set(5, 10, 7); - scene.add(dirLight); - const backLight = new THREE.DirectionalLight(0x4444ff, 1); - backLight.position.set(-5, -5, -5); - scene.add(backLight); + // Lights + scene.add(new THREE.AmbientLight(0x404040, 2)); + const dirLight = new THREE.DirectionalLight(0xffffff, 2); + dirLight.position.set(5, 10, 7); + scene.add(dirLight); + const backLight = new THREE.DirectionalLight(0x4444ff, 1); + backLight.position.set(-5, -5, -5); + scene.add(backLight); - // Load STL - const loader = new STLLoader(); - loader.load(url, (geometry) => { - document.getElementById('loading').style.display = 'none'; + // Load STL + const loader = new STLLoader(); + loader.load(url, (geometry) => { + document.getElementById('loading').style.display = 'none'; - geometry.computeBoundingSphere(); - const center = geometry.boundingSphere.center; - const radius = geometry.boundingSphere.radius; + geometry.computeBoundingSphere(); + const center = geometry.boundingSphere.center; + const radius = geometry.boundingSphere.radius; - const material = new THREE.MeshStandardMaterial({ - color: 0xe0af68, - metalness: 0.12, - roughness: 0.55, + const material = new THREE.MeshStandardMaterial({ + color: 0xe0af68, + metalness: 0.12, + roughness: 0.55, + }); + const mesh = new THREE.Mesh(geometry, material); + mesh.position.sub(center); + scene.add(mesh); + + // Auto-scale camera + camera.position.setLength(radius * 3); + controls.target.set(0, 0, 0); + controls.update(); + }, undefined, (err) => { + document.getElementById('loading').textContent = 'Failed to load model'; + console.error(err); }); - const mesh = new THREE.Mesh(geometry, material); - mesh.position.sub(center); - scene.add(mesh); - // Auto-scale camera - camera.position.setLength(radius * 3); - controls.target.set(0, 0, 0); - controls.update(); - }, undefined, (err) => { - document.getElementById('loading').textContent = 'Failed to load model'; - console.error(err); - }); + function animate() { + requestAnimationFrame(animate); + controls.update(); + renderer.render(scene, camera); + } + animate(); - function animate() { - requestAnimationFrame(animate); - controls.update(); - renderer.render(scene, camera); + addEventListener('resize', () => { + camera.aspect = innerWidth / innerHeight; + camera.updateProjectionMatrix(); + renderer.setSize(innerWidth, innerHeight); + }); } - animate(); - - addEventListener('resize', () => { - camera.aspect = innerWidth / innerHeight; - camera.updateProjectionMatrix(); - renderer.setSize(innerWidth, innerHeight); - }); diff --git a/webclient/public/content-viewers/stl.html b/webclient/public/content-viewers/stl.html index 7c39978..233fa99 100644 --- a/webclient/public/content-viewers/stl.html +++ b/webclient/public/content-viewers/stl.html @@ -63,63 +63,64 @@ + 'Try enabling hardware acceleration or a different browser.

' + ''; console.error('WebGL init failed:', err); - throw err; } - const controls = new OrbitControls(camera, renderer.domElement); - controls.enableDamping = true; - controls.dampingFactor = 0.05; - controls.autoRotate = true; - controls.autoRotateSpeed = 1; + if (renderer) { + const controls = new OrbitControls(camera, renderer.domElement); + controls.enableDamping = true; + controls.dampingFactor = 0.05; + controls.autoRotate = true; + controls.autoRotateSpeed = 1; - // Lights - scene.add(new THREE.AmbientLight(0x404040, 2)); - const dirLight = new THREE.DirectionalLight(0xffffff, 2); - dirLight.position.set(5, 10, 7); - scene.add(dirLight); - const backLight = new THREE.DirectionalLight(0x4444ff, 1); - backLight.position.set(-5, -5, -5); - scene.add(backLight); + // Lights + scene.add(new THREE.AmbientLight(0x404040, 2)); + const dirLight = new THREE.DirectionalLight(0xffffff, 2); + dirLight.position.set(5, 10, 7); + scene.add(dirLight); + const backLight = new THREE.DirectionalLight(0x4444ff, 1); + backLight.position.set(-5, -5, -5); + scene.add(backLight); - // Load STL - const loader = new STLLoader(); - loader.load(url, (geometry) => { - document.getElementById('loading').style.display = 'none'; + // Load STL + const loader = new STLLoader(); + loader.load(url, (geometry) => { + document.getElementById('loading').style.display = 'none'; - geometry.computeBoundingSphere(); - const center = geometry.boundingSphere.center; - const radius = geometry.boundingSphere.radius; + geometry.computeBoundingSphere(); + const center = geometry.boundingSphere.center; + const radius = geometry.boundingSphere.radius; - const material = new THREE.MeshStandardMaterial({ - color: 0xe0af68, - metalness: 0.12, - roughness: 0.55, + const material = new THREE.MeshStandardMaterial({ + color: 0xe0af68, + metalness: 0.12, + roughness: 0.55, + }); + const mesh = new THREE.Mesh(geometry, material); + mesh.position.sub(center); + scene.add(mesh); + + // Auto-scale camera + camera.position.setLength(radius * 3); + controls.target.set(0, 0, 0); + controls.update(); + }, undefined, (err) => { + document.getElementById('loading').textContent = 'Failed to load model'; + console.error(err); }); - const mesh = new THREE.Mesh(geometry, material); - mesh.position.sub(center); - scene.add(mesh); - // Auto-scale camera - camera.position.setLength(radius * 3); - controls.target.set(0, 0, 0); - controls.update(); - }, undefined, (err) => { - document.getElementById('loading').textContent = 'Failed to load model'; - console.error(err); - }); + function animate() { + requestAnimationFrame(animate); + controls.update(); + renderer.render(scene, camera); + } + animate(); - function animate() { - requestAnimationFrame(animate); - controls.update(); - renderer.render(scene, camera); + addEventListener('resize', () => { + camera.aspect = innerWidth / innerHeight; + camera.updateProjectionMatrix(); + renderer.setSize(innerWidth, innerHeight); + }); } - animate(); - - addEventListener('resize', () => { - camera.aspect = innerWidth / innerHeight; - camera.updateProjectionMatrix(); - renderer.setSize(innerWidth, innerHeight); - });