diff --git a/web/src/components/IdeContainer/IdeContainer.js b/web/src/components/IdeContainer/IdeContainer.js index 7a8a45d..08127d6 100644 --- a/web/src/components/IdeContainer/IdeContainer.js +++ b/web/src/components/IdeContainer/IdeContainer.js @@ -1,4 +1,4 @@ -import { useContext } from 'react' +import { useContext, useRef, useEffect } from 'react' import { Mosaic, MosaicWindow } from 'react-mosaic-component' import { IdeContext } from 'src/components/IdeToolbarNew' import IdeEditor from 'src/components/IdeEditor' @@ -7,25 +7,52 @@ import IdeConsole from 'src/components/IdeConsole' import 'react-mosaic-component/react-mosaic-component.css' const ELEMENT_MAP = { - Editor: , - Viewer: , - Console: , + Editor: , + Viewer: , + Console: , } const IdeContainer = () => { const { state, dispatch } = useContext(IdeContext) + const viewerDOM = useRef(null) - return (
- ( - - { ELEMENT_MAP[id] } - - )} - value={state.layout} - onChange={newLayout => dispatch({ type: 'updateLayout', payload: { message: newLayout } })} - /> -
) + useEffect(handleViewerSizeUpdate, [viewerDOM]) + + function handleViewerSizeUpdate() { + if (viewerDOM !== null && viewerDOM.current) { + const { width, height } = viewerDOM.current.getBoundingClientRect() + dispatch({ + type: 'render', + payload: { + code: state.code, + viewerSize: { width, height }, + }, + }) + } + } + + return ( +
+ ( + + {id === 'Viewer' ? ( +
+ {ELEMENT_MAP[id]} +
+ ) : ( + ELEMENT_MAP[id] + )} +
+ )} + value={state.layout} + onChange={(newLayout) => + dispatch({ type: 'setLayout', payload: { message: newLayout } }) + } + onRelease={handleViewerSizeUpdate} + /> +
+ ) } -export default IdeContainer \ No newline at end of file +export default IdeContainer diff --git a/web/src/components/IdeViewer/IdeViewer.js b/web/src/components/IdeViewer/IdeViewer.js index d8a27e5..c2248ee 100644 --- a/web/src/components/IdeViewer/IdeViewer.js +++ b/web/src/components/IdeViewer/IdeViewer.js @@ -137,56 +137,55 @@ const IdeViewer = () => { const indigo300 = '#A5B4FC' const indigo900 = '#312E81' return ( -
-
- {image && ( -
- -
- )} - {state.isLoading && ( -
-
-
- )} -
setIsDragging(true)} - > - - setIsDragging(true)} - onCameraChange={(camera) => { - dispatch({ - type: 'render', - payload: { - code: currentCode, - camera, - }, - }) - }} - /> - - - - - - - +
+ {state.isLoading && ( +
+
+ )} + {image && ( +
+ +
+ )} + {state.isLoading && ( +
+
+
+ )} +
setIsDragging(true)} + > + + setIsDragging(true)} + onCameraChange={(camera) => + dispatch({ + type: 'render', + payload: { + code: currentCode, + camera, + }, + }) + } + /> + + + + + + +
) diff --git a/web/src/helpers/cadPackages/openScadController.js b/web/src/helpers/cadPackages/openScadController.js index 630bf82..be52e94 100644 --- a/web/src/helpers/cadPackages/openScadController.js +++ b/web/src/helpers/cadPackages/openScadController.js @@ -2,34 +2,35 @@ let openScadBaseURL = process.env.OPENSCAD_BASE_URL || 'https://x2wvhihk56.execute-api.us-east-1.amazonaws.com/dev' -let lastCameraSettings = { - position: { - x: 200, - y: -20, - z: 140, - }, - rotation: { - x: 55, - y: 3.8, - z: 84, - }, - dist: 245, -} +let lastViewPortSize = 'INIT' +let lastCameraSettings = 'INIT' export const render = async ({ code, settings }) => { - const body = JSON.stringify({ - settings: { - size: { - x: 500, - y: 500, - }, - camera: settings.camera || lastCameraSettings, - }, - file: code, - }) + const size = settings.viewerSize + ? { + x: Math.round(settings.viewerSize?.width), + y: Math.round(settings.viewerSize?.height), + } + : lastViewPortSize + const camera = settings.camera || lastCameraSettings if (settings.camera) { lastCameraSettings = settings.camera } + if (settings.viewerSize) { + lastViewPortSize = size + } + if ([camera, size].includes('INIT')) { + return { + status: 'insufficient-preview-info', + } + } + const body = JSON.stringify({ + settings: { + size, + camera, + }, + file: code, + }) try { const response = await fetch(openScadBaseURL + '/render', { method: 'POST', @@ -45,7 +46,7 @@ export const render = async ({ code, settings }) => { "'main.scad'" ) return { - isError: true, + status: 'error', message: { type: 'error', message: cleanedErrorMessage, @@ -54,6 +55,7 @@ export const render = async ({ code, settings }) => { } const data = await response.blob() return { + status: 'healthy', objectData: { type: 'png', data, @@ -69,7 +71,7 @@ export const render = async ({ code, settings }) => { // and in future I think we need timeouts differently as they maybe from a user trying to render something too complex // or something with minkowski in it :/ either way something like "render timed out, try again or here are tips to reduce part complexity" with a link talking about $fn and minkowski etc return { - isError: true, + status: 'error', message: { type: 'error', message: 'network issue', diff --git a/web/src/helpers/hooks/useIdeState.js b/web/src/helpers/hooks/useIdeState.js index 15723f1..aba8d30 100644 --- a/web/src/helpers/hooks/useIdeState.js +++ b/web/src/helpers/hooks/useIdeState.js @@ -66,7 +66,7 @@ export const useIdeState = () => { ...state, ideType: payload.message, } - case 'updateLayout': + case 'setLayout': return { ...state, layout: payload.message, @@ -88,10 +88,14 @@ export const useIdeState = () => { cadPackages[state.ideType] .render({ code: payload.code, - settings: { camera: payload.camera }, + settings: { + camera: payload.camera, + viewerSize: payload.viewerSize, + }, }) - .then(({ objectData, message, isError }) => { - if (isError) { + .then(({ objectData, message, status }) => { + if (status === 'insufficient-preview-info') return + if (status === 'error') { dispatch({ type: 'errorRender', payload: { message },