From b9829bb6961a8d80b36631071592b5dc56cd9a0b Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Fri, 24 Jun 2022 21:13:17 +0200 Subject: [PATCH 01/22] flash effect on ctrl enter --- packages/react/dist/index.cjs.js | 4 +- packages/react/dist/index.es.js | 45 ++++++++++++++----- packages/react/src/components/CodeMirror6.jsx | 34 ++++++++++++++ packages/react/src/index.js | 2 +- repl/src/App.jsx | 5 ++- 5 files changed, 75 insertions(+), 15 deletions(-) diff --git a/packages/react/dist/index.cjs.js b/packages/react/dist/index.cjs.js index 284fa75fc..55eeacd9a 100644 --- a/packages/react/dist/index.cjs.js +++ b/packages/react/dist/index.cjs.js @@ -1,3 +1,3 @@ -"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var o=require("react"),te=require("react-codemirror6"),D=require("@codemirror/view"),I=require("@codemirror/state"),oe=require("@codemirror/lang-javascript"),s=require("@codemirror/highlight"),ae=require("react-hook-inview"),re=require("@strudel.cycles/eval"),ne=require("@strudel.cycles/core/util.mjs"),p=require("@strudel.cycles/tone"),z=require("@strudel.cycles/core"),v=require("@strudel.cycles/midi");function se(e){return e&&typeof e=="object"&&"default"in e?e:{default:e}}var g=se(o);const ce="#abb2bf",le="#7d8799",ie="#ffffff",ue="#21252b",P="rgba(0, 0, 0, 0.5)",de="transparent",W="#353a42",ge="rgba(128, 203, 196, 0.5)",F="#ffcc00",fe=D.EditorView.theme({"&":{color:"#ffffff",backgroundColor:de,fontSize:"15px","z-index":11},".cm-content":{caretColor:F,lineHeight:"22px"},".cm-line":{background:"#2C323699"},"&.cm-focused .cm-cursor":{backgroundColor:F,width:"3px"},"&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection":{backgroundColor:ge},".cm-panels":{backgroundColor:ue,color:"#ffffff"},".cm-panels.cm-panels-top":{borderBottom:"2px solid black"},".cm-panels.cm-panels-bottom":{borderTop:"2px solid black"},".cm-searchMatch":{backgroundColor:"#72a1ff59",outline:"1px solid #457dff"},".cm-searchMatch.cm-searchMatch-selected":{backgroundColor:"#6199ff2f"},".cm-activeLine":{backgroundColor:P},".cm-selectionMatch":{backgroundColor:"#aafe661a"},"&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket":{backgroundColor:"#bad0f847",outline:"1px solid #515a6b"},".cm-gutters":{background:"transparent",color:"#676e95",border:"none"},".cm-activeLineGutter":{backgroundColor:P},".cm-foldPlaceholder":{backgroundColor:"transparent",border:"none",color:"#ddd"},".cm-tooltip":{border:"none",backgroundColor:W},".cm-tooltip .cm-tooltip-arrow:before":{borderTopColor:"transparent",borderBottomColor:"transparent"},".cm-tooltip .cm-tooltip-arrow:after":{borderTopColor:W,borderBottomColor:W},".cm-tooltip-autocomplete":{"& > ul > li[aria-selected]":{backgroundColor:P,color:ce}}},{dark:!0}),me=s.HighlightStyle.define([{tag:s.tags.keyword,color:"#c792ea"},{tag:s.tags.operator,color:"#89ddff"},{tag:s.tags.special(s.tags.variableName),color:"#eeffff"},{tag:s.tags.typeName,color:"#f07178"},{tag:s.tags.atom,color:"#f78c6c"},{tag:s.tags.number,color:"#ff5370"},{tag:s.tags.definition(s.tags.variableName),color:"#82aaff"},{tag:s.tags.string,color:"#c3e88d"},{tag:s.tags.special(s.tags.string),color:"#f07178"},{tag:s.tags.comment,color:le},{tag:s.tags.variableName,color:"#f07178"},{tag:s.tags.tagName,color:"#ff5370"},{tag:s.tags.bracket,color:"#a2a1a4"},{tag:s.tags.meta,color:"#ffcb6b"},{tag:s.tags.attributeName,color:"#c792ea"},{tag:s.tags.propertyName,color:"#c792ea"},{tag:s.tags.className,color:"#decb6b"},{tag:s.tags.invalid,color:ie}]),be=[fe,me],B=I.StateEffect.define(),pe=I.StateField.define({create(){return D.Decoration.none},update(e,a){try{for(let l of a.effects)l.is(B)&&(e=D.Decoration.set(l.value.flatMap(u=>(u.context.locations||[]).map(({start:f,end:c})=>{const i=u.context.color||"#FFCA28";let m=a.newDoc.line(f.line).from+f.column,n=a.newDoc.line(c.line).from+c.column;const r=a.newDoc.length;return m>r||n>r?void 0:D.Decoration.mark({attributes:{style:`outline: 1px solid ${i}`}}).range(m,n)})).filter(Boolean),!0));return e}catch{return e}},provide:e=>D.EditorView.decorations.from(e)});function $({value:e,onChange:a,onViewChanged:l,onCursor:u,options:f,editorDidMount:c}){return g.default.createElement(g.default.Fragment,null,g.default.createElement(te.CodeMirror,{onViewChange:l,style:{display:"flex",flexDirection:"column",flex:"1 0 auto"},value:e,onChange:a,extensions:[oe.javascript(),be,pe]}))}function Q(e){const{onEvent:a,onQuery:l,onSchedule:u,ready:f=!0,onDraw:c}=e,[i,m]=o.useState(!1),n=1,r=()=>Math.floor(p.Tone.getTransport().seconds/n),y=(b=r())=>{const w=new z.TimeSpan(b,b+1),S=l?.(new z.State(w))||[];u?.(S,b);const H=w.begin.valueOf();p.Tone.getTransport().cancel(H);const N=(b+1)*n-.5,R=Math.max(p.Tone.getTransport().seconds,N)+.1;p.Tone.getTransport().schedule(()=>{y(b+1)},R),S?.filter(h=>h.part.begin.equals(h.whole?.begin)).forEach(h=>{p.Tone.getTransport().schedule(k=>{a(k,h,p.Tone.getContext().currentTime),p.Tone.Draw.schedule(()=>{c?.(k,h)},k)},h.part.begin.valueOf())})};o.useEffect(()=>{f&&y()},[a,u,l,c,f]);const _=async()=>{m(!0),await p.Tone.start(),p.Tone.getTransport().start("+0.1")},C=()=>{p.Tone.getTransport().pause(),m(!1)};return{start:_,stop:C,onEvent:a,started:i,setStarted:m,toggle:()=>i?C():_(),query:y,activeCycle:r}}function U(e){return o.useEffect(()=>(window.addEventListener("message",e),()=>window.removeEventListener("message",e)),[e]),o.useCallback(a=>window.postMessage(a,"*"),[])}let he=()=>Math.floor((1+Math.random())*65536).toString(16).substring(1);const ve=e=>encodeURIComponent(btoa(e));function G({tune:e,defaultSynth:a,autolink:l=!0,onEvent:u,onDraw:f}){const c=o.useMemo(()=>he(),[]),[i,m]=o.useState(e),[n,r]=o.useState(),[y,_]=o.useState(""),[C,E]=o.useState(),[b,w]=o.useState(!1),[S,H]=o.useState(""),[N,R]=o.useState(),h=o.useMemo(()=>i!==n||C,[i,n,C]),k=o.useCallback(d=>_(t=>t+`${t?` +"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var a=require("react"),oe=require("react-codemirror6"),y=require("@codemirror/view"),F=require("@codemirror/state"),ae=require("@codemirror/lang-javascript"),c=require("@codemirror/highlight"),re=require("react-hook-inview"),ne=require("@strudel.cycles/eval"),se=require("@strudel.cycles/core/util.mjs"),p=require("@strudel.cycles/tone"),j=require("@strudel.cycles/core"),v=require("@strudel.cycles/midi");function ce(e){return e&&typeof e=="object"&&"default"in e?e:{default:e}}var f=ce(a);const le="#abb2bf",ie="#7d8799",ue="#ffffff",de="#21252b",W="rgba(0, 0, 0, 0.5)",fe="transparent",P="#353a42",ge="rgba(128, 203, 196, 0.5)",O="#ffcc00",me=y.EditorView.theme({"&":{color:"#ffffff",backgroundColor:fe,fontSize:"15px","z-index":11},".cm-content":{caretColor:O,lineHeight:"22px"},".cm-line":{background:"#2C323699"},"&.cm-focused .cm-cursor":{backgroundColor:O,width:"3px"},"&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection":{backgroundColor:ge},".cm-panels":{backgroundColor:de,color:"#ffffff"},".cm-panels.cm-panels-top":{borderBottom:"2px solid black"},".cm-panels.cm-panels-bottom":{borderTop:"2px solid black"},".cm-searchMatch":{backgroundColor:"#72a1ff59",outline:"1px solid #457dff"},".cm-searchMatch.cm-searchMatch-selected":{backgroundColor:"#6199ff2f"},".cm-activeLine":{backgroundColor:W},".cm-selectionMatch":{backgroundColor:"#aafe661a"},"&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket":{backgroundColor:"#bad0f847",outline:"1px solid #515a6b"},".cm-gutters":{background:"transparent",color:"#676e95",border:"none"},".cm-activeLineGutter":{backgroundColor:W},".cm-foldPlaceholder":{backgroundColor:"transparent",border:"none",color:"#ddd"},".cm-tooltip":{border:"none",backgroundColor:P},".cm-tooltip .cm-tooltip-arrow:before":{borderTopColor:"transparent",borderBottomColor:"transparent"},".cm-tooltip .cm-tooltip-arrow:after":{borderTopColor:P,borderBottomColor:P},".cm-tooltip-autocomplete":{"& > ul > li[aria-selected]":{backgroundColor:W,color:le}}},{dark:!0}),be=c.HighlightStyle.define([{tag:c.tags.keyword,color:"#c792ea"},{tag:c.tags.operator,color:"#89ddff"},{tag:c.tags.special(c.tags.variableName),color:"#eeffff"},{tag:c.tags.typeName,color:"#f07178"},{tag:c.tags.atom,color:"#f78c6c"},{tag:c.tags.number,color:"#ff5370"},{tag:c.tags.definition(c.tags.variableName),color:"#82aaff"},{tag:c.tags.string,color:"#c3e88d"},{tag:c.tags.special(c.tags.string),color:"#f07178"},{tag:c.tags.comment,color:ie},{tag:c.tags.variableName,color:"#f07178"},{tag:c.tags.tagName,color:"#ff5370"},{tag:c.tags.bracket,color:"#a2a1a4"},{tag:c.tags.meta,color:"#ffcb6b"},{tag:c.tags.attributeName,color:"#c792ea"},{tag:c.tags.propertyName,color:"#c792ea"},{tag:c.tags.className,color:"#decb6b"},{tag:c.tags.invalid,color:ue}]),pe=[me,be],V=F.StateEffect.define(),he=F.StateField.define({create(){return y.Decoration.none},update(e,o){try{for(let r of o.effects)if(r.is(V))if(r.value){const i=y.Decoration.mark({attributes:{style:"background-color: #FFCA2880"}});e=y.Decoration.set([i.range(0,o.newDoc.length)])}else e=y.Decoration.set([]);return e}catch(r){return console.warn("flash error",r),e}},provide:e=>y.EditorView.decorations.from(e)}),ve=e=>{e.dispatch({effects:V.of(!0)}),setTimeout(()=>{e.dispatch({effects:V.of(!1)})},200)},B=F.StateEffect.define(),ye=F.StateField.define({create(){return y.Decoration.none},update(e,o){try{for(let r of o.effects)r.is(B)&&(e=y.Decoration.set(r.value.flatMap(i=>(i.context.locations||[]).map(({start:g,end:l})=>{const u=i.context.color||"#FFCA28";let m=o.newDoc.line(g.line).from+g.column,s=o.newDoc.line(l.line).from+l.column;const n=o.newDoc.length;return m>n||s>n?void 0:y.Decoration.mark({attributes:{style:`outline: 1px solid ${u}`}}).range(m,s)})).filter(Boolean),!0));return e}catch{return e}},provide:e=>y.EditorView.decorations.from(e)});function Q({value:e,onChange:o,onViewChanged:r,onCursor:i,options:g,editorDidMount:l}){return f.default.createElement(f.default.Fragment,null,f.default.createElement(oe.CodeMirror,{onViewChange:r,style:{display:"flex",flexDirection:"column",flex:"1 0 auto"},value:e,onChange:o,extensions:[ae.javascript(),pe,ye,he]}))}function U(e){const{onEvent:o,onQuery:r,onSchedule:i,ready:g=!0,onDraw:l}=e,[u,m]=a.useState(!1),s=1,n=()=>Math.floor(p.Tone.getTransport().seconds/s),C=(b=n())=>{const k=new j.TimeSpan(b,b+1),D=r?.(new j.State(k))||[];i?.(D,b);const H=k.begin.valueOf();p.Tone.getTransport().cancel(H);const N=(b+1)*s-.5,R=Math.max(p.Tone.getTransport().seconds,N)+.1;p.Tone.getTransport().schedule(()=>{C(b+1)},R),D?.filter(h=>h.part.begin.equals(h.whole?.begin)).forEach(h=>{p.Tone.getTransport().schedule(M=>{o(M,h,p.Tone.getContext().currentTime),p.Tone.Draw.schedule(()=>{l?.(M,h)},M)},h.part.begin.valueOf())})};a.useEffect(()=>{g&&C()},[o,i,r,l,g]);const S=async()=>{m(!0),await p.Tone.start(),p.Tone.getTransport().start("+0.1")},w=()=>{p.Tone.getTransport().pause(),m(!1)};return{start:S,stop:w,onEvent:o,started:u,setStarted:m,toggle:()=>u?w():S(),query:C,activeCycle:n}}function G(e){return a.useEffect(()=>(window.addEventListener("message",e),()=>window.removeEventListener("message",e)),[e]),a.useCallback(o=>window.postMessage(o,"*"),[])}let Ce=()=>Math.floor((1+Math.random())*65536).toString(16).substring(1);const we=e=>encodeURIComponent(btoa(e));function J({tune:e,defaultSynth:o,autolink:r=!0,onEvent:i,onDraw:g}){const l=a.useMemo(()=>Ce(),[]),[u,m]=a.useState(e),[s,n]=a.useState(),[C,S]=a.useState(""),[w,T]=a.useState(),[b,k]=a.useState(!1),[D,H]=a.useState(""),[N,R]=a.useState(),h=a.useMemo(()=>u!==s||w,[u,s,w]),M=a.useCallback(d=>S(t=>t+`${t?` -`:""}${d}`),[]),K=o.useMemo(()=>{if(n&&!n.includes("strudel disable-highlighting"))return(d,t)=>f?.(d,t,n)},[n,f]),T=Q({onDraw:K,onEvent:o.useCallback((d,t,Y)=>{try{u?.(t),t.context.logs?.length&&t.context.logs.forEach(k);const{onTrigger:x,velocity:Z}=t.context;if(x)x(d,t,Y,1,t.wholeOrPart().begin.valueOf(),t.duration.valueOf());else if(a){const ee=ne.getPlayableNoteValue(t);a.triggerAttackRelease(ee,t.duration.valueOf(),d,Z)}else throw new Error("no defaultSynth passed to useRepl.")}catch(x){console.warn(x),x.message="unplayable event: "+x?.message,k(x.message)}},[u,k,a]),onQuery:o.useCallback(d=>{try{return N?.query(d)||[]}catch(t){return console.warn(t),t.message="query error: "+t.message,E(t),[]}},[N]),onSchedule:o.useCallback((d,t)=>X(d,t),[]),ready:!!N&&!!n}),A=U(({data:{from:d,type:t}})=>{t==="start"&&d!==c&&(T.setStarted(!1),r(void 0))}),L=o.useCallback(async(d=i)=>{if(n&&!h){E(void 0),T.start();return}try{w(!0);const t=await re.evaluate(d);T.start(),A({type:"start",from:c}),R(()=>t.pattern),l&&(window.location.hash="#"+encodeURIComponent(btoa(i))),H(ve(i)),E(void 0),r(d),w(!1)}catch(t){t.message="evaluation error: "+t.message,console.warn(t),E(t)}},[n,h,i,T,l,c,A]),X=(d,t)=>{d.length};return{pending:b,code:i,setCode:m,pattern:N,error:C,cycle:T,setPattern:R,dirty:h,log:y,togglePlay:()=>{T.started?T.stop():L()},setActiveCode:r,activateCode:L,activeCode:n,pushLog:k,hash:S}}function V(...e){return e.filter(Boolean).join(" ")}let q=[],O;function J({view:e,pattern:a,active:l}){o.useEffect(()=>{if(e)if(a&&l){let f=function(){try{const c=p.Tone.getTransport().seconds,m=[Math.max(O||c,c-1/10),c+1/60];O=c+1/60,q=q.filter(r=>r.whole.end>c);const n=a.queryArc(...m).filter(r=>r.hasOnset());q=q.concat(n),e.dispatch({effects:B.of(q)})}catch{e.dispatch({effects:B.of([])})}u=requestAnimationFrame(f)},u=requestAnimationFrame(f);return()=>{cancelAnimationFrame(u)}}else q=[],e.dispatch({effects:B.of([])})},[a,l,e])}const ye="_container_10e1g_1",Ce="_header_10e1g_5",we="_buttons_10e1g_9",ke="_button_10e1g_9",Me="_buttonDisabled_10e1g_17",Ee="_error_10e1g_21",Te="_body_10e1g_25";var M={container:ye,header:Ce,buttons:we,button:ke,buttonDisabled:Me,error:Ee,body:Te};function j({type:e}){return g.default.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",className:"sc-h-5 sc-w-5",viewBox:"0 0 20 20",fill:"currentColor"},{refresh:g.default.createElement("path",{fillRule:"evenodd",d:"M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z",clipRule:"evenodd"}),play:g.default.createElement("path",{fillRule:"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z",clipRule:"evenodd"}),pause:g.default.createElement("path",{fillRule:"evenodd",d:"M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z",clipRule:"evenodd"})}[e])}function xe({tune:e,defaultSynth:a,hideOutsideView:l=!1}){const{code:u,setCode:f,pattern:c,activateCode:i,error:m,cycle:n,dirty:r,togglePlay:y}=G({tune:e,defaultSynth:a,autolink:!1}),[_,C]=o.useState(),[E,b]=ae.useInView({threshold:.01}),w=o.useRef(),S=o.useMemo(()=>((b||!l)&&(w.current=!0),b||w.current),[b,l]);return J({view:_,pattern:c,active:n.started}),g.default.createElement("div",{className:M.container,ref:E},g.default.createElement("div",{className:M.header},g.default.createElement("div",{className:M.buttons},g.default.createElement("button",{className:V(M.button,n.started?"sc-animate-pulse":""),onClick:()=>y()},g.default.createElement(j,{type:n.started?"pause":"play"})),g.default.createElement("button",{className:V(r?M.button:M.buttonDisabled),onClick:()=>i()},g.default.createElement(j,{type:"refresh"}))),m&&g.default.createElement("div",{className:M.error},m.message)),g.default.createElement("div",{className:M.body},S&&g.default.createElement($,{value:u,onChange:f,onViewChanged:C})))}function _e(e){const{ready:a,connected:l,disconnected:u}=e,[f,c]=o.useState(!0),[i,m]=o.useState(v.WebMidi?.outputs||[]);return o.useEffect(()=>{v.enableWebMidi().then(()=>{v.WebMidi.addListener("connected",r=>{m([...v.WebMidi.outputs]),l?.(v.WebMidi,r)}),v.WebMidi.addListener("disconnected",r=>{m([...v.WebMidi.outputs]),u?.(v.WebMidi,r)}),a?.(v.WebMidi),c(!1)}).catch(r=>{if(r){console.error(r),console.warn("Web Midi could not be enabled..");return}})},[a,l,u,i]),{loading:f,outputs:i,outputByName:r=>v.WebMidi.getOutputByName(r)}}exports.CodeMirror=$;exports.MiniRepl=xe;exports.cx=V;exports.useCycle=Q;exports.useHighlighting=J;exports.usePostMessage=U;exports.useRepl=G;exports.useWebMidi=_e; +`:""}${d}`),[]),X=a.useMemo(()=>{if(s&&!s.includes("strudel disable-highlighting"))return(d,t)=>g?.(d,t,s)},[s,g]),x=U({onDraw:X,onEvent:a.useCallback((d,t,Z)=>{try{i?.(t),t.context.logs?.length&&t.context.logs.forEach(M);const{onTrigger:_,velocity:ee}=t.context;if(_)_(d,t,Z,1);else if(o){const te=se.getPlayableNoteValue(t);o.triggerAttackRelease(te,t.duration.valueOf(),d,ee)}else throw new Error("no defaultSynth passed to useRepl.")}catch(_){console.warn(_),_.message="unplayable event: "+_?.message,M(_.message)}},[i,M,o]),onQuery:a.useCallback(d=>{try{return N?.query(d)||[]}catch(t){return console.warn(t),t.message="query error: "+t.message,T(t),[]}},[N]),onSchedule:a.useCallback((d,t)=>Y(d,t),[]),ready:!!N&&!!s}),L=G(({data:{from:d,type:t}})=>{t==="start"&&d!==l&&(x.setStarted(!1),n(void 0))}),z=a.useCallback(async(d=u)=>{if(s&&!h){T(void 0),x.start();return}try{k(!0);const t=await ne.evaluate(d);x.start(),L({type:"start",from:l}),R(()=>t.pattern),r&&(window.location.hash="#"+encodeURIComponent(btoa(u))),H(we(u)),T(void 0),n(d),k(!1)}catch(t){t.message="evaluation error: "+t.message,console.warn(t),T(t)}},[s,h,u,x,r,l,L]),Y=(d,t)=>{d.length};return{pending:b,code:u,setCode:m,pattern:N,error:w,cycle:x,setPattern:R,dirty:h,log:C,togglePlay:()=>{x.started?x.stop():z()},setActiveCode:n,activateCode:z,activeCode:s,pushLog:M,hash:D}}function A(...e){return e.filter(Boolean).join(" ")}let q=[],I;function K({view:e,pattern:o,active:r}){a.useEffect(()=>{if(e)if(o&&r){let g=function(){try{const l=p.Tone.getTransport().seconds,m=[Math.max(I||l,l-1/10),l+1/60];I=l+1/60,q=q.filter(n=>n.whole.end>l);const s=o.queryArc(...m).filter(n=>n.hasOnset());q=q.concat(s),e.dispatch({effects:B.of(q)})}catch{e.dispatch({effects:B.of([])})}i=requestAnimationFrame(g)},i=requestAnimationFrame(g);return()=>{cancelAnimationFrame(i)}}else q=[],e.dispatch({effects:B.of([])})},[o,r,e])}const ke="_container_10e1g_1",Me="_header_10e1g_5",Ee="_buttons_10e1g_9",Te="_button_10e1g_9",xe="_buttonDisabled_10e1g_17",_e="_error_10e1g_21",Se="_body_10e1g_25";var E={container:ke,header:Me,buttons:Ee,button:Te,buttonDisabled:xe,error:_e,body:Se};function $({type:e}){return f.default.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",className:"sc-h-5 sc-w-5",viewBox:"0 0 20 20",fill:"currentColor"},{refresh:f.default.createElement("path",{fillRule:"evenodd",d:"M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z",clipRule:"evenodd"}),play:f.default.createElement("path",{fillRule:"evenodd",d:"M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z",clipRule:"evenodd"}),pause:f.default.createElement("path",{fillRule:"evenodd",d:"M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z",clipRule:"evenodd"})}[e])}function De({tune:e,defaultSynth:o,hideOutsideView:r=!1}){const{code:i,setCode:g,pattern:l,activateCode:u,error:m,cycle:s,dirty:n,togglePlay:C}=J({tune:e,defaultSynth:o,autolink:!1}),[S,w]=a.useState(),[T,b]=re.useInView({threshold:.01}),k=a.useRef(),D=a.useMemo(()=>((b||!r)&&(k.current=!0),b||k.current),[b,r]);return K({view:S,pattern:l,active:s.started}),f.default.createElement("div",{className:E.container,ref:T},f.default.createElement("div",{className:E.header},f.default.createElement("div",{className:E.buttons},f.default.createElement("button",{className:A(E.button,s.started?"sc-animate-pulse":""),onClick:()=>C()},f.default.createElement($,{type:s.started?"pause":"play"})),f.default.createElement("button",{className:A(n?E.button:E.buttonDisabled),onClick:()=>u()},f.default.createElement($,{type:"refresh"}))),m&&f.default.createElement("div",{className:E.error},m.message)),f.default.createElement("div",{className:E.body},D&&f.default.createElement(Q,{value:i,onChange:g,onViewChanged:w})))}function Ne(e){const{ready:o,connected:r,disconnected:i}=e,[g,l]=a.useState(!0),[u,m]=a.useState(v.WebMidi?.outputs||[]);return a.useEffect(()=>{v.enableWebMidi().then(()=>{v.WebMidi.addListener("connected",n=>{m([...v.WebMidi.outputs]),r?.(v.WebMidi,n)}),v.WebMidi.addListener("disconnected",n=>{m([...v.WebMidi.outputs]),i?.(v.WebMidi,n)}),o?.(v.WebMidi),l(!1)}).catch(n=>{if(n){console.error(n),console.warn("Web Midi could not be enabled..");return}})},[o,r,i,u]),{loading:g,outputs:u,outputByName:n=>v.WebMidi.getOutputByName(n)}}exports.CodeMirror=Q;exports.MiniRepl=De;exports.cx=A;exports.flash=ve;exports.useCycle=U;exports.useHighlighting=K;exports.usePostMessage=G;exports.useRepl=J;exports.useWebMidi=Ne; diff --git a/packages/react/dist/index.es.js b/packages/react/dist/index.es.js index 77ae32c90..a0269039c 100644 --- a/packages/react/dist/index.es.js +++ b/packages/react/dist/index.es.js @@ -145,6 +145,37 @@ const materialPalenightHighlightStyle = HighlightStyle.define([ // : Extension const materialPalenight = [materialPalenightTheme, materialPalenightHighlightStyle]; +const setFlash = StateEffect.define(); +const flashField = StateField.define({ + create() { + return Decoration.none; + }, + update(flash2, tr) { + try { + for (let e of tr.effects) { + if (e.is(setFlash)) { + if (e.value) { + const mark = Decoration.mark({ attributes: { style: `background-color: #FFCA2880` } }); + flash2 = Decoration.set([mark.range(0, tr.newDoc.length)]); + } else { + flash2 = Decoration.set([]); + } + } + } + return flash2; + } catch (err) { + console.warn("flash error", err); + return flash2; + } + }, + provide: (f) => EditorView.decorations.from(f) +}); +const flash = (view) => { + view.dispatch({ effects: setFlash.of(true) }); + setTimeout(() => { + view.dispatch({ effects: setFlash.of(false) }); + }, 200); +}; const setHighlights = StateEffect.define(); const highlightField = StateField.define({ create() { @@ -187,7 +218,8 @@ function CodeMirror({ value, onChange, onViewChanged, onCursor, options, editorD extensions: [ javascript(), materialPalenight, - highlightField + highlightField, + flashField ] })); } @@ -340,14 +372,7 @@ function useRepl({ tune, defaultSynth, autolink = true, onEvent, onDraw: onDrawP /* console.warn('no instrument chosen', event); throw new Error(`no instrument chosen for ${JSON.stringify(event)}`); */ } else { - onTrigger( - time, - event, - currentTime, - 1 /* cps */, - event.wholeOrPart().begin.valueOf(), - event.duration.valueOf(), - ); + onTrigger(time, event, currentTime, 1 /* cps */); } } catch (err) { console.warn(err); @@ -623,4 +648,4 @@ function useWebMidi(props) { return { loading, outputs, outputByName }; } -export { CodeMirror, MiniRepl, cx, useCycle, useHighlighting, usePostMessage, useRepl, useWebMidi }; +export { CodeMirror, MiniRepl, cx, flash, useCycle, useHighlighting, usePostMessage, useRepl, useWebMidi }; diff --git a/packages/react/src/components/CodeMirror6.jsx b/packages/react/src/components/CodeMirror6.jsx index ee0cc9405..74051a971 100644 --- a/packages/react/src/components/CodeMirror6.jsx +++ b/packages/react/src/components/CodeMirror6.jsx @@ -7,6 +7,39 @@ import { javascript } from '@codemirror/lang-javascript'; // import { materialPalenight } from 'codemirror6-themes'; import { materialPalenight } from '../themes/material-palenight'; +export const setFlash = StateEffect.define(); +const flashField = StateField.define({ + create() { + return Decoration.none; + }, + update(flash, tr) { + try { + for (let e of tr.effects) { + if (e.is(setFlash)) { + if (e.value) { + const mark = Decoration.mark({ attributes: { style: `background-color: #FFCA2880` } }); + flash = Decoration.set([mark.range(0, tr.newDoc.length)]); + } else { + flash = Decoration.set([]); + } + } + } + return flash; + } catch (err) { + console.warn('flash error', err); + return flash; + } + }, + provide: (f) => EditorView.decorations.from(f), +}); + +export const flash = (view) => { + view.dispatch({ effects: setFlash.of(true) }); + setTimeout(() => { + view.dispatch({ effects: setFlash.of(false) }); + }, 200); +}; + export const setHighlights = StateEffect.define(); const highlightField = StateField.define({ create() { @@ -61,6 +94,7 @@ export default function CodeMirror({ value, onChange, onViewChanged, onCursor, o javascript(), materialPalenight, highlightField, + flashField, // theme, language, ... ]} /> diff --git a/packages/react/src/index.js b/packages/react/src/index.js index f008dbde7..7ba993a7e 100644 --- a/packages/react/src/index.js +++ b/packages/react/src/index.js @@ -1,6 +1,6 @@ // import 'tailwindcss/tailwind.css'; -export { default as CodeMirror } from './components/CodeMirror6'; +export { default as CodeMirror, flash } from './components/CodeMirror6'; export * from './components/MiniRepl'; export { default as useCycle } from './hooks/useCycle'; export { default as useHighlighting } from './hooks/useHighlighting'; diff --git a/repl/src/App.jsx b/repl/src/App.jsx index 4b9005916..e18bc3a51 100644 --- a/repl/src/App.jsx +++ b/repl/src/App.jsx @@ -6,7 +6,7 @@ This program is free software: you can redistribute it and/or modify it under th import controls from '@strudel.cycles/core/controls.mjs'; import { evalScope, evaluate } from '@strudel.cycles/eval'; -import { CodeMirror, cx, useHighlighting, useRepl, useWebMidi } from '@strudel.cycles/react'; +import { CodeMirror, cx, flash, useHighlighting, useRepl, useWebMidi } from '@strudel.cycles/react'; import { getDefaultSynth, cleanupDraw, cleanupUi, Tone } from '@strudel.cycles/tone'; import React, { useCallback, useLayoutEffect, useRef, useState } from 'react'; import './App.css'; @@ -92,6 +92,7 @@ function App() { if (e.ctrlKey || e.altKey) { if (e.code === 'Enter') { e.preventDefault(); + flash(view); await activateCode(); } else if (e.code === 'Period') { cycle.stop(); @@ -101,7 +102,7 @@ function App() { }; window.addEventListener('keydown', handleKeyPress, true); return () => window.removeEventListener('keydown', handleKeyPress, true); - }, [pattern, code, activateCode, cycle]); + }, [pattern, code, activateCode, cycle, view]); useHighlighting({ view, pattern, active: cycle.started && !activeCode?.includes('strudel disable-highlighting') }); From 4039b962b4cee579aa7c72817561ebfa61406af0 Mon Sep 17 00:00:00 2001 From: Felix Roos Date: Sun, 26 Jun 2022 12:49:29 +0200 Subject: [PATCH 02/22] can now generate short link for sharing --- repl/package-lock.json | 516 ++++++++++++++++++++++++++++++++++++++++- repl/package.json | 2 + repl/src/App.jsx | 64 ++++- 3 files changed, 569 insertions(+), 13 deletions(-) diff --git a/repl/package-lock.json b/repl/package-lock.json index c983ec80b..10375f90a 100644 --- a/repl/package-lock.json +++ b/repl/package-lock.json @@ -8,6 +8,8 @@ "name": "@strudel.cycles/repl", "version": "0.0.0", "dependencies": { + "@supabase/supabase-js": "^1.35.3", + "nanoid": "^4.0.0", "react": "^17.0.2", "react-dom": "^17.0.2" }, @@ -509,6 +511,59 @@ "node": ">= 8.0.0" } }, + "node_modules/@supabase/functions-js": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-1.3.3.tgz", + "integrity": "sha512-35vO9niHRtzGe1QSvXKdOfvGPiX2KC44dGpWU6y0/gZCfTIgog/soU9HqABzQC/maVowO3hGLWfez5aN0MKfow==", + "dependencies": { + "cross-fetch": "^3.1.5" + } + }, + "node_modules/@supabase/gotrue-js": { + "version": "1.22.16", + "resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-1.22.16.tgz", + "integrity": "sha512-t/tR87anihvyc9ePk53NF2CG8yzTDiWOt0ReZpr7sRKV91sHNLbghVMsMDwPONWnVQ9V2/qfKutuAvPGTB/Dew==", + "dependencies": { + "cross-fetch": "^3.0.6" + } + }, + "node_modules/@supabase/postgrest-js": { + "version": "0.37.3", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-0.37.3.tgz", + "integrity": "sha512-Iqwv9D80YGkCi60Zl2lsV04WxOmjFqxpFmxoZ5xUqsVZHvIoAbJ9tMM3+0F7VkZZbsjnaYHrpJ58xLxU7cgy2w==", + "dependencies": { + "cross-fetch": "^3.1.5" + } + }, + "node_modules/@supabase/realtime-js": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-1.7.2.tgz", + "integrity": "sha512-DMUaFIKj7KszGtWTTQbhMmUzZf7UnwYqySsmY+G8HgYxvY3ZaVa+DZD0I6ofgr4OLNr0po/ODM2a4lf5m5GNBg==", + "dependencies": { + "@types/phoenix": "^1.5.4", + "websocket": "^1.0.34" + } + }, + "node_modules/@supabase/storage-js": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-1.7.1.tgz", + "integrity": "sha512-0ZlKlGgB3Qzhu07fts5pr2Y+c4xW58d7sDOB9m6nSfltS6SSfBPmqtdhU0zV9vy3vAjC74XeqUcpMhHP5E+aoA==", + "dependencies": { + "cross-fetch": "^3.1.0" + } + }, + "node_modules/@supabase/supabase-js": { + "version": "1.35.3", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-1.35.3.tgz", + "integrity": "sha512-uwO8OVdMFsGZNZ1xQhFz22+PSW0EWYZ5xVq+jQeGz8nhabEu+Q9Uyep/bcNzOpyPJRzbGfxSPRzgAdAxfJgFhw==", + "dependencies": { + "@supabase/functions-js": "^1.3.3", + "@supabase/gotrue-js": "^1.22.14", + "@supabase/postgrest-js": "^0.37.2", + "@supabase/realtime-js": "^1.7.2", + "@supabase/storage-js": "^1.7.0" + } + }, "node_modules/@tailwindcss/typography": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.2.tgz", @@ -523,6 +578,11 @@ "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || insiders" } }, + "node_modules/@types/phoenix": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.5.4.tgz", + "integrity": "sha512-L5eZmzw89eXBKkiqVBcJfU1QGx9y+wurRIEgt0cuLH0hwNtVUxtx+6cu0R2STwWj468sjXyBYPYDtGclUd1kjQ==" + }, "node_modules/@vitejs/plugin-react": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-1.3.2.tgz", @@ -688,6 +748,18 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/bufferutil": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz", + "integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==", + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", @@ -790,6 +862,14 @@ "safe-buffer": "~5.1.1" } }, + "node_modules/cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "dependencies": { + "node-fetch": "2.6.7" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -802,6 +882,15 @@ "node": ">=4" } }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -860,6 +949,39 @@ "integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==", "dev": true }, + "node_modules/es5-ext": { + "version": "0.10.61", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz", + "integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==", + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, "node_modules/esbuild": { "version": "0.14.39", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.39.tgz", @@ -1239,6 +1361,19 @@ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true }, + "node_modules/ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "dependencies": { + "type": "^2.5.0" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", + "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" + }, "node_modules/fast-glob": { "version": "3.2.11", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", @@ -1426,6 +1561,11 @@ "node": ">=0.12.0" } }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -1528,15 +1668,48 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.0.tgz", + "integrity": "sha512-IgBP8piMxe/gf73RTQx7hmnhwz0aaEXYakvqZyE302IXW3HyVNhdNGC+O2MwMAVhLEnvXlvKtGbtJf6wvHihCg==", "bin": { - "nanoid": "bin/nanoid.cjs" + "nanoid": "bin/nanoid.js" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": "^14 || ^16 || >=18" + } + }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-gyp-build": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.4.0.tgz", + "integrity": "sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ==", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" } }, "node_modules/node-releases": { @@ -1714,6 +1887,18 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, + "node_modules/postcss/node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -1980,6 +2165,36 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/utf-8-validate": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz", + "integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==", + "hasInstallScript": true, + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -2023,6 +2238,49 @@ } } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/websocket": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz", + "integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==", + "dependencies": { + "bufferutil": "^4.0.1", + "debug": "^2.2.0", + "es5-ext": "^0.10.50", + "typedarray-to-buffer": "^3.1.5", + "utf-8-validate": "^5.0.2", + "yaeti": "^0.0.6" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/websocket/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/websocket/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -2032,6 +2290,14 @@ "node": ">=0.4" } }, + "node_modules/yaeti": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", + "integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==", + "engines": { + "node": ">=0.10.32" + } + }, "node_modules/yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", @@ -2402,6 +2668,59 @@ "picomatch": "^2.2.2" } }, + "@supabase/functions-js": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-1.3.3.tgz", + "integrity": "sha512-35vO9niHRtzGe1QSvXKdOfvGPiX2KC44dGpWU6y0/gZCfTIgog/soU9HqABzQC/maVowO3hGLWfez5aN0MKfow==", + "requires": { + "cross-fetch": "^3.1.5" + } + }, + "@supabase/gotrue-js": { + "version": "1.22.16", + "resolved": "https://registry.npmjs.org/@supabase/gotrue-js/-/gotrue-js-1.22.16.tgz", + "integrity": "sha512-t/tR87anihvyc9ePk53NF2CG8yzTDiWOt0ReZpr7sRKV91sHNLbghVMsMDwPONWnVQ9V2/qfKutuAvPGTB/Dew==", + "requires": { + "cross-fetch": "^3.0.6" + } + }, + "@supabase/postgrest-js": { + "version": "0.37.3", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-0.37.3.tgz", + "integrity": "sha512-Iqwv9D80YGkCi60Zl2lsV04WxOmjFqxpFmxoZ5xUqsVZHvIoAbJ9tMM3+0F7VkZZbsjnaYHrpJ58xLxU7cgy2w==", + "requires": { + "cross-fetch": "^3.1.5" + } + }, + "@supabase/realtime-js": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-1.7.2.tgz", + "integrity": "sha512-DMUaFIKj7KszGtWTTQbhMmUzZf7UnwYqySsmY+G8HgYxvY3ZaVa+DZD0I6ofgr4OLNr0po/ODM2a4lf5m5GNBg==", + "requires": { + "@types/phoenix": "^1.5.4", + "websocket": "^1.0.34" + } + }, + "@supabase/storage-js": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-1.7.1.tgz", + "integrity": "sha512-0ZlKlGgB3Qzhu07fts5pr2Y+c4xW58d7sDOB9m6nSfltS6SSfBPmqtdhU0zV9vy3vAjC74XeqUcpMhHP5E+aoA==", + "requires": { + "cross-fetch": "^3.1.0" + } + }, + "@supabase/supabase-js": { + "version": "1.35.3", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-1.35.3.tgz", + "integrity": "sha512-uwO8OVdMFsGZNZ1xQhFz22+PSW0EWYZ5xVq+jQeGz8nhabEu+Q9Uyep/bcNzOpyPJRzbGfxSPRzgAdAxfJgFhw==", + "requires": { + "@supabase/functions-js": "^1.3.3", + "@supabase/gotrue-js": "^1.22.14", + "@supabase/postgrest-js": "^0.37.2", + "@supabase/realtime-js": "^1.7.2", + "@supabase/storage-js": "^1.7.0" + } + }, "@tailwindcss/typography": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.2.tgz", @@ -2413,6 +2732,11 @@ "lodash.merge": "^4.6.2" } }, + "@types/phoenix": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.5.4.tgz", + "integrity": "sha512-L5eZmzw89eXBKkiqVBcJfU1QGx9y+wurRIEgt0cuLH0hwNtVUxtx+6cu0R2STwWj468sjXyBYPYDtGclUd1kjQ==" + }, "@vitejs/plugin-react": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-1.3.2.tgz", @@ -2519,6 +2843,14 @@ "picocolors": "^1.0.0" } }, + "bufferutil": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz", + "integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==", + "requires": { + "node-gyp-build": "^4.3.0" + } + }, "camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", @@ -2593,12 +2925,29 @@ "safe-buffer": "~5.1.1" } }, + "cross-fetch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", + "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "requires": { + "node-fetch": "2.6.7" + } + }, "cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -2643,6 +2992,35 @@ "integrity": "sha512-0Rcpald12O11BUogJagX3HsCN3FE83DSqWjgXoHo5a72KUKMSfI39XBgJpgNNxS9fuGzytaFjE06kZkiVFy2qA==", "dev": true }, + "es5-ext": { + "version": "0.10.61", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz", + "integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==", + "requires": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, "esbuild": { "version": "0.14.39", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.39.tgz", @@ -2829,6 +3207,21 @@ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true }, + "ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "requires": { + "type": "^2.5.0" + }, + "dependencies": { + "type": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", + "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" + } + } + }, "fast-glob": { "version": "3.2.11", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", @@ -2965,6 +3358,11 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==" + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -3043,10 +3441,27 @@ "dev": true }, "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-4.0.0.tgz", + "integrity": "sha512-IgBP8piMxe/gf73RTQx7hmnhwz0aaEXYakvqZyE302IXW3HyVNhdNGC+O2MwMAVhLEnvXlvKtGbtJf6wvHihCg==" + }, + "next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "node-gyp-build": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.4.0.tgz", + "integrity": "sha512-amJnQCcgtRVw9SvoebO3BKGESClrfXGCUTX9hSn1OuGQTQBOZmVd0Z0OlecpuRksKvbsUqALE8jls/ErClAPuQ==" }, "node-releases": { "version": "2.0.4", @@ -3104,6 +3519,14 @@ "nanoid": "^3.3.3", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" + }, + "dependencies": { + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "dev": true + } } }, "postcss-js": { @@ -3325,6 +3748,32 @@ "is-number": "^7.0.0" } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "utf-8-validate": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz", + "integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==", + "requires": { + "node-gyp-build": "^4.3.0" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -3344,12 +3793,59 @@ "rollup": "^2.59.0" } }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "websocket": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.34.tgz", + "integrity": "sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ==", + "requires": { + "bufferutil": "^4.0.1", + "debug": "^2.2.0", + "es5-ext": "^0.10.50", + "typedarray-to-buffer": "^3.1.5", + "utf-8-validate": "^5.0.2", + "yaeti": "^0.0.6" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } + } + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true }, + "yaeti": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", + "integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==" + }, "yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", diff --git a/repl/package.json b/repl/package.json index c0afb29a1..9c5923719 100644 --- a/repl/package.json +++ b/repl/package.json @@ -15,6 +15,8 @@ "static": "npx serve ../docs" }, "dependencies": { + "@supabase/supabase-js": "^1.35.3", + "nanoid": "^4.0.0", "react": "^17.0.2", "react-dom": "^17.0.2" }, diff --git a/repl/src/App.jsx b/repl/src/App.jsx index e18bc3a51..ca7fe5e6b 100644 --- a/repl/src/App.jsx +++ b/repl/src/App.jsx @@ -15,6 +15,15 @@ import * as tunes from './tunes.mjs'; import * as WebDirt from 'WebDirt'; import { loadWebDirt } from '@strudel.cycles/webdirt'; import { resetLoadedSamples, getAudioContext } from '@strudel.cycles/webaudio'; +import { createClient } from '@supabase/supabase-js'; +import { nanoid } from 'nanoid'; + +// Create a single supabase client for interacting with your database +const supabase = createClient( + 'https://pidxdsxphlhzjnzmifth.supabase.co', + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBpZHhkc3hwaGxoempuem1pZnRoIiwicm9sZSI6ImFub24iLCJpYXQiOjE2NTYyMzA1NTYsImV4cCI6MTk3MTgwNjU1Nn0.bqlw7802fsWRnqU5BLYtmXk_k-D1VFmbkHMywWc15NM', +); + evalScope( Tone, controls, @@ -37,11 +46,27 @@ loadWebDirt({ sampleFolder: 'EmuSP12', }); -const initialUrl = window.location.href; -const codeParam = window.location.href.split('#')[1]; +// load code from url hash (either short hash from database or decode long hash) let decoded; try { - decoded = atob(decodeURIComponent(codeParam || '')); + const initialUrl = window.location.href; + const hash = initialUrl.split('?')[1]?.split('#')?.[0]; + const codeParam = window.location.href.split('#')[1]; + // looking like https://strudel.tidalcycles.org/?J01s5i1J0200 (fixed hash length) + if (codeParam) { + // looking like https://strudel.tidalcycles.org/#ImMzIGUzIg%3D%3D (hash length depends on code length) + decoded = atob(decodeURIComponent(codeParam || '')); + console.log('decoded hash from url'); + } else if (hash) { + const { data, error } = await supabase.from('code').select('code').eq('hash', hash); + if (error) { + throw error; + } + if (data.length) { + decoded = data[0].code; + console.log('loaded hash from database', hash); + } + } } catch (err) { console.warn('failed to decode', err); } @@ -58,6 +83,7 @@ const isEmbedded = window.location !== window.parent.location; function App() { // const [editor, setEditor] = useState(); const [view, setView] = useState(); + const [lastShared, setLastShared] = useState(); const { setCode, setPattern, @@ -196,6 +222,38 @@ function App() { 📚 tutorial )} + {!isEmbedded && ( + + )} {isEmbedded && (