import { useNavigate, useSearchParams } from 'react-router-dom';
import { ArrowLeft } from 'lucide-react';
import { useTranslation } from 'react-i18next';
export function GCodeViewerPage() {
const navigate = useNavigate();
const [searchParams] = useSearchParams();
const { t } = useTranslation();
// Safety guard: if this React app is itself inside an iframe (e.g. the
// StaticFiles mount isn't registered and serve_spa returned us here),
// don't render another iframe — that would create an infinite loop.
if (window !== window.top) {
return (
GCode viewer static files not found. Check that the{' '}
gcode_viewer/ directory exists and restart uvicorn.
);
}
const cameFromArchive = searchParams.has('archive');
const cameFromLibrary = searchParams.has('library_file');
const fallbackPath = cameFromArchive ? '/archives' : cameFromLibrary ? '/files' : '/';
const backLabel = cameFromArchive
? t('gcodeViewer.backToArchives')
: cameFromLibrary
? t('gcodeViewer.backToFiles')
: t('gcodeViewer.back');
const handleBack = () => {
// Prefer browser history so we land where the user actually was (preserving
// scroll position, filters, etc.). Fall back to a sensible default route
// when the viewer was opened from a fresh tab / shared link.
if (window.history.length > 1) {
navigate(-1);
} else {
navigate(fallbackPath);
}
};
// Forward the outer page's query string (e.g. ?archive=82) to the iframe so
// the adapter inside can pick up the archive to load. The iframe itself must
// keep the trailing slash on /gcode-viewer/ so it hits the raw-viewer route;
// the outer SPA URL uses no trailing slash so a reload falls through to the
// SPA catch-all and keeps the Bambuddy layout shell.
const iframeSrc = `/gcode-viewer/${window.location.search}`;
return (
// h-14 (3.5 rem) is the fixed header height defined in Layout.tsx.
// Subtracting it prevents a double scrollbar inside the layout shell.
);
}