Encode code into url to make sharing snippets easy

resolves #253
This commit is contained in:
Kurt Hutten
2021-03-16 20:26:58 +11:00
parent 03ce3530c1
commit 01bc76e09a
3 changed files with 73 additions and 5 deletions

View File

@@ -1,10 +1,30 @@
import { useContext } from 'react' import { useContext, useEffect } from 'react'
import { isBrowser } from '@redwoodjs/prerender/browserUtils'
import { IdeContext } from 'src/components/IdeToolbarNew' import { IdeContext } from 'src/components/IdeToolbarNew'
import Editor from '@monaco-editor/react' import Editor from '@monaco-editor/react'
const IdeEditor = () => { const IdeEditor = () => {
const { state, dispatch } = useContext(IdeContext) const { state, dispatch } = useContext(IdeContext)
const scriptKey = 'encoded_script'
useEffect(() => {
// load code from hash if it's there
let hash
if (isBrowser) {
hash = window.location.hash
}
const [key, scriptBase64] = hash.slice(1).split('=')
if (key === scriptKey) {
const script = atob(scriptBase64)
dispatch({ type: 'updateCode', payload: script })
}
}, [])
useEffect(() => {
if (isBrowser) {
window.location.hash = ''
}
}, [state.code])
function handleCodeChange(value, _event) { function handleCodeChange(value, _event) {
dispatch({ type: 'updateCode', payload: value }) dispatch({ type: 'updateCode', payload: value })
} }

View File

@@ -1,9 +1,10 @@
import IdeContainer from 'src/components/IdeContainer'
import { createContext } from 'react' import { createContext } from 'react'
import IdeContainer from 'src/components/IdeContainer'
import { isBrowser } from '@redwoodjs/prerender/browserUtils'
import { useIdeState } from 'src/helpers/hooks/useIdeState' import { useIdeState } from 'src/helpers/hooks/useIdeState'
import { copyTextToClipboard } from 'src/helpers/clipboard'
export const IdeContext = createContext() export const IdeContext = createContext()
const IdeToolbarNew = () => { const IdeToolbarNew = () => {
const [state, dispatch] = useIdeState() const [state, dispatch] = useIdeState()
function setIdeType(ide) { function setIdeType(ide) {
@@ -12,12 +13,19 @@ const IdeToolbarNew = () => {
function handleRender() { function handleRender() {
dispatch({ type: 'render', payload: { code: state.code } }) dispatch({ type: 'render', payload: { code: state.code } })
} }
function handleMakeLink() {
if (isBrowser) {
const scriptBase64 = btoa(state.code)
window.location.hash = `encoded_script=${scriptBase64}`
copyTextToClipboard(window.location.href)
}
}
return ( return (
<IdeContext.Provider value={{ state, dispatch }}> <IdeContext.Provider value={{ state, dispatch }}>
<div className="p-8 border-2"> <div className="p-8 border-2">
<nav className="flex"> <nav className="flex">
<button {/* <button
onClick={() => setIdeType('openCascade')} onClick={() => setIdeType('openCascade')}
className="p-2 br-2 border-2 m-2 bg-blue-200" className="p-2 br-2 border-2 m-2 bg-blue-200"
> >
@@ -28,10 +36,13 @@ const IdeToolbarNew = () => {
className="p-2 br-2 border-2 m-2 bg-indigo-200" className="p-2 br-2 border-2 m-2 bg-indigo-200"
> >
Switch to OpenSCAD Switch to OpenSCAD
</button> </button> */}
<button onClick={handleRender} className="p-2 br-2 border-2 m-2"> <button onClick={handleRender} className="p-2 br-2 border-2 m-2">
Render Render
</button> </button>
<button onClick={handleMakeLink} className="p-2 br-2 border-2 m-2">
Copy link
</button>
</nav> </nav>
<IdeContainer /> <IdeContainer />
</div> </div>

View File

@@ -0,0 +1,37 @@
function fallbackCopyTextToClipboard(text) {
var textArea = document.createElement('textarea')
textArea.value = text
// Avoid scrolling to bottom
textArea.style.top = '0'
textArea.style.left = '0'
textArea.style.position = 'fixed'
document.body.appendChild(textArea)
textArea.focus()
textArea.select()
try {
var successful = document.execCommand('copy')
var msg = successful ? 'successful' : 'unsuccessful'
console.log('Fallback: Copying text command was ' + msg)
} catch (err) {
console.error('Fallback: Oops, unable to copy', err)
}
document.body.removeChild(textArea)
}
export function copyTextToClipboard(text) {
if (!navigator.clipboard) {
fallbackCopyTextToClipboard(text)
return
}
navigator.clipboard.writeText(text).then(
function () {
console.log('Async: Copying to clipboard was successful!')
},
function (err) {
console.error('Async: Could not copy text: ', err)
}
)
}