diff --git a/index.js b/index.js index 7fd587a..922f2d2 100644 --- a/index.js +++ b/index.js @@ -32,10 +32,11 @@ jss.createStyleSheet({ } }).attach(); -const { file, selectedPrinter } = queryString.parse(location.search); +let { file, selectedPrinter, actions } = queryString.parse(location.search); +if (actions) actions = JSON.parse(actions); render(( - + ), document.getElementById('app')); diff --git a/src/interface/index.js b/src/interface/index.js index 0903562..4b2edee 100644 --- a/src/interface/index.js +++ b/src/interface/index.js @@ -113,10 +113,18 @@ class Interface extends React.Component { onCancel: PropTypes.func, name: PropTypes.string.isRequired, muiTheme: PropTypes.object.isRequired, - allowDragDrop: PropTypes.bool.isRequired + allowDragDrop: PropTypes.bool.isRequired, + actions: PropTypes.arrayOf(PropTypes.shape({ type: PropTypes.string })) }; static defaultProps = { + actions: [{ + type: 'WIFI_PRINT', + title: 'Print over WiFi' + }, { + type: 'DOWNLOAD', + title: 'Download GCode' + }], pixelRatio: 1, name: 'Doodle3D', allowDragDrop: true @@ -223,7 +231,7 @@ class Interface extends React.Component { } }; - slice = async (target) => { + slice = async (action) => { const { isSlicing, settings, mesh, scene: { material, mesh: { matrix } } } = this.state; const { name } = this.props; @@ -232,7 +240,7 @@ class Interface extends React.Component { this.setState({ error: 'please select a printer first' }); return; } - if (target === 'WIFI' && !settings.ip) { + if (action.target === 'WIFI_PRINT' && !settings.ip) { this.setState({ error: 'please connect to a WiFi enabled printer' }); return; } @@ -249,7 +257,7 @@ class Interface extends React.Component { try { const updateProgres = progress => this.setState({ progress: { ...this.state.progress, ...progress } }); - await slice(target, name, exportMesh, settings, updateProgres); + await slice(action, name, exportMesh, settings, updateProgres); } catch (error) { this.setState({ error: error.message }); throw error; @@ -333,7 +341,7 @@ class Interface extends React.Component { } render() { - const { classes, onCancel, selectedPrinter } = this.props; + const { classes, onCancel, selectedPrinter, actions } = this.props; const { isSlicing, progress, showFullScreen, error, objectDimensions, settings } = this.state; const style = { ...(showFullScreen ? {} : { maxWidth: 'inherit', width: '100%', height: '100%' }) }; @@ -361,26 +369,39 @@ class Interface extends React.Component { : ) */} - - - - this.slice('WIFI')} /> - this.slice('DOWNLOAD')} /> - - + {actions.length === 1 ? ( + this.slice(actions[0])} + className={`${classes.button}`} + disabled={isSlicing} + /> + ) : ( + + + + + {actions.map((action) => ( + this.slice(action)} /> + ))} + + + + )} diff --git a/src/interface/utils.js b/src/interface/utils.js index 1db8e1c..f527280 100644 --- a/src/interface/utils.js +++ b/src/interface/utils.js @@ -143,15 +143,15 @@ export function sleep(time) { const GCODE_SERVER_URL = 'https://gcodeserver.doodle3d.com'; -export async function slice(target, name, mesh, settings, updateProgress) { +export async function slice(action, name, mesh, settings, updateProgress) { let steps; let currentStep = 0; let wifiBox; - switch (target) { + switch (action.target) { case 'DOWNLOAD': steps = 1; break; - case 'WIFI': + case 'WIFI_PRINT': if (settings.printer === 'doodle3d_printer') { const { state } = await getMalyanStatus(settings.ip); if (state !== 'idle') throw { message: 'printer is busy', code: 0 }; @@ -165,6 +165,9 @@ export async function slice(target, name, mesh, settings, updateProgress) { } steps = 2; break; + case 'CUSTOM_UPLOAD': + steps = 2; + break; default: throw { message: 'unknown target', code: 1 }; break; @@ -185,14 +188,14 @@ export async function slice(target, name, mesh, settings, updateProgress) { }); currentStep ++; - switch (target) { + switch (action.target) { case 'DOWNLOAD': { const file = new Blob([gcode], { type: 'text/plain' }); fileSaver.saveAs(file, `${name}.gcode`); break; } - case 'WIFI': { + case 'WIFI_PRINT': { if (settings.printer === 'doodle3d_printer') { const body = new FormData(); const file = new Blob([gcode], { type: 'plain/text' }); @@ -251,6 +254,25 @@ export async function slice(target, name, mesh, settings, updateProgress) { } break; } + case 'CUSTOM_UPLOAD': { + const body = new FormData(); + const file = new Blob([`;${JSON.stringify({ + ...settings, + name: `${name}.gcode`, + printer: { type: settings.printers, title: printerSettings[settings.printer].title }, + material: { type: settings.material, title: materialSettings[settings.material].title }, + quality: { type: settings.quality, title: qualitySettings[settings.quality].title } + }).trim()}\n${gcode}`]); + body.append('file', file, 'doodle.gcode'); + + await fetchProgress(action.url, { method: 'POST', body }, progress => { + updateProgress({ + action: 'Uploading', + percentage: (currentStep + progress.loaded / progress.total) / steps + }); + }); + currentStep ++; + } default: throw { message: 'unknown target', code: 1 };