diff --git a/web/src/components/IdeCascadeStudio/IdeCascadeStudio.js b/web/src/components/IdeCascadeStudio/IdeCascadeStudio.js index 72cf624..42c75d1 100644 --- a/web/src/components/IdeCascadeStudio/IdeCascadeStudio.js +++ b/web/src/components/IdeCascadeStudio/IdeCascadeStudio.js @@ -3,6 +3,7 @@ import CascadeController from 'src/helpers/cascadeController' import IdeToolbar from 'src/components/IdeToolbar' import { useEffect, useState } from 'react' import { threejsViewport } from 'src/cascade/js/MainPage/CascadeState' +import { uploadToCloudinary } from 'src/helpers/cloudinary' const defaultExampleCode = `// Welcome to Cascade Studio! Here are some useful functions: // Translate(), Rotate(), Scale(), Union(), Difference(), Intersection() @@ -70,6 +71,41 @@ const IdeCascadeStudio = ({ part, saveCode, loading }) => { partTitle: part?.title, image: part?.user?.image, }} + onCapture={ async () => { + const config = { + currImage: part?.mainImage, + callback: uploadAndUpdateImage, + cloudinaryImgURL: '', + updated: false, + } + // Get the canvas image as a Data URL + config.image = await CascadeController.capture(threejsViewport.environment) + config.imageObjectURL = window.URL.createObjectURL(config.image) + + async function uploadAndUpdateImage(){ + // Upload the image to Cloudinary + const cloudinaryImgURL = await uploadToCloudinary(config.image) + + // Save the screenshot as the mainImage + saveCode({ + input: { + mainImage: cloudinaryImgURL.public_id, + }, + id: part?.id, + isFork: !canEdit, + }) + + return cloudinaryImgURL + } + + // if there isn't a screenshot saved yet, just go ahead and save right away + if (!part || !part.mainImage) { + config.cloudinaryImgURL = await uploadAndUpdateImage().public_id + config.updated = true + } + + return config + }} /> > diff --git a/web/src/components/IdePartCell/IdePartCell.js b/web/src/components/IdePartCell/IdePartCell.js index 581a032..7a2975d 100644 --- a/web/src/components/IdePartCell/IdePartCell.js +++ b/web/src/components/IdePartCell/IdePartCell.js @@ -50,7 +50,7 @@ export const Success = ({ part, refetch }) => { const { user } = useUser() const [updatePart, { loading, error }] = useMutation(UPDATE_PART_MUTATION, { onCompleted: () => { - addMessage('Part updated.', { classes: 'rw-flash-success' }) + addMessage('Part updated.', { classes: 'rw-flash-success fixed w-screen z-10' }) }, }) const [forkPart] = useMutation(FORK_PART_MUTATION, { diff --git a/web/src/components/IdeToolbar/IdeToolbar.js b/web/src/components/IdeToolbar/IdeToolbar.js index ba5307a..337b863 100644 --- a/web/src/components/IdeToolbar/IdeToolbar.js +++ b/web/src/components/IdeToolbar/IdeToolbar.js @@ -23,6 +23,7 @@ const IdeToolbar = ({ userNamePart, isDraft, code, + onCapture, }) => { const [anchorEl, setAnchorEl] = useState(null) const [whichPopup, setWhichPopup] = useState(null) @@ -30,6 +31,7 @@ const IdeToolbar = ({ const { isAuthenticated, currentUser } = useAuth() const showForkButton = !(canEdit || isDraft) const [title, setTitle] = useState('untitled-part') + const [captureState, setCaptureState] = useState(false) const { user } = useUser() useKeyPress((e) => { const rx = /INPUT|SELECT|TEXTAREA/i @@ -104,6 +106,16 @@ const IdeToolbar = ({ setIsLoginModalOpen(true) } + const handleDownload = (url) => { + const aTag = document.createElement('a') + document.body.appendChild(aTag) + aTag.href= url + aTag.style.display = 'none' + aTag.download = `CadHub_${ Date.now() }.jpg` + aTag.click() + document.body.removeChild(aTag) + } + const anchorOrigin = { vertical: 'bottom', horizontal: 'center', @@ -219,6 +231,59 @@ const IdeToolbar = ({