Skip to content

Commit 6fef048

Browse files
committed
feat: load wasm
1 parent 8726677 commit 6fef048

File tree

3 files changed

+92
-10
lines changed

3 files changed

+92
-10
lines changed

src/App.tsx

Lines changed: 87 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,61 @@ import { ResizableHandle, ResizablePanelGroup } from "@/components/Resizable";
22
import { Editor } from "./Editor";
33
import { Logo } from "./components/Logo";
44
import { Preview } from "./Preview";
5+
import { useStore } from "@/store";
6+
import { useEffect, type FC } from "react";
7+
8+
// Glue code required to be able to run wasm compiled Go code.
9+
import "@/utils/wasm_exec.js";
10+
import { LoaderIcon } from "lucide-react";
11+
12+
type GoPreviewDef = (v: unknown) => Promise<string>;
13+
14+
// Extend the Window object to include the Go related code that is added from
15+
// wasm_exec.js and our loaded Go code.
16+
declare global {
17+
interface Window {
18+
// Loaded from wasm
19+
go_preview?: GoPreviewDef;
20+
Go: { new (): Go };
21+
}
22+
}
23+
24+
declare class Go {
25+
argv: string[];
26+
env: { [envKey: string]: string };
27+
exit: (code: number) => void;
28+
importObject: WebAssembly.Imports;
29+
exited: boolean;
30+
mem: DataView;
31+
run(instance: WebAssembly.Instance): Promise<void>;
32+
}
533

634
export const App = () => {
35+
const $isWasmLoaded = useStore((state) => state.isWasmLoaded);
36+
const $setIsWasmLoaded = useStore((state) => state.setIsWasmLoaded);
37+
38+
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
39+
useEffect(() => {
40+
const initWasm = async () => {
41+
try {
42+
const goWasm = new window.Go();
43+
const result = await WebAssembly.instantiateStreaming(
44+
fetch("build/preview.wasm"),
45+
goWasm.importObject,
46+
);
47+
48+
goWasm.run(result.instance);
49+
$setIsWasmLoaded(true);
50+
} catch (e) {
51+
console.error(e);
52+
}
53+
};
54+
55+
if (!$isWasmLoaded) {
56+
initWasm();
57+
}
58+
}, []);
59+
760
return (
861
<main className="flex h-dvh w-screen flex-col items-center bg-surface-primary">
962
{/* NAV BAR */}
@@ -43,16 +96,42 @@ export const App = () => {
4396
</div>
4497
</nav>
4598

46-
{/* CONTENT */}
47-
<ResizablePanelGroup direction={"horizontal"}>
48-
{/* EDITOR */}
49-
<Editor />
99+
<div className="relative h-full w-full">
100+
{!$isWasmLoaded ? (
101+
<div className="absolute top-0 left-0 z-30 flex h-full w-full items-center justify-center backdrop-blur-sm">
102+
<WasmLoading />
103+
</div>
104+
) : null}
105+
106+
<ResizablePanelGroup
107+
aria-hidden={!$isWasmLoaded}
108+
direction={"horizontal"}
109+
>
110+
{/* EDITOR */}
111+
<Editor />
50112

51-
<ResizableHandle className="bg-surface-quaternary" />
113+
<ResizableHandle className="bg-surface-quaternary" />
52114

53-
{/* PREVIEW */}
54-
<Preview />
55-
</ResizablePanelGroup>
115+
{/* PREVIEW */}
116+
<Preview />
117+
</ResizablePanelGroup>
118+
</div>
56119
</main>
57120
);
58121
};
122+
123+
const WasmLoading: FC = () => {
124+
return (
125+
<div className="flex w-full max-w-xs flex-col items-center justify-center gap-2 rounded-xl border border-[#38BDF8] bg-surface-tertiary p-4">
126+
<LoaderIcon className="animate-spin text-content-primary" />
127+
<div className="text-center">
128+
<p className="font-semibold text-content-primary text-xl">
129+
Loading Assets
130+
</p>
131+
<p className="text-content-secondary text-sm">
132+
Add some copy here to explain that this will only take a few moments
133+
</p>
134+
</div>
135+
</div>
136+
);
137+
};

src/Editor.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export const Editor: FC = () => {
125125
{/* CODE EDITOR */}
126126
<div className="relative h-full w-full">
127127
<Button
128-
className="absolute top-3 right-3 z-50"
128+
className="absolute top-3 right-3 z-10"
129129
variant="subtle"
130130
size="sm"
131131
onClick={onCopy}

src/store.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,17 @@ const defaultCode = `terraform {
1010

1111
type State = {
1212
code: string;
13+
isWasmLoaded: boolean;
1314
error?: string;
1415
setCode: (code: string) => void;
1516
setError: (error: string) => void;
17+
setIsWasmLoaded: (isWasmLoaded: boolean) => void;
1618
};
1719

1820
export const useStore = create<State>()((set) => ({
1921
code: defaultCode,
22+
isWasmLoaded: false,
2023
setCode: (code) => set((_) => ({ code })),
2124
setError: (error) => set((_) => ({ error })),
25+
setIsWasmLoaded: (isWasmLoaded) => set((_) => ({ isWasmLoaded })),
2226
}));
23-

0 commit comments

Comments
 (0)