diff --git a/packages/core/repl.mjs b/packages/core/repl.mjs index 9fb6b4b9..7c609d66 100644 --- a/packages/core/repl.mjs +++ b/packages/core/repl.mjs @@ -94,7 +94,6 @@ export function repl({ afterEval?.({ code, pattern, meta }); return pattern; } catch (err) { - // console.warn(`[repl] eval error: ${err.message}`); logger(`[eval] error: ${err.message}`, 'error'); updateState({ evalError: err, pending: false }); onEvalError?.(err); diff --git a/website/src/repl/Header.jsx b/website/src/repl/Header.jsx index f806d5d3..748b84e4 100644 --- a/website/src/repl/Header.jsx +++ b/website/src/repl/Header.jsx @@ -19,7 +19,7 @@ export function Header({ context }) { isDirty, activeCode, handleTogglePlay, - handleUpdate, + handleEvaluate, handleShuffle, handleShare, } = context; @@ -85,7 +85,7 @@ export function Header({ context }) { )} handleUpdate({})} + onClick={handleEvaluate} title="update" className={cx( 'flex items-center space-x-1', diff --git a/website/src/repl/Repl.jsx b/website/src/repl/Repl.jsx index 1c45c47f..faf4bb07 100644 --- a/website/src/repl/Repl.jsx +++ b/website/src/repl/Repl.jsx @@ -160,38 +160,25 @@ export function Repl({ embedded = false }) { // UI Actions // - const handleTogglePlay = async () => editorRef.current?.toggle(); + const handleTogglePlay = async () => { + editorRef.current?.toggle(); + }; - // payload = {reset?: boolean, code?: string, evaluate?: boolean, pattern?: string } - const handleUpdate = async (payload) => { - const { id, code } = payload; + const handleUpdate = (id, code) => { setViewingPattern(id); editorRef.current.setCode(code); + }; - // const { reset = false, code = null, evaluate = true, pattern = null } = payload; - - // if (reset) { - // clearCanvas(); - // resetLoadedSounds(); - // editorRef.current.repl.setCps(1); - // await prebake(); // declare default samples - // } - // if (code != null && pattern != null) { - // setViewingPattern(pattern); - // editorRef.current.setCode(code); - // } - // if (evaluate) { - // editorRef.current.evaluate(); - // } + const handleEvaluate = () => { + editorRef.current.evaluate(); }; const handleShuffle = async () => { - // window.postMessage('strudel-shuffle'); const { code, name } = getRandomTune(); logger(`[repl] ✨ loading random tune "${name}"`); setActivePattern(name); + setViewingPattern(name); clearCanvas(); resetLoadedSounds(); - editorRef.current.repl.setCps(1); await prebake(); // declare default samples editorRef.current.setCode(code); editorRef.current.repl.evaluate(code); @@ -208,6 +195,7 @@ export function Repl({ embedded = false }) { handleUpdate, handleShuffle, handleShare, + handleEvaluate, }; return ( diff --git a/website/src/repl/panel/PatternsTab.jsx b/website/src/repl/panel/PatternsTab.jsx index d8ce363e..25e1f575 100644 --- a/website/src/repl/panel/PatternsTab.jsx +++ b/website/src/repl/panel/PatternsTab.jsx @@ -30,7 +30,7 @@ function PatternButton({ showOutline, onClick, label, showHiglight }) { ); } -function PatternButtons({ patterns, activePattern, onClick, viewingPattern, isExample = false }) { +function PatternButtons({ patterns, activePattern, onClick, viewingPattern, started }) { return ( {Object.entries(patterns).map(([id]) => ( @@ -38,8 +38,8 @@ function PatternButtons({ patterns, activePattern, onClick, viewingPattern, isEx key={id} label={id} showHiglight={id === viewingPattern} - showOutline={id === activePattern} - onClick={() => onClick(id, isExample)} + showOutline={id === activePattern && started} + onClick={() => onClick(id)} /> ))} @@ -51,11 +51,10 @@ export function PatternsTab({ context }) { const examplePatterns = useMemo(() => examplePattern.getAll(), []); const activePattern = useActivePattern(); const viewingPattern = useViewingPattern(); - const updateCodeWindow = (id, code) => { - context.handleUpdate({ code, id, evaluate: false }); + context.handleUpdate(id, code); }; - const onPatternBtnClick = (id, isExample) => { + const onPatternBtnClick = (id, isExample = false) => { const code = isExample ? examplePatterns[id].code : userPatterns[id].code; // display selected pattern code in the window @@ -80,16 +79,12 @@ export function PatternsTab({ context }) { title="Rename" > - {/* */} )} { - const { id, data } = userPattern.duplicate( - viewingPattern, - userPatterns[viewingPattern]?.code ?? examplePatterns[viewingPattern]?.code, - ); + const { id, data } = userPattern.duplicate(viewingPattern); updateCodeWindow(id, data.code); }} title="Duplicate" @@ -101,7 +96,6 @@ export function PatternsTab({ context }) { className="hover:opacity-50" onClick={() => { const { id, data } = userPattern.delete(viewingPattern); - console.log({ id, data }); updateCodeWindow(id, data.code); }} title="Delete" @@ -115,6 +109,7 @@ export function PatternsTab({ context }) { @@ -155,8 +150,8 @@ export function PatternsTab({ context }) { Examples onPatternBtnClick(id, true)} + started={context.started} patterns={examplePatterns} activePattern={activePattern} viewingPattern={viewingPattern} diff --git a/website/src/settings.mjs b/website/src/settings.mjs index 6edf24e2..16d70ce6 100644 --- a/website/src/settings.mjs +++ b/website/src/settings.mjs @@ -54,11 +54,13 @@ export function useActivePattern() { return useStore($activePattern); } export function initUserCode(code) { - const userPatterns = getUserPatterns(); - const match = Object.entries(userPatterns).find(([_, pat]) => pat.code === code); - const id = match?.[0] || ''; - setActivePattern(id); - setViewingPattern(id); + const patterns = { ...userPattern.getAll(), ...examplePattern.getAll() }; + const match = Object.entries(patterns).find(([_, pat]) => pat.code === code); + const id = match?.[0]; + if (id != null) { + setActivePattern(id); + setViewingPattern(id); + } } export function useSettings() { @@ -122,22 +124,25 @@ export const createPatternID = () => { }; export const getNextCloneID = (id) => { - const userPatterns = this.getAll(); - const clones = Object.entries(userPatterns).filter(([patID]) => patID.startsWith(id)); + const patterns = { ...userPattern.getAll(), ...examplePattern.getAll() }; + const clones = Object.entries(patterns).filter(([patID]) => patID.startsWith(id)); const num = String(clones.length + 1).padStart(3, '0'); const newID = id + '_' + num; return newID; }; +const examplePatterns = Object.fromEntries(Object.entries(tunes).map(([id, code]) => [id, { code }])); + export const examplePattern = { getAll() { - const examplePatterns = {}; - Object.entries(tunes).forEach(([key, code]) => (examplePatterns[key] = { code })); return examplePatterns; }, getPatternData(id) { - const userPatterns = this.getAll(); - return userPatterns[id]; + const pats = this.getAll(); + return pats[id]; + }, + exists(id) { + return this.getPatternData(id) != null; }, }; @@ -150,8 +155,7 @@ export const userPattern = { return userPatterns[id]; }, exists(id) { - const userPatterns = this.getAll(); - return userPatterns[id] != null; + return this.getPatternData(id) != null; }, create() { const newID = createPatternID(); @@ -164,7 +168,9 @@ export const userPattern = { const userPatterns = this.getAll(); setUserPatterns({ ...userPatterns, [id]: data }); }, - duplicate(id, data) { + duplicate(id) { + const examplePatternData = examplePattern.getPatternData(id); + const data = examplePatternData != null ? examplePatternData : this.getPatternData(id); const newID = getNextCloneID(id); this.update(newID, data); return { id: newID, data }; @@ -179,36 +185,37 @@ export const userPattern = { if (examplePatternData != null) { return { id: viewingPattern, data: examplePatternData }; } - setViewingPattern(null); + // setViewingPattern(null); setActivePattern(null); - return { id: null, data: { code: '' } }; + return { id: null, data: { code: defaultCode } }; }, delete(id) { const userPatterns = this.getAll(); - const updatedPatterns = Object.fromEntries(Object.entries(userPatterns).filter(([key]) => key !== id)); + delete userPatterns[id]; if (getActivePattern() === id) { setActivePattern(null); } - setUserPatterns(updatedPatterns); + setUserPatterns(userPatterns); const viewingPattern = getViewingPattern(); if (viewingPattern === id) { - return this.create(); + return { id: null, data: { code: defaultCode } }; } - return { id: viewingPattern, data: updatedPatterns[id] }; + return { id: viewingPattern, data: userPatterns[viewingPattern] }; }, rename(id) { const userPatterns = this.getAll(); const newID = prompt('Enter new name', id); + const data = userPatterns[id]; if (newID === null) { // canceled - return; + return { id, data }; } if (userPatterns[newID]) { alert('Name already taken!'); - return; + return { id, data }; } - const data = userPatterns[id]; + userPatterns[newID] = data; // copy code delete userPatterns[id];