diff options
| author | Sam Nystrom <sam@samnystrom.dev> | 2024-03-16 22:54:54 -0400 |
|---|---|---|
| committer | Sam Nystrom <sam@samnystrom.dev> | 2024-03-16 22:54:54 -0400 |
| commit | 1d5f74bca29c6bb28bef6035aa09a1e35884b40a (patch) | |
| tree | 910801e8f2bf940f77438642f7a20448385d822a | |
| parent | 7c37715afd7d9572a7f1a79552a187ab2a3e4184 (diff) | |
| -rw-r--r-- | assembly/index.ts | 45 | ||||
| -rw-r--r-- | bunfig.toml | 2 | ||||
| -rw-r--r-- | package.json | 2 | ||||
| -rw-r--r-- | src/components/NodeEditor.tsx | 67 | ||||
| -rw-r--r-- | src/index.tsx | 3 | ||||
| -rw-r--r-- | src/pages/Editor.tsx | 6 | ||||
| -rw-r--r-- | src/pages/SignUp.test.tsx | 34 | ||||
| -rw-r--r-- | src/pages/SignUp.tsx | 9 | ||||
| -rw-r--r-- | src/test-preload.ts | 9 |
9 files changed, 119 insertions, 58 deletions
diff --git a/assembly/index.ts b/assembly/index.ts index e94b0a8..8218a08 100644 --- a/assembly/index.ts +++ b/assembly/index.ts @@ -320,11 +320,12 @@ export function unzip(x: StaticArray<f32>): StaticArray<f32> { } function ditfft2(x: StaticArray<f32>, n: i32, s: i32, out: StaticArray<f32>): void { - if (n == 1) { + //trace('x,n,s,X:', 4, <f64>x.length, <f64>n, <f64>s, <f64>out.length); + /*if (n == 1) { out[0] = x[0]; out[1] = x[1]; return; - } else if (n == 2) { + } /*else if (n == 2) {*/ for (let k = 0; k < out.length - out.length % 2; k += 2) { for (let n = 0; n < x.length - x.length % 2; n += 2) { const y = -<f32>2 * Mathf.PI * <f32>k / <f32>x.length * <f32>n; @@ -334,11 +335,11 @@ function ditfft2(x: StaticArray<f32>, n: i32, s: i32, out: StaticArray<f32>): vo out[k+1] += x[n] * v + x[n+1] * u; } } - return; - } - ditfft2(x.slice<StaticArray<f32>>(0, n), n/2, 2*s, out.slice<StaticArray<f32>>(0, n)); - ditfft2(x.slice<StaticArray<f32>>(s * 2), n/2, 2*s, out.slice<StaticArray<f32>>(n)); - const outptr = changetype<usize>(out); + /*return; + }*/ + // ditfft2(x, n/2, 2*s, out.slice<StaticArray<f32>>(0, n)); + // ditfft2(x.slice<StaticArray<f32>>(s * 2), n/2, 2*s, out.slice<StaticArray<f32>>(n)); + /*const outptr = changetype<usize>(out); const twiddle = vf32(-<f32>2 * Mathf.PI / <f32>n); let vk = f32x4(0,1,2,3); for (let k = 0; k < n/2 - n/2 % 2; k += 4) { @@ -349,22 +350,30 @@ function ditfft2(x: StaticArray<f32>, n: i32, s: i32, out: StaticArray<f32>): vo v128.store(outptr + k*2 * 4, v128.add<f32>(p, q)); v128.store(outptr + (k*2 + n/2) * 4, v128.sub<f32>(p, q)); vk = v128.add<f32>(vk, vf32(1)); - } - for (let k = n/2 - n/2 % 2; k < n/2; k++) { + }*/ + //for (let k = n/2 - n/2 % 2; k < n/2; k++) { + /*for (let k = 0; k < n/2; k++) { + trace('n,s,k', 3, <f64>n, <f64>s, <f64>k); const pr = unchecked(out[k*2]); const pi = unchecked(out[k*2+1]); - const y = -<f32>2 * Mathf.PI * <f32>k / <f32>n; - const qr = Mathf.cos(y) * out[k*2+n/2] - const qi = Mathf.sin(y) * out[k*2+n/2+1]; + const tw = -<f32>2 * Mathf.PI / <f32>n * <f32>k; + const u = Mathf.cos(tw); + const v = Mathf.sin(tw); + const x = out[(k+n/2)*2]; + const y = out[(k+n/2)*2+1]; + const qr = x * u - y * v; + const qi = x * v + y * u; unchecked(out[k*2] = pr + qr); unchecked(out[k*2+1] = pi + qi); - unchecked(out[k*2+n/2] = pr - qr); - unchecked(out[k*2+n/2+1] = pi - qi); - } + unchecked(out[(k+n/2)*2] = pr - qr); + unchecked(out[(k+n/2)*2+1] = pi - qi); + }*/ } export function fft(x: StaticArray<f32>): StaticArray<f32> { - const out = new StaticArray<f32>(x.length); - ditfft2(x, x.length/2, 1, out); + const len = x.length - x.length % 2; + const out = new StaticArray<f32>(len); + if (len == 0) return out; + ditfft2(x.slice<StaticArray<f32>>(0, len), len/2, 1, out); return out; -}
\ No newline at end of file +} diff --git a/bunfig.toml b/bunfig.toml new file mode 100644 index 0000000..445a41d --- /dev/null +++ b/bunfig.toml @@ -0,0 +1,2 @@ +[test] +preload = "./src/test-preload.ts" diff --git a/package.json b/package.json index 5f00d1c..4cd959f 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,8 @@ "preact-router": "^4.1.2" }, "devDependencies": { + "@happy-dom/global-registrator": "^13.8.6", + "@testing-library/preact": "^3.2.3", "assemblyscript": "^0.27.24", "esbuild": "^0.20.1", "typescript": "^5.3.3" diff --git a/src/components/NodeEditor.tsx b/src/components/NodeEditor.tsx index 758fb76..4cb7011 100644 --- a/src/components/NodeEditor.tsx +++ b/src/components/NodeEditor.tsx @@ -87,7 +87,7 @@ const NodeEditor = ({ project }: NodeEditorProps) => { const filter = pb.filter('project.id = {:id}', { id: project.id }); const projectNodes = await pb.collection('nodes').getFullList({ filter }); const projectLinks = await pb.collection('links').getFullList({ filter }); - const instances = projectNodes.map(node => instantiateNode(node.id, node.x, node.y, node.name)); + const instances = projectNodes.map(node => instantiateNode(node.id, node.x, node.y, nodeRegistry[node.type])); nodes.value = nodes.value.concat(instances); })(); }, []); @@ -237,14 +237,13 @@ const NodeEditor = ({ project }: NodeEditorProps) => { scale.value *= 1 + delta; }), []); - const addNode = useCallback(async (name: string, info: NodeInfo<any, any>) => { - const node = await pb.collection('nodes').create({ x: 100, y: 100, type: name, project: projectId, collapsed: false }); - alert(JSON.stringify(node)); + const addNode = useCallback(async (type: string, info: NodeInfo<any, any>) => { + const node = await pb.collection('nodes').create({ x: 100, y: 100, type, project: project.id, collapsed: false }); nodes.value = nodes.value.concat(instantiateNode(node.id, node.x, node.y, info)); }, []); return ( - <div class="__NodeEditor"> + <> <Toolbar title={project.name}> <ButtonMenu label="Add"> {Object.entries(nodeRegistry).map(([name, node]) => ( @@ -252,34 +251,36 @@ const NodeEditor = ({ project }: NodeEditorProps) => { ))} </ButtonMenu> </Toolbar> - <svg width="100vw" height="100vh" ref={svgRef} onMouseDown={onBgMouseDown} onWheel={onBgWheel}> - <pattern - id="bg-grid-major" - patternUnits="userSpaceOnUse" - x={offsetX} y={offsetY} - width={120 * scale.value} height={120 * scale.value} - > - <pattern id="bg-grid-minor" patternUnits="userSpaceOnUse" x="0" y="0" width="24" height="24"> - <circle cx="2" cy="2" r="1" fill="var(--surface)" /> - </pattern> - <g transform={`scale(${scale})`}> - <rect fill="url(#bg-grid-minor)" x="0" y="0" width="100%" height="100%" /> - <circle cx="2" cy="2" r="2" fill="var(--surface)" /> - </g> - </pattern> - <rect fill="url(#bg-grid-major)" x="0" y="0" width="100%" height="100%" /> - <g transform={`translate(${offsetX},${offsetY}) scale(${scale})`}> - {allLinks.value.map(({fromX, fromY, toX, toY}) => ( - <Link fromX={fromX} fromY={fromY} toX={toX} toY={toY} /> - ))} - <SocketHandlers.Provider value={socketHandlers}> - {nodes.value.map(node => ( - <node.component id={node.id} x={node.x} y={node.y} inputs={node.inputs} /> - ))} - </SocketHandlers.Provider> - </g> - </svg> - </div> + <main> + <svg class="__NodeEditor" width="100vw" height="100vh" ref={svgRef} onMouseDown={onBgMouseDown} onWheel={onBgWheel}> + <pattern + id="bg-grid-major" + patternUnits="userSpaceOnUse" + x={offsetX} y={offsetY} + width={120 * scale.value} height={120 * scale.value} + > + <pattern id="bg-grid-minor" patternUnits="userSpaceOnUse" x="0" y="0" width="24" height="24"> + <circle cx="2" cy="2" r="1" fill="color-mix(in srgb, var(--overlay) 25%, var(--surface))" /> + </pattern> + <g transform={`scale(${scale})`}> + <rect fill="url(#bg-grid-minor)" x="0" y="0" width="100%" height="100%" /> + <circle cx="2" cy="2" r="2" fill="color-mix(in srgb, var(--overlay) 25%, var(--surface))" /> + </g> + </pattern> + <rect fill="url(#bg-grid-major)" x="0" y="0" width="100%" height="100%" /> + <g transform={`translate(${offsetX},${offsetY}) scale(${scale})`}> + {allLinks.value.map(({fromX, fromY, toX, toY}) => ( + <Link fromX={fromX} fromY={fromY} toX={toX} toY={toY} /> + ))} + <SocketHandlers.Provider value={socketHandlers}> + {nodes.value.map(node => ( + <node.component id={node.id} x={node.x} y={node.y} inputs={node.inputs} /> + ))} + </SocketHandlers.Provider> + </g> + </svg> + </main> + </> ); }; diff --git a/src/index.tsx b/src/index.tsx index cd8c870..a67fd94 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,3 +1,4 @@ +import 'preact/debug'; import { render } from 'preact'; import { useMemo } from 'preact/hooks'; import { Router } from 'preact-router'; @@ -7,7 +8,7 @@ import { Home, SignUp, LogIn, ProjectsList, Editor } from './pages'; import './index.css'; export const App = () => { - const pb = useMemo(() => new PocketBase(`/`), []); + const pb = useMemo(() => new PocketBase('http://localhost:8090/'), []); return ( <Pb.Provider value={pb}> <Router> diff --git a/src/pages/Editor.tsx b/src/pages/Editor.tsx index c929595..c5b369f 100644 --- a/src/pages/Editor.tsx +++ b/src/pages/Editor.tsx @@ -20,11 +20,7 @@ const Editor = ({ user, project }: EditorProps) => { })(); }, []); - return ( - <> - {!!projectData.value && <NodeEditor project={projectData.value} />} - </> - ); + return projectData.value ? <NodeEditor project={projectData.value} /> : null; }; export default Editor; diff --git a/src/pages/SignUp.test.tsx b/src/pages/SignUp.test.tsx new file mode 100644 index 0000000..3029beb --- /dev/null +++ b/src/pages/SignUp.test.tsx @@ -0,0 +1,34 @@ +import { expect, test } from 'bun:test'; +import { render, fireEvent } from '@testing-library/preact'; +import { Pb } from '../context.ts'; +import { pb } from '../preload.ts'; +import SignUp from './SignUp.tsx'; + +test('has a link to log in', () => { + const { getAllByText, getByLabelText, getByText } = render( + <SignUp /> + ); + + expect(getAllByText(/log in/i)).not.toHaveLength(0); +}); + +test('can sign up', () => { + const username = 'foo'; + const email = 'foo@example.com'; + const password = '12345678'; + + const { getByText, getByLabelText } = render( + <Pb.Provider value={pb}> + <SignUp /> + </Pb.Provider> + ); + + fireEvent.change(getByLabelText(/username/i), {target: {value: username}}); + fireEvent.change(getByLabelText(/email/i), {target: {value: email}}); + fireEvent.change(getByLabelText(/password/i), {target: {value: password}}); + fireEvent.change(getByLabelText(/confirm password/i), {target: {value: password}}); + + fireEvent.click(getByText(/continue/i)); + + expect(pb.authStore.isValid()).toBeTrue(); +}); diff --git a/src/pages/SignUp.tsx b/src/pages/SignUp.tsx index e1cee3c..755c180 100644 --- a/src/pages/SignUp.tsx +++ b/src/pages/SignUp.tsx @@ -2,7 +2,14 @@ import { useContext, useCallback } from 'preact/hooks'; import { useSignal } from '@preact/signals'; import { route } from 'preact-router'; import { Pb } from '../context.ts'; -import { Header, Content, Form, FormLabel, TextInput, Button, ArrowButton } from '../components'; + +import Header from '../components/Header.tsx'; +import Content from '../components/Content.tsx'; +import Form from '../components/Form.tsx'; +import FormLabel from '../components/FormLabel.tsx'; +import TextInput from '../components/TextInput.tsx'; +import Button from '../components/Button.tsx'; +import ArrowButton from '../components/ArrowButton.tsx'; const SignUp = () => { const pb = useContext(Pb)!; diff --git a/src/test-preload.ts b/src/test-preload.ts new file mode 100644 index 0000000..3ec72a1 --- /dev/null +++ b/src/test-preload.ts @@ -0,0 +1,9 @@ +import { GlobalRegistrator } from '@happy-dom/global-registrator'; +import PocketBase from 'pocketbase'; + +GlobalRegistrator.register(); + +const proc = Bun.spawn(['./pocketbase', 'serve', '--http', '127.0.0.1:8090']); + +const pb = new PocketBase('http://localhost:8090/'); +export { pb }; |
