diff --git a/website/src/repl/Repl.jsx b/website/src/repl/Repl.jsx index f2aec277e..49c0940cb 100644 --- a/website/src/repl/Repl.jsx +++ b/website/src/repl/Repl.jsx @@ -138,9 +138,7 @@ export function Repl({ embedded = false }) {
{ - window.postMessage('strudel-container'); - }} + ref={() => window.postMessage('strudel-container')} > {/* */}
diff --git a/website/src/repl/Repl2.jsx b/website/src/repl/Repl2.jsx new file mode 100644 index 000000000..49c0940cb --- /dev/null +++ b/website/src/repl/Repl2.jsx @@ -0,0 +1,154 @@ +/* +App.js - +Copyright (C) 2022 Strudel contributors - see +This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . +*/ + +import PlayCircleIcon from '@heroicons/react/20/solid/PlayCircleIcon'; +import { getDrawContext, logger, $replstate, $repldirty } from '@strudel.cycles/core'; +import { cx } from '@strudel.cycles/react'; +import { getAudioContext } from '@strudel.cycles/webaudio'; +import { writeText } from '@tauri-apps/api/clipboard'; +import { nanoid } from 'nanoid'; +import { createContext, useState } from 'react'; +import { useSettings } from '../settings.mjs'; +import { isTauri } from '../tauri.mjs'; +import { Footer } from './Footer'; +import { Header } from './Header'; +import Loader from './Loader'; +import './Repl.css'; +import { resetSounds } from './prebake.mjs'; +import { useStore } from '@nanostores/react'; + +let clearCanvas; +if (typeof window !== 'undefined') { + const drawContext = getDrawContext(); + clearCanvas = () => drawContext.clearRect(0, 0, drawContext.canvas.height, drawContext.canvas.width); +} + +export const ReplContext = createContext(null); + +export function Repl({ embedded = false }) { + //const isEmbedded = embedded || window.location !== window.parent.location; + const isEmbedded = false; + const [lastShared, setLastShared] = useState(); + const { panelPosition, isZen } = useSettings(); + const replState = useStore($replstate); + const isDirty = useStore($repldirty); + + // + // UI Actions + // + + const handleTogglePlay = async () => { + window.postMessage('strudel-toggle-play'); + /* await getAudioContext().resume(); // fixes no sound in ios webkit + if (!started) { + logger('[repl] started. tip: you can also start by pressing ctrl+enter', 'highlight'); + activateCode(); + } else { + logger('[repl] stopped. tip: you can also stop by pressing ctrl+dot', 'highlight'); + stop(); + } */ + }; + const handleUpdate = () => { + isDirty && activateCode(); + logger('[repl] code updated! tip: you can also update the code by pressing ctrl+enter', 'highlight'); + }; + + const handleShuffle = async () => { + const { code, name } = getRandomTune(); + logger(`[repl] ✨ loading random tune "${name}"`); + clearCanvas(); + await resetSounds(); + // scheduler.setCps(1); + await evaluate(code, false); + }; + + const handleShare = async () => { + const codeToShare = activeCode || code; + if (lastShared === codeToShare) { + logger(`Link already generated!`, 'error'); + return; + } + // generate uuid in the browser + const hash = nanoid(12); + const shareUrl = window.location.origin + window.location.pathname + '?' + hash; + const { data, error } = await supabase.from('code').insert([{ code: codeToShare, hash }]); + if (!error) { + setLastShared(activeCode || code); + // copy shareUrl to clipboard + if (isTauri()) { + await writeText(shareUrl); + } else { + await navigator.clipboard.writeText(shareUrl); + } + const message = `Link copied to clipboard: ${shareUrl}`; + alert(message); + // alert(message); + logger(message, 'highlight'); + } else { + console.log('error', error); + const message = `Error: ${error.message}`; + // alert(message); + logger(message); + } + }; + const pending = false; + const error = undefined; + const { started, activeCode } = replState; + + const context = { + // scheduler, + embedded, + started, + pending, + isDirty, + lastShared, + activeCode, + // handleChangeCode: codemirror.handleChangeCode, + handleTogglePlay, + handleUpdate, + handleShuffle, + handleShare, + }; + + return ( + // bg-gradient-to-t from-blue-900 to-slate-900 + // bg-gradient-to-t from-green-900 to-slate-900 + +
+ +
+ {/* isEmbedded && !started && ( + + ) */} +
+
window.postMessage('strudel-container')} + > + {/* */} +
+ {panelPosition === 'right' && !isEmbedded &&
} +
+ {error && ( +
{error.message || 'Unknown Error :-/'}
+ )} + {panelPosition === 'bottom' && !isEmbedded &&
+
+ ); +} diff --git a/website/src/repl/VanillaRepl.astro b/website/src/repl/VanillaRepl.astro index 34ba9c5ec..6c5ff0e73 100644 --- a/website/src/repl/VanillaRepl.astro +++ b/website/src/repl/VanillaRepl.astro @@ -1,6 +1,6 @@ --- import HeadCommon from '../components/HeadCommon.astro'; -import { Repl } from '../repl/Repl.jsx'; +import { Repl } from '../repl/Repl2.jsx'; ---