Files
cadhub/app/web/src/components/IdeToolbarNew/IdeToolbarNew.js
Kurt Hutten 053b1d642c Improve script URL ecoding
added some magic to get scripts to efficiently encoded into the URL.
We're using pako to compress the script, but this outputs to a 8bit
array. Stringifying this array adds a lot of overhead, because "125"
has three characters in it.
Instead we're using the character codes to turn these a bit numbers
into single characters base64 is used as well because not all of the
characters are allowed in a url (and b64 is better than
encodeURIComponent).
2021-05-08 09:07:54 +10:00

81 lines
2.5 KiB
JavaScript

import { createContext, useEffect } from 'react'
import IdeContainer from 'src/components/IdeContainer'
import { isBrowser } from '@redwoodjs/prerender/browserUtils'
import { useIdeState, codeStorageKey } from 'src/helpers/hooks/useIdeState'
import { copyTextToClipboard } from 'src/helpers/clipboard'
import { requestRender } from 'src/helpers/hooks/useIdeState'
import { encode, decode } from 'src/helpers/compress'
export const IdeContext = createContext()
const IdeToolbarNew = ({ cadPackage }) => {
const [state, thunkDispatch] = useIdeState()
const scriptKey = 'encoded_script'
const scriptKeyV2 = 'encoded_script_v2'
useEffect(() => {
thunkDispatch({
type: 'initIde',
payload: { cadPackage },
})
// load code from hash if it's there
let hash
if (isBrowser) {
hash = window.location.hash
}
const [key, encodedScript] = hash.slice(1).split('=')
if (key === scriptKey) {
const script = atob(encodedScript)
thunkDispatch({ type: 'updateCode', payload: script })
} else if (key === scriptKeyV2) {
const script = decode(encodedScript)
thunkDispatch({ type: 'updateCode', payload: script })
}
window.location.hash = ''
setTimeout(() => handleRender()) // definitely a little hacky, timeout with no delay is just to push it into the next event loop.
}, [cadPackage])
function handleRender() {
thunkDispatch((dispatch, getState) => {
const state = getState()
dispatch({ type: 'setLoading' })
requestRender({
state,
dispatch,
code: state.code,
viewerSize: state.viewerSize,
camera: state.camera,
})
})
localStorage.setItem(codeStorageKey, state.code)
}
function handleMakeLink() {
if (isBrowser) {
const encodedScript = encode(state.code)
window.location.hash = `${scriptKeyV2}=${encodedScript}`
copyTextToClipboard(window.location.href)
}
}
return (
<IdeContext.Provider value={{ state, thunkDispatch }}>
<div className="h-full flex flex-col">
<nav className="flex">
<button
onClick={handleRender}
className="border-2 px-2 text-gray-700 text-sm m-1"
>
Render
</button>
<button
onClick={handleMakeLink}
className="border-2 text-gray-700 px-2 text-sm m-1 ml-2"
>
Copy link
</button>
</nav>
<IdeContainer />
</div>
</IdeContext.Provider>
)
}
export default IdeToolbarNew