Skip to content

Commit

Permalink
feat(playground): support state param in playground (#12168)
Browse files Browse the repository at this point in the history
* feat(playground): support state param in playground
  • Loading branch information
fiji-flo authored Nov 22, 2024
1 parent f1417ae commit 4390f8c
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 18 deletions.
58 changes: 40 additions & 18 deletions client/src/playground/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ import prettierPluginHTML from "prettier/plugins/html";
import { Button } from "../ui/atoms/button";
import Editor, { EditorHandle } from "./editor";
import { SidePlacement } from "../ui/organisms/placement";
import { compressAndBase64Encode, EditorContent, SESSION_KEY } from "./utils";
import {
compressAndBase64Encode,
decompressFromBase64,
EditorContent,
SESSION_KEY,
} from "./utils";

import "./index.scss";
import { PLAYGROUND_BASE_HOST } from "../env";
Expand Down Expand Up @@ -68,6 +73,7 @@ export default function Playground() {
const gleanClick = useGleanClick();
let [searchParams, setSearchParams] = useSearchParams();
const gistId = searchParams.get("id");
const stateParam = searchParams.get("state");
let [dialogState, setDialogState] = useState(DialogState.none);
let [shared, setShared] = useState(false);
let [shareUrl, setShareUrl] = useState<URL | null>(null);
Expand All @@ -80,7 +86,9 @@ export default function Playground() {
null
);
let { data: initialCode } = useSWRImmutable<EditorContent>(
!shared && gistId ? `/api/v1/play/${encodeURIComponent(gistId)}` : null,
!stateParam && !shared && gistId
? `/api/v1/play/${encodeURIComponent(gistId)}`
: null,
async (url) => {
const response = await fetch(url);

Expand All @@ -98,7 +106,11 @@ export default function Playground() {
},
{
fallbackData:
(!gistId && state === State.initial && load(SESSION_KEY)) || undefined,
(!stateParam &&
!gistId &&
state === State.initial &&
load(SESSION_KEY)) ||
undefined,
}
);
const htmlRef = useRef<EditorHandle | null>(null);
Expand Down Expand Up @@ -172,23 +184,33 @@ export default function Playground() {
};

useEffect(() => {
if (state === State.initial || state === State.remote) {
if (initialCode && Object.values(initialCode).some(Boolean)) {
setEditorContent(initialCode);
if (!gistId) {
// don't auto run shared code
updateWithCode(initialCode);
(async () => {
if (state === State.initial || state === State.remote) {
if (initialCode && Object.values(initialCode).some(Boolean)) {
setEditorContent(initialCode);
if (!gistId) {
// don't auto run shared code
updateWithCode(initialCode);
}
} else if (stateParam) {
try {
let { state } = await decompressFromBase64(stateParam);
let code = JSON.parse(state || "{}") as EditorContent;
setEditorContent(code);
} catch (e) {
console.error(e);
}
} else {
setEditorContent({
html: HTML_DEFAULT,
css: CSS_DEFAULT,
js: JS_DEFAULT,
});
}
} else {
setEditorContent({
html: HTML_DEFAULT,
css: CSS_DEFAULT,
js: JS_DEFAULT,
});
setState(State.ready);
}
setState(State.ready);
}
}, [initialCode, state, gistId]);
})();
}, [initialCode, state, gistId, stateParam]);

useEffect(() => {
window.addEventListener("message", messageListener);
Expand Down
29 changes: 29 additions & 0 deletions client/src/playground/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,32 @@ export async function compressAndBase64Encode(inputString: string) {

return { state, hash };
}

function base64ToBytes(base64: string): ArrayBuffer {
const binString = atob(base64);
const len = binString.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binString.charCodeAt(i);
}
return bytes.buffer;
}

export async function decompressFromBase64(base64String: string) {
if (!base64String) {
return { state: null, hash: null };
}
const bytes = base64ToBytes(base64String);
const hashBuffer = await window.crypto.subtle.digest("SHA-256", bytes);
const hashArray = Array.from(new Uint8Array(hashBuffer)).slice(0, 20);
const hash = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");

const decompressionStream = new DecompressionStream("deflate-raw");

const decompressedStream = new Response(
new Blob([bytes]).stream().pipeThrough(decompressionStream)
).arrayBuffer();

const state = new TextDecoder().decode(await decompressedStream);
return { state, hash };
}

0 comments on commit 4390f8c

Please sign in to comment.