mirror of
https://github.com/morten-olsen/bob.git
synced 2026-02-08 01:46:29 +01:00
99 lines
2.0 KiB
TypeScript
99 lines
2.0 KiB
TypeScript
import {
|
|
useCallback,
|
|
useContext,
|
|
useEffect,
|
|
useMemo,
|
|
useRef,
|
|
useState,
|
|
} from 'react';
|
|
import { RunnerContext } from './context';
|
|
|
|
type BlockProps = {
|
|
worker: Worker;
|
|
action: string;
|
|
presenter?: React.FC<any>;
|
|
};
|
|
|
|
const id = (function* () {
|
|
let i = 0;
|
|
while (true) {
|
|
yield i++;
|
|
}
|
|
})();
|
|
|
|
const Block: React.FC<BlockProps> = ({
|
|
worker,
|
|
action,
|
|
presenter: Presenter,
|
|
}) => {
|
|
const currentId = useRef(id.next().value);
|
|
const { vars } = useContext(RunnerContext);
|
|
const [output, setOutput] = useState<unknown>();
|
|
const [error, setError] = useState<unknown>();
|
|
const [running, setRunning] = useState<boolean>();
|
|
const [duration, setDuration] = useState<number>();
|
|
|
|
const view = useMemo(() => {
|
|
if (error) {
|
|
return error.toString();
|
|
}
|
|
if (Presenter) {
|
|
return <Presenter output={output} />;
|
|
}
|
|
return JSON.stringify(output, null, 2);
|
|
}, [output, error, Presenter]);
|
|
|
|
const runBlock = useCallback(async () => {
|
|
setRunning(true);
|
|
setError(undefined);
|
|
setOutput(undefined);
|
|
|
|
try {
|
|
worker.postMessage({
|
|
type: 'run',
|
|
action,
|
|
vars,
|
|
id: currentId.current,
|
|
});
|
|
} catch (error) {
|
|
setError(error);
|
|
}
|
|
|
|
setRunning(false);
|
|
}, [worker, vars, action]);
|
|
|
|
useEffect(() => {
|
|
const listener = (event: MessageEvent) => {
|
|
const { type, payload, id, duration } = event.data;
|
|
if (id !== currentId.current) {
|
|
return;
|
|
}
|
|
setDuration(duration);
|
|
setRunning(false);
|
|
if (type === 'output') {
|
|
setOutput(payload);
|
|
}
|
|
if (type === 'error') {
|
|
setError(payload);
|
|
}
|
|
};
|
|
worker.addEventListener('message', listener);
|
|
return () => {
|
|
worker.removeEventListener('message', listener);
|
|
};
|
|
}, [worker]);
|
|
|
|
return (
|
|
<div>
|
|
<button onClick={runBlock} disabled={running}>
|
|
Run
|
|
</button>
|
|
{duration && <div>Duration: {duration.toFixed(2)}ms</div>}
|
|
{running && <div>Running...</div>}
|
|
{view}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export { Block };
|