Get image upload to cloudinary with the same public id

This means we can put a consistent url in the head for the card image
This commit is contained in:
Kurt Hutten
2021-08-14 15:19:48 +10:00
parent 50e9ac61f8
commit 32155ba98c
17 changed files with 425 additions and 77 deletions

View File

@@ -4,8 +4,19 @@ import Popover from '@material-ui/core/Popover'
import Svg from 'src/components/Svg/Svg'
import Button from 'src/components/Button/Button'
import { useIdeContext } from 'src/helpers/hooks/useIdeContext'
import { canvasToBlob, blobTo64 } from 'src/helpers/canvasToBlob'
import { useUpdateProject } from 'src/helpers/hooks/useUpdateProject'
import { uploadToCloudinary } from 'src/helpers/cloudinary'
import {
useUpdateSocialCard,
makeSocialPublicId,
} from 'src/helpers/hooks/useUpdateSocialCard'
import {
uploadToCloudinary,
serverVerifiedImageUpload,
} from 'src/helpers/cloudinary'
import SocialCardCell from 'src/components/SocialCardCell/SocialCardCell'
import { toJpeg } from 'html-to-image'
import { useAuth } from '@redwoodjs/auth'
const anchorOrigin = {
vertical: 'bottom',
@@ -16,51 +27,50 @@ const transformOrigin = {
horizontal: 'center',
}
const CaptureButton = ({ canEdit, TheButton, shouldUpdateImage }) => {
const CaptureButton = ({
canEdit,
TheButton,
shouldUpdateImage,
projectTitle,
userName,
}) => {
const [captureState, setCaptureState] = useState<any>({})
const [anchorEl, setAnchorEl] = useState(null)
const [whichPopup, setWhichPopup] = useState(null)
const { state, project } = useIdeContext()
const ref = React.useRef<HTMLDivElement>(null)
const { updateProject } = useUpdateProject({
onCompleted: () => toast.success('Image updated'),
})
const { updateSocialCard } = useUpdateSocialCard({})
const { getToken } = useAuth()
const getSocialBlob = async (): Promise<string> => {
const tokenPromise = getToken()
const blob = await toJpeg(ref.current, { cacheBust: true, quality: 0.75 })
const token = await tokenPromise
const { publicId } = await serverVerifiedImageUpload(
blob,
project?.id,
token,
makeSocialPublicId(userName, projectTitle)
)
return publicId
}
const onCapture = async () => {
const threeInstance = state.threeInstance
const isOpenScadImage = state?.objectData?.type === 'png'
let imgBlob
let image64
if (!isOpenScadImage) {
const updateCanvasSize = ({
width,
height,
}: {
width: number
height: number
}) => {
threeInstance.camera.aspect = width / height
threeInstance.camera.updateProjectionMatrix()
threeInstance.gl.setSize(width, height)
threeInstance.gl.render(
threeInstance.scene,
threeInstance.camera,
null,
false
)
}
const oldSize = threeInstance.size
updateCanvasSize({ width: 400, height: 300 })
imgBlob = new Promise((resolve, reject) => {
threeInstance.gl.domElement.toBlob(
(blob) => {
resolve(blob)
},
'image/jpeg',
1
)
})
updateCanvasSize(oldSize)
imgBlob = canvasToBlob(threeInstance, { width: 400, height: 300 })
image64 = blobTo64(
await canvasToBlob(threeInstance, { width: 500, height: 522 })
)
} else {
imgBlob = state.objectData.data
image64 = blobTo64(state.objectData.data)
}
const config = {
image: await imgBlob,
@@ -69,11 +79,22 @@ const CaptureButton = ({ canEdit, TheButton, shouldUpdateImage }) => {
callback: uploadAndUpdateImage,
cloudinaryImgURL: '',
updated: false,
image64: await image64,
}
setCaptureState(config)
async function uploadAndUpdateImage() {
// Upload the image to Cloudinary
const cloudinaryImgURL = await uploadToCloudinary(config.image)
const [cloudinaryImgURL, socialCloudinaryURL] = await Promise.all([
uploadToCloudinary(config.image),
getSocialBlob(),
])
updateSocialCard({
variables: {
projectId: project?.id,
url: socialCloudinaryURL,
},
})
// Save the screenshot as the mainImage
updateProject({
@@ -92,9 +113,8 @@ const CaptureButton = ({ canEdit, TheButton, shouldUpdateImage }) => {
if (shouldUpdateImage) {
config.cloudinaryImgURL = (await uploadAndUpdateImage()).public_id
config.updated = true
setCaptureState(config)
}
return config
}
const handleDownload = (url) => {
@@ -123,7 +143,7 @@ const CaptureButton = ({ canEdit, TheButton, shouldUpdateImage }) => {
<TheButton
onClick={async (event) => {
handleClick({ event, whichPopup: 'capture' })
setCaptureState(await onCapture())
onCapture()
}}
/>
<Popover
@@ -163,7 +183,7 @@ const CaptureButton = ({ canEdit, TheButton, shouldUpdateImage }) => {
name="refresh"
className="mr-2 w-4 text-indigo-600"
/>{' '}
Update Part Image
Update Project Image
</button>
) : (
<div className="flex justify-center mb-4">
@@ -187,6 +207,20 @@ const CaptureButton = ({ canEdit, TheButton, shouldUpdateImage }) => {
</div>
</div>
)}
<div className="rounded-lg shadow-md mt-4 overflow-hidden">
<div
className="transform scale-50 origin-top-left"
style={{ width: '600px', height: '315px' }}
>
<div style={{ width: '1200px', height: '630px' }} ref={ref}>
<SocialCardCell
userName={userName}
projectTitle={projectTitle}
image64={captureState.image64}
/>
</div>
</div>
</div>
</div>
</Popover>
</div>

View File

@@ -37,12 +37,13 @@ export const Failure = ({ error }: CellFailureProps) => (
export const Success = ({
userProject,
variables: { image64 },
}: CellSuccessProps<FindSocialCardQuery>) => {
const image = userProject?.Project?.mainImage
const gravatar = userProject?.image
return (
<div
className="flex-col flex h-screen bg-ch-gray-800 text-ch-gray-300"
className="flex-col flex h-full bg-ch-gray-800 text-ch-gray-300"
id="social-card-loaded"
>
<div
@@ -65,7 +66,7 @@ export const Success = ({
{gravatar && (
<Gravatar image={gravatar} className="w-14 h-14" size={60} />
)}
<div className="text-2xl font-fira-sans ml-6">
<div className="text-2xl font-fira-sans ml-6 whitespace-nowrap">
{userProject?.userName}
</div>
</div>
@@ -86,13 +87,19 @@ export const Success = ({
</div>
<div className="h-full overflow-hidden relative">
<div className="absolute inset-0 flex items-center justify-center">
<CloudinaryImage
cloudName="irevdev"
publicId={image || 'CadHub/eia1kwru54g2kf02s2xx'}
width={500}
height={522}
crop="crop"
/>
{image64 ? (
<div
style={{ backgroundImage: `url(${image64})` }}
className="w-full h-full bg-no-repeat bg-center"
/>
) : (
<div
style={{
backgroundImage: `url(http://res.cloudinary.com/irevdev/image/upload/c_crop,h_522,w_500/v1/${image})`,
}}
className="w-full h-full bg-no-repeat bg-center bg-blend-difference bg-contain bg-ch-gray-800"
/>
)}
</div>
</div>
</div>
@@ -133,7 +140,7 @@ export const Success = ({
CadHub
</h2>
<div
className="text-pink-400 text-sm font-bold font-ropa-sans hidden md:block"
className="text-pink-400 text-sm font-bold font-ropa-sans hidden md:block whitespace-nowrap"
style={{ paddingBottom: '2rem', marginLeft: '-1.8rem' }}
>
pre-alpha