diff --git a/packages/react/src/components/CodeMirror6.jsx b/packages/react/src/components/CodeMirror6.jsx
index beab8f17a..520d8b76a 100644
--- a/packages/react/src/components/CodeMirror6.jsx
+++ b/packages/react/src/components/CodeMirror6.jsx
@@ -135,7 +135,7 @@ export default function CodeMirror({
}
return _extensions;
- }, [keybindings, isAutoCompletionEnabled, isLineWrappingEnabled, onEvaluate, onReEvaluate, onStop]);
+ }, [keybindings, isAutoCompletionEnabled, isLineWrappingEnabled, onEvaluate, onReEvaluate, onStop, onPanic]);
const basicSetup = useMemo(() => ({ lineNumbers: isLineNumbersDisplayed }), [isLineNumbersDisplayed]);
diff --git a/website/src/repl/Repl.jsx b/website/src/repl/Repl.jsx
index d9eb7001e..98d889c9e 100644
--- a/website/src/repl/Repl.jsx
+++ b/website/src/repl/Repl.jsx
@@ -4,22 +4,21 @@ Copyright (C) 2022 Strudel contributors - see .
*/
-import { cleanupDraw, cleanupUi, controls, evalScope, getDrawContext, logger } from '@strudel.cycles/core';
-import { CodeMirror, cx, flash, useHighlighting, useStrudel, useKeydown } from '@strudel.cycles/react';
-import { getAudioContext, initAudioOnFirstClick, resetLoadedSounds, webaudioOutput } from '@strudel.cycles/webaudio';
+import { cleanupDraw, cleanupUi, getDrawContext, logger } from '@strudel.cycles/core';
+import { CodeMirror, cx, flash, useHighlighting, useStrudel } from '@strudel.cycles/react';
+import { getAudioContext, initAudioOnFirstClick, webaudioOutput } from '@strudel.cycles/webaudio';
import { createClient } from '@supabase/supabase-js';
import { nanoid } from 'nanoid';
import React, { createContext, useCallback, useEffect, useState, useMemo } from 'react';
import './Repl.css';
import { Footer } from './Footer';
import { Header } from './Header';
-import { prebake } from './prebake.mjs';
+import { prebake, resetSounds } from './prebake.mjs';
import * as tunes from './tunes.mjs';
import PlayCircleIcon from '@heroicons/react/20/solid/PlayCircleIcon';
import { themes } from './themes.mjs';
import { settingsMap, useSettings, setLatestCode } from '../settings.mjs';
import Loader from './Loader';
-import { settingPatterns } from '../settings.mjs';
import { code2hash, hash2code } from './helpers.mjs';
import { isTauri } from '../tauri.mjs';
import { useWidgets } from '@strudel.cycles/react/src/hooks/useWidgets.mjs';
@@ -35,35 +34,7 @@ const supabase = createClient(
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBpZHhkc3hwaGxoempuem1pZnRoIiwicm9sZSI6ImFub24iLCJpYXQiOjE2NTYyMzA1NTYsImV4cCI6MTk3MTgwNjU1Nn0.bqlw7802fsWRnqU5BLYtmXk_k-D1VFmbkHMywWc15NM',
);
-let modules = [
- import('@strudel.cycles/core'),
- import('@strudel.cycles/tonal'),
- import('@strudel.cycles/mini'),
- import('@strudel.cycles/xen'),
- import('@strudel.cycles/webaudio'),
- import('@strudel/codemirror'),
- import('@strudel/hydra'),
- import('@strudel.cycles/serial'),
- import('@strudel.cycles/soundfonts'),
- import('@strudel.cycles/csound'),
-];
-if (isTauri()) {
- modules = modules.concat([
- import('@strudel/desktopbridge/loggerbridge.mjs'),
- import('@strudel/desktopbridge/midibridge.mjs'),
- import('@strudel/desktopbridge/oscbridge.mjs'),
- ]);
-} else {
- modules = modules.concat([import('@strudel.cycles/midi'), import('@strudel.cycles/osc')]);
-}
-
-const modulesLoading = evalScope(
- controls, // sadly, this cannot be exported from core direclty
- settingPatterns,
- ...modules,
-);
-
-const presets = prebake();
+const init = prebake();
let drawContext, clearCanvas;
if (typeof window !== 'undefined') {
@@ -140,7 +111,7 @@ export function Repl({ embedded = false }) {
getTime,
beforeEval: async () => {
setPending(true);
- await modulesLoading;
+ await init;
cleanupUi();
cleanupDraw();
},
@@ -186,29 +157,6 @@ export function Repl({ embedded = false }) {
});
}, []);
- // keyboard shortcuts
- useKeydown(
- useCallback(
- async (e) => {
- if (e.ctrlKey || e.altKey) {
- if (e.code === 'Enter') {
- if (getAudioContext().state !== 'running') {
- alert('please click play to initialize the audio. you can use shortcuts after that!');
- return;
- }
- e.preventDefault();
- flash(view);
- await activateCode();
- } else if (e.key === '.' || e.code === 'Period') {
- stop();
- e.preventDefault();
- }
- }
- },
- [activateCode, stop, view],
- ),
- );
-
// highlighting
const { setMiniLocations } = useHighlighting({
view,
@@ -252,9 +200,8 @@ export function Repl({ embedded = false }) {
const { code, name } = getRandomTune();
logger(`[repl] ✨ loading random tune "${name}"`);
clearCanvas();
- resetLoadedSounds();
+ await resetSounds();
scheduler.setCps(1);
- await prebake(); // declare default samples
await evaluate(code, false);
};
@@ -306,6 +253,17 @@ export function Repl({ embedded = false }) {
setView(v);
}, []);
+ // Codemirror hooks
+ const onEvaluate = () => {
+ if (getAudioContext().state !== 'running') {
+ alert('please click play to initialize the audio. you can use shortcuts after that!');
+ return;
+ }
+ flash(view);
+ activateCode();
+ };
+ const onStop = () => stop();
+
return (
// bg-gradient-to-t from-blue-900 to-slate-900
// bg-gradient-to-t from-green-900 to-slate-900
@@ -341,6 +299,8 @@ export function Repl({ embedded = false }) {
onChange={handleChangeCode}
onViewChanged={handleViewChanged}
onSelectionChange={handleSelectionChange}
+ onEvaluate={onEvaluate}
+ onStop={onStop}
/>
{panelPosition === 'right' && !isEmbedded && }
diff --git a/website/src/repl/prebake.mjs b/website/src/repl/prebake.mjs
index 863a609ce..999311705 100644
--- a/website/src/repl/prebake.mjs
+++ b/website/src/repl/prebake.mjs
@@ -156,7 +156,7 @@ export async function prebake() {
export const resetSounds = () => {
soundMap.set({});
- registerStockSounds();
+ return registerStockSounds();
};
const maxPan = noteToMidi('C8');